https://numpy.org/doc/stable/user/basics.broadcasting.html?highlight=broadcasting
위의 NumPy doc에 따르면 브로드캐스팅(Broadcasting)은 산수연산(Arithmetic operations)을 수행할 때, 서로 다른 shape을 가지는 arrays를 어떻게 다룰지(treats)를 묘사하는 단어라고 한다. 특정 제약사항을 조건으로, shape이 다른 두 array가 호환되는 shape을 가지도록 작은 array가 큰 array에 'broadcast'한다. 그리고 Python 대신 C로 looping이 일어날 수 있도록 해준다고 한다.
우선 이전 글에서 봐왔던 것처럼 NumPy 연산은 한 쌍의 array에 대해서, element-by-element(Element-wise)로 이뤄진다. 따라서 가장 단순한 경우, 두 arrays는 같은 shape이어야 한다. 아래 코드처럼 a와 b array모두 (2, 5)의 shape을 가진다면 element-by-element로 연산이 이루어진다.
a = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
b = np.array([[11, 12, 13, 14, 15], [16, 17, 18, 19, 20]])
print(a.shape, b.shape) # (2, 5) (2, 5)
print(a + b)
#[[12 14 16 18 20]
# [22 24 26 28 30]]
array의 shape이 특정 제약사항을 만족시키면, NumPy의 Broadcasting rule이 두 arrays는 같은 shape이어야 한다는 제약을 relax해준다. 아래는 array와 하나의 scalar value 사이의 연산에서 일어나는 Broadcating이다.
a = np.arange(10)
b = 4
print(a, a + b, sep='\n')
#[0 1 2 3 4 5 6 7 8 9]
#[ 4 5 6 7 8 9 10 11 12 13]
위 코드를 보면 scalar 값 b가 array a와 같은 shape을 같는 array로 stratch된 것과, 그 요소가 원래 scalar 값 4로 채워져 있음을 확인할 수 있다. 다만, stratch 된다는 비유는 단지 개념이 그렇다는 것이고 실제로는 NumPy가 memory와 연산이 가능한한 효율적으로 처리되도록 stratch한 copy를 진짜로 만들지는 않는다.
두 arrays에 대해 연산을 할 때, NumPy는 이들의 shapes를 element-wise로 비교한다. 비교하는 순서는 trailing dimensions부터 왼쪽방향으로 한다. 다시말해서, shape의 가장 우측 element부터 좌측으로 element-wise로 비교한다(같은 axes or dimensions끼리 비교하게 된다). 그리고 비교하는 두 dimensions는 다음과 같을 때 compatible이다.
1. 그 값이 같을 때, 혹은
2. 그 중 하나의 값이 1일 때
만약 이 조건들이 만족되지 않으면, 두 arrays가 서로 호환되지 않는 shapes를 가진다는 것을 나타내는 ValueError: operands could not be broadcast together exception 가 throw된다.
Broadcasting이 되는 예.
A (4d array): 5 x 1 x 4 x 1
B (3d array): _ x 6 x 4 x 7 # 차원을 맞춰서 보기편하게 하기 위해 _표기
result (4d): 5 x 6 x 4 x 7
먼저 rules대로, 가장 우측부터 element-wise로 비교한다.
dim A B result
1. 1 7 7 -> 위의 조건 중 조건 2에 해당하므로 compatible이다. 이 경우, dimension size가 작은 쪽(1)이 큰 쪽(7)과 match되도록 stratch된다.
2. 4 4 4 -> 위의 조건 중 조건 1에 해당하므로 compatible이다. 이 경우, 그대로 element-wise로 연산이 가능하므로 별도의 처리가 필요없다.
3. 1 6 6 -> 1dim과 마찬가지.
4. 5 _ 5 -> 새로운 차원을 만들어 match 되도록한다. stratch or copy
만약 다음과 같은 두 arrays라면 ValueError가 throw된다.
Broadcasting이 되지 않는 예.
A (3d array): 9 x 5 x 3
B (2d array): _ x 4 x 1
dim A B result
1. 3 1 3 -> 위의 조건 중 조건 2에 해당하므로 compatible이다. 이 경우, dimension size가 작은 쪽(1)이 큰 쪽(3)과 match되도록 stratch된다.
2. 5 4 x -> 위의 조건 중 어느 조건에도 해당하지 않으므로 incompatible이다. ValueError가 throw된다.
3. 9 _ 6
np.newaxis를 사용하여 새 축을 만들어 compatible shape으로 만들 수있고, Vector Quantization과 같이 실용적인 사용법도 있다. 자세한 것은 글의 맨 위 링크로 가서 살펴보기 바란다.