지난번 포스팅에서는 같은 차원 크기의 배열 간 산술연산인 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
# : the scalar are broadcasted along the same dimensions of ndarray

 

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
# : the scalar are broadcasted along the same dimensions of DataFrame

 

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
# Arithmetic operations between 2-D array and 1-D array
# that is the same length as the row-length

 

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
# ValueError: operands could not be broadcast together with shapes (4,3) (4,)

 

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
# 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 를 참고하세요. 

 

많은 도움 되었기를 바랍니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾹 눌러주세요. ^^

 

728x90
반응형
Posted by Rfriend
,