TL;DR — broadcasting은 작은 배열을 실제 복사하지 않고 큰 배열의 축에 맞춰 반복해 읽는 배열 라이브러리 규칙입니다. 끝 축부터 비교해 같거나 한쪽이 1이면 통과합니다.
왜 배우나요? — 모양이 다른 배열을
+로 더하는 numpy·PyTorch 코드를 이해하고, 에러 없이 잘못된 축으로 확장되는 조용한 버그를 막기 위해 배웁니다.AI 어디에 쓰이나요? — 완전연결층의 편향 더하기 와 특성별 평균 빼기에서 반복해서 등장합니다.
모양이 달라도 더해지는 이유
numpy나 PyTorch 코드를 읽다 보면 처음엔 이상해 보이는 장면을 만납니다. 100명의 학생을 행, 국어·영어·수학 3과목을 열로 둔 성적표에 과목별 보정 점수 3개를 그냥 더합니다. 행×열 표기와 축의 뜻이 이제 일치합니다.
정확히 말해 broadcasting은 실제 복사 명령이 아니라 어느 값을 반복해서 읽을지 정하는 가상 확장 규칙입니다. 도장 하나가 각 행의 같은 열에 대응한다고 생각하면 됩니다.
fixture 와 을 쓰면 결과는 입니다. 그림·공식·코드가 모두 이 한 fixture를 사용합니다.
작은 벡터가 행마다 도장처럼 복제됩니다
위 그림의 버튼을 눌러 세 상태를 순서대로 넘겨 보세요.
[벡터]에서는 길이 3짜리 이 행렬 와 나란히 놓입니다. 이때는 끝 축 과 이 같은지만 확인하고, 다음 상태의 확장 결과는 아직 보이지 않습니다.
[가상 확장]에서는 에서 아래 두 행 자리로 향하는 화살표를 따라가세요. 같은 한 줄을 두 행에서 반복해 읽으며, 점선 행은 실제 메모리 복사가 아닌 가상 확장 자리입니다.
[결과]에서는 각 칸이 X 성분 + v 성분 = 결과로 남아 있습니다. 예를 들어 , 처럼 같은 첫 번째 성분이 두 행의 첫 열에 더해져 이 완성됩니다.
한 줄 정리 — 작은 배열이 큰 배열의 각 행에 똑같이 복제되어 자리끼리 더해집니다.
: 입력 행렬
: 각 행에 더해지는 벡터
결과의 행 열 = 의 그 자리 값에 의 번째 값을 더한 것
행이 몇 번째든 같은 를 더함
수학에는 없는, 코드만의 규칙
여기서 꼭 짚고 넘어갈 것이 있습니다. 수학 교과서의 선형대수에는 broadcasting이라는 개념이 아예 없습니다. 고전적인 정의에서 행렬과 벡터의 덧셈은 모양이 완전히 같을 때만 정의됩니다 — 행렬과 길이 3짜리 벡터의 덧셈은 수학적으로는 '정의되지 않은 연산'입니다. 굳이 하려면 사람이 손으로 를 두 번 쌓아 이라는 어엿한 행렬을 명시적으로 만든 다음에야 더할 수 있습니다.
그러니 broadcasting은 수학에서 물려받은 규칙이 아니라, numpy 같은 배열 언어가 손수 도입한 코드 편의 문법입니다. '모양이 조금 달라도 자동으로 맞춰 줄 테니 반복 코드를 쓰지 말라'는, 프로그래머를 위한 약속인 것이죠. 그래서 이 규칙은 수학책이 아니라 라이브러리 문서에서 배우게 됩니다.
규칙은 하나 — 끝 축부터 맞춰 보기
대신 아무 모양이나 맞춰 주지는 않습니다. 규칙은 딱 하나만 기억하면 됩니다: 뒤쪽(오른쪽) 차원부터 하나씩 맞춰 보고, 각 자리가 서로 '같거나' 한쪽이 '1'이면 통과. 과 은 끝자리가 으로 같으니 통과이고, 크기가 1이거나 아예 없는 앞쪽 축은 상대에 맞춰 늘어납니다. 반대로 과 는 끝자리가 라 그 자리에서 바로 막혀 에러가 납니다. 아래 코드로 두 경우를 다 확인해 봅시다.
X = ([[1, 2, 3], [4, 5, 6]]) # shape (2, 3)
v = ([10, 20, 30]) # shape (3,)
(X, v) # 뒤쪽 차원 3 == 3 -> 호환
(X + v) # v가 두 행에 똑같이 더해짐(도장 두 번)
w = ([10, 20, 30, 40]) # shape (4,) — 끝자리 4 != 3
:
(X + w) # shape 불일치 -> 실패
e:
("ValueError:", e)출력 (에러 트레이스백)
(2, 3) (3,) [[11 22 33] [14 25 36]] ValueError: operands could not be broadcast together with shapes (2,3) (4,)
X.shape와 v.shape를 찍어 보면 (2, 3)과 (3,)입니다 — 끝자리가 으로 같으니 규칙을 통과합니다. 그래서 X + v는 위 공식 그대로, 이 두 행에 똑같이 더해진 [[11 22 33] [14 25 36]]을 냅니다(그림의 [result]와 같은 값). 반면 w는 길이가 4라 끝자리가 , 규칙에서 막혀 ValueError가 나고 numpy가 친절하게 어긋난 두 모양 (2,3)과 (4,)를 그대로 알려 줍니다. 실전에서 이 에러 메시지를 만나면 '아, 끝 축이 안 맞았구나'로 바로 읽으면 됩니다.
한 줄 정리 — 끝 축부터 맞춰 보아 같거나 한쪽이 1이면 통과, 아니면 shape 에러입니다.
딥러닝 코드에 숨은 broadcasting
대표적인 사용 장면은 편향(bias) 더하기입니다. 가 '샘플 수 × 출력 특성 수'이고 가 '출력 특성 수' 벡터이면, broadcasting이 를 모든 샘플 행에 같은 방식으로 대응시킵니다. 특성별 평균을 빼는 normalization에서도 같은 shape 규칙을 씁니다.
다만 축을 잘못 두면 에러 없이 엉뚱한 방향으로 확장될 수 있습니다. 그래서 shape뿐 아니라 '어느 축이 샘플이고 어느 축이 특성인가'를 함께 확인해야 합니다.
batch = ([[1., 2.], [3., 4.], [5., 6.]]) # (3, 2): 샘플 3개, 특성 2개
b = ([0.5, -1.0]) # (2,) bias 벡터
((batch + b).) # (3, 2) 유지
(batch + b) # 모든 샘플 행에 같은 bias
mean = batch(=0) # (2,) 특성별 평균
(batch - mean) # 중앙 정렬(정규화 1단계)(3, 2) [[1.5 1. ] [3.5 3. ] [5.5 5. ]] [[-2. -2.] [ 0. 0.] [ 2. 2.]]
batch는 샘플 3개·특성 2개인 행렬, b는 특성마다 하나씩인 편향입니다. 끝자리 가 맞아 batch + b는 모양 를 그대로 유지한 채 세 샘플 행에 같은 을 얹습니다 — 이것이 에서 매번 일어나는 일입니다. 이어지는 batch - mean은 특성별 평균 를 각 행에서 빼 데이터를 가운데로 모은 것으로, 정규화의 첫 단계이자 또 하나의 broadcasting입니다. 두 연산 모두 반복문 한 줄 없이 표 전체를 한 방에 처리했습니다.