본문 바로가기
Python/Build setting

[Numpy]넘파이 연산(Broadcasting)

by 소소한 혜밍씨 2022. 8. 30.

Broadcasting은 numpy가 산술 연산을 수행 할 때 다른 모양의 배열로 작업 할 수있게 해주는 메커니즘이다.

 

더 작은 배열과 더 큰 배열이 있을 때

 

즉, 작은 배열을 여러 번 사용하여 더 큰 배열에서 연산을 수행하고자 할 때 사용한다.

 

 

 

 

그러나, broadcasting을 인지하지 못한 경우에도 사용될 경우 연산에 큰 오류를 범할 수 있다.

 

연산 자체는 가능하지만 원하는 값을 도출해낸 것이 아니고

 

원하는 값을 명확하게 알지 못할 때는 오류값임을 인지하기 어렵기 때문이다.

 

 

 

 

Broadcasting은 어떤 원리도 작동이 되는지 아래의 코드로 확인해보자.

 

먼저, 행렬의 각 행에 상수 벡터를 추가하려 한다고 가정해보자.

 

x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
y = np.array([1,0,2])

print(x, x.shape)
print(y, y.shape)



# 출력
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]] (4, 3)
[1 0 2] (3,)

 

z = x + y

print(z, z.shape)



# 출력
[[ 2  2  5]
 [ 5  5  8]
 [ 8  8 11]
 [11 11 14]] (4, 3)

 

위 결과를 보면, z = x + y 는 broadcasting으로 인해 x가 shape (4, 3)이고 y가 shape (3)인데도 연산 결과가 출력된다.

 

왜냐하면 y가 실제로 shape (4, 3)인 것처럼 작동했기 때문이다.

 

각 행은 y의 사본 즉, [1, 0, 2]가 모든 행에 복사되어 shape (4, 3)을 만들어 낸 것이고 합계는 요소별로 수행된 것이다.

 

Shape의 변화를 살펴보면

 

  • (4, 3) + (3,)       :     x + y를 출력하고자 함(배열의 랭크가 같지 않음)
  • (4, 3) + (1, 3)    :     x와 y의 모양이 같은 길이가 될 때까지 배열의 낮은 랭크쪽에 1을 붙임 ex) (1, 3), (1, 1, 3), ~
  • (4, 3) + (4, 3)    :     shape이 1인 곳은 복사가 되어 연산이 가능해짐
  • (4, 3)                :     연산 결과 출력

 

 

 

그렇다고 broadcasting이 항상 수행되는 것은 아니다.

 

x = np.array([1,2,3]).reshape(1,3)
y = np.array([4,5]).reshape(1,2)

print(x, x.shape)
print(y, y.shape)



# 출력
[[1 2 3]] (1, 3)
[[4 5]] (1, 2)

 

# broadcasting 조건에 맞지 않음
print(x + y)



# 출력
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_2482151/2191624560.py in <module>
      1 # broadcasting 조건에 맞지 않음
----> 2 print(x + y)

ValueError: operands could not be broadcast together with shapes (1,3) (1,2)

 

위의 경우는 broadcasting 조건에 맞지 않으므로 broadcasting이 발생하지 않고 에러가 발생한다.

 

그렇다면 어떤 부분이 broadcasting 조건에 맞지 않은 것일까

 

 

 

 

x와 y가 출력된 결과는 다음과 같다.

 

[[1 2 3]] (1, 3)
[[4 5]] (1, 2)

 

1행 3열, 1행 2열 중 shape이 동일하지 않은 부분 은 '열'

 

두 array의 열 중 하나의 값은 1이어야 다른 값을 복사하게 되는데

 

이 경우는 두 열의 값 모두 1이 아니므로 복사가 진행되지 않아 에러가 발생하게 되었다.

 

 

 

 

Broadcasting 발생할 수 있는 조건에 맞추어 다시 결과를 출력해보자.

 

# y의 shape 변경
y = y.swapaxes(0, 1)

print(y, y.shape)



# 출력
[[4]
 [5]] (2, 1)

 

# broadcasting 발생
print(x + y)



# 출력
[[5 6 7]
 [6 7 8]]

 

 

 

댓글