지난번 포스팅에서는 같은 차원 크기의 배열 간 산술연산인 Vectorization 에 대해서 소개하였습니다.
이번 포스팅에서는 차원의 크기가 서로 다른 배열 간 산술연산 시의 Broadcasting 에 대해서 알아보겠습니다. (Braodcasting도 Vectorization 의 일부분 입니다. 사실, 지난번 vectorization에서 Scalar와의 연산 시 element-wise 연산 시 이미 Broadcasting을 맛보았었습니다. ㅎㅎ)
Broadcasting이 서로 다른 모양, 크기의 배열 간 연산이다 보니 좀 헷갈릴 수도 있는데요, 알아두면 매우 편리하고 또 빠른 연산으로 유용합니다. 이해하기 쉽도록 Broadcasting 되는 모습을 이미지(점선 & 화살표)로 표현을 병행했습니다.
배열의 차원(Dimension)과 축(Axis) 별로 4가지 유형의 Broadcasting 을 차례대로 소개해보겠습니다.
1) Broadcasting over axis 1 with a Scalar
2) Broadcasting over axis 0 with a 1-D array
3) Broadcasting over axis 1 with a 2-D array
4) Broadcasting over axis 0 with a 3-D array
순서대로 예를 들어 살펴보겠습니다.
1) Broadcasting over axis 1 with a Scalar |
먼저, 간단한 Scalar 부터 시작해보시지요.
# (1-1) Arithmetic operations between array and scalars
In [1]: import numpy as np In [2]: a_ar = np.array([1., 2., 3., 4.]) In [3]: a_ar.shape Out[3]: (4,) In [4]: a_ar + 1 Out[4]: array([ 2., 3., 4., 5.])
|
배열 뿐만 아니라 Pandas의 DataFrame 도 Scalar 산술 연산 시에 Broadcasting 이 적용됩니다. 간단한 예를 들어볼겠요.
# (1-2) Arithmetic operations between DataFrame and scalars
In [5]: import pandas as pd In [6]: a_df = pd.DataFrame({'x1': [1, 2, 3, 4], 'x2': [5, 6, 7, 8]}) In [7]: a_df Out[7]: x1 x2 0 1 5 1 2 6 2 3 7 3 4 8 In [8]: a_df + 1 Out[8]: x1 x2 0 2 6 1 3 7 2 4 8 3 5 9
|
자, 이제 차원을 하나 늘려볼까요?
2) Broadcasting over axis 0 with a 1-D array |
세로 방향(over axis 0)으로 row를 복사해가면서 Braodcasting을 하는 예입니다.
## (2) Broadcasting using a 1-D array
In [9]: b = np.arange(12).reshape((4, 3)) In [10]: b.shape Out[10]: (4, 3) In [11]: b Out[11]: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]]) In [12]: c = np.array([0, 1, 2]) In [13]: c.shape Out[13]: (3,) In [14]: c Out[14]: array([0, 1, 2])
# adding c (1-D array) row-wise to b (2-D array) In [15]: b + c Out[15]: array([[ 0, 2, 4], [ 3, 5, 7], [ 6, 8, 10], [ 9, 11, 13]])
|
배열의 차원 크기, 모양이 다르다고 해서 Broadcasting 이 아무때나 되는 것은 아닙니다. Broadcasting을 시키려면 기준 축에 있는 원소의 크기(개수)가 서로 같아야지 짝을 맞추어서 확산(broadcasting, propagating)을 할 수 있습니다. 말로 설명하기가 좀 어렵습니다. ^^; 아래에 Broadcasting이 안되고 ValueError가 난 사례를 예로 들어보겠습니다.
ValueError: operands could not be broadcast together with shapes (4,3) (4,) |
## Shape mismatches
In [11]: b Out[11]: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]])
In [16]: d = np.array([0, 1, 2, 3]) In [17]: b + d Traceback (most recent call last): File "<ipython-input-17-8c4237e65878>", line 1, in <module> b + d ValueError: operands could not be broadcast together with shapes (4,3) (4,)
|
3) Broadcasting over axis 1 with a 2-D array |
가로 방향(over axis 1)으로 column을 복사해가면서 broadcasting하는 예입니다.
## (3) Broadcasting over axis 1 of a 2-D array
In [18]: b = np.arange(12).reshape((4, 3)) In [19]: b.shape Out[19]: (4, 3) In [20]: b Out[20]: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]]) In [21]: e = np.array([0, 1, 2, 3]).reshape(4, 1) In [22]: e.shape Out[22]: (4, 1) In [23]: e Out[23]: array([[0], [1], [2], [3]])
# adding e (2-D array) column-wise to b (2-D array) In [24]: b + e Out[24]: array([[ 0, 1, 2], [ 4, 5, 6], [ 8, 9, 10], [12, 13, 14]])
|
자, 이제 3차원으로 넘어가보겠습니다. 머리가 슬슬 아파오지요? ^^;
4차원부터는 그림으로 예시를 들기가 애매해서 3차원까지만 할께요.
4) Broadcasting over axis 0 with a 3-D array |
3-D 배열에서 앞뒤 방향(over axis 0) 으로 2-D 배열을 복사해가면서 Broadcasting 하는 예제입니다.
## (4) Broadcasting over axis 0 of a 3-D array
In [25]: f = np.arange(24).reshape((2,4,3)) In [26]: f Out[26]: array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]], [[12, 13, 14], [15, 16, 17], [18, 19, 20], [21, 22, 23]]])
# 2-D array In [27]: g = np.ones((4,3)) In [28]: g Out[28]: array([[ 1., 1., 1.], [ 1., 1., 1.], [ 1., 1., 1.], [ 1., 1., 1.]])
# Broadcasting over axis 0 of a 3-D array : 3-D array + 2-D array In [29]: f + g Out[29]: array([[[ 1., 2., 3.], [ 4., 5., 6.], [ 7., 8., 9.], [ 10., 11., 12.]], [[ 13., 14., 15.], [ 16., 17., 18.], [ 19., 20., 21.], [ 22., 23., 24.]]])
|
* 서로 다른 차원을 가진 두 배열의 산술연산 시 repeat(n, axis) 메소드를 통해 차원을 맞추어주는 방법은 https://rfriend.tistory.com/549 를 참고하세요.
많은 도움 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾹 눌러주세요. ^^