[NumPy] 03. ndarray 기본 연산과 broadcasting
Updated:
import numpy as np
3.1. ndarray 기본 연산
+, -, *, /, //, %, ** python 기본 연산자를 numpy의 ndarray에 적용할 수 있는데 모두 원소끼리 연산이 이루어지는 형태이다.
즉, 일반적으로 알고있는 행렬 연산처럼 생각을 하면 안된다.
a = np.arange(12).reshape((3,4))
b = np.arange(11,23).reshape((3,4))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
print("a-b:\n",a-b)
print("a*b:\n",a*b)
print("a/b:\n",a/b)
a:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
b:
[[11 12 13 14]
[15 16 17 18]
[19 20 21 22]]
a+b:
[[11 13 15 17]
[19 21 23 25]
[27 29 31 33]]
a-b:
[[-11 -11 -11 -11]
[-11 -11 -11 -11]
[-11 -11 -11 -11]]
a*b:
[[ 0 12 26 42]
[ 60 80 102 126]
[152 180 210 242]]
a/b:
[[0. 0.08333333 0.15384615 0.21428571]
[0.26666667 0.3125 0.35294118 0.38888889]
[0.42105263 0.45 0.47619048 0.5 ]]
3.2 broadcasting
numpy는 ndarray의 shape이 일치하지 않을때도 연산을 지원한다.
서로다른 shape을 가진 ndarray를 맞추는 과정을 broadcasting이라고 하며 다음과 같이 이루어진다.
Case1. dimension이 일치할 때
shape이 작은 쪽을 큰 쪽에 맞춰 확장한다.
- (3,3) + (1,3) : (1,3)을 (3,3)으로 확장시켜 + 연산을 수행한다.
- (3,3) + (3,1) : (3,1)을 (3,1)으로 확장시켜 + 연산을 수행한다.
- (2,3,1) + (1,3,1): (1,3,1)을 (2,3,1)로 확장시켜 + 연산을 수행한다.
- (2,1,2) + (2,3,1): (2,1,2)을 (2,3,2)로 (2,3,1)을 (2,3,2)로 확장시켜 + 연산을 수행한다.
a = np.arange(9).reshape((3,3))
b = np.arange(3).reshape((1,3))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
a:
[[0 1 2]
[3 4 5]
[6 7 8]]
b:
[[0 1 2]]
a+b:
[[ 0 2 4]
[ 3 5 7]
[ 6 8 10]]
a = np.arange(9).reshape((3,3))
b = np.arange(3).reshape((3,1))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
a:
[[0 1 2]
[3 4 5]
[6 7 8]]
b:
[[0]
[1]
[2]]
a+b:
[[ 0 1 2]
[ 4 5 6]
[ 8 9 10]]
a = np.arange(2*3*2).reshape((2,3,2))
b = np.arange(1*3*2).reshape((1,3,2))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
a:
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]]
b:
[[[0 1]
[2 3]
[4 5]]]
a+b:
[[[ 0 2]
[ 4 6]
[ 8 10]]
[[ 6 8]
[10 12]
[14 16]]]
a = np.arange(2*3*2).reshape((2,3,2))
b = np.arange(2*3*1).reshape((2,3,1))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
a:
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]]
b:
[[[0]
[1]
[2]]
[[3]
[4]
[5]]]
a+b:
[[[ 0 1]
[ 3 4]
[ 6 7]]
[[ 9 10]
[12 13]
[15 16]]]
a = np.arange(2*1*2).reshape((2,1,2))
b = np.arange(2*3*1).reshape((2,3,1))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
a:
[[[0 1]]
[[2 3]]]
b:
[[[0]
[1]
[2]]
[[3]
[4]
[5]]]
a+b:
[[[0 1]
[1 2]
[2 3]]
[[5 6]
[6 7]
[7 8]]]
Case2. dimension이 다를 때
dimension이 작은 쪽을 큰 쪽에 맞춰서 dimension을 확장한다.
- (2,3) + (3,) : (3,)을 (1,3)으로 만든다음 (2,3)으로 확장시켜 + 연산을 수행한다.
- (2,3,2) + (3,2) : (3,2)를 (1,3,2)로 만든다음 (2,3,2)로 확장시켜 + 연산을 수행한다.
- (2,3,2) + (2,): (2,)을 (2,3,2)순서로 확장한다음 + 연산을 수행한다.
즉 차원이 작은 쪽의 shape이 큰 쪽의 오른쪽 shape과 일치해야함을 알 수 있다.
a = np.arange(2*3).reshape((2,3))
b = np.arange(3)
print("a:\n",a)
print("b:",b)
print("a+b:\n",a+b)
a:
[[0 1 2]
[3 4 5]]
b: [0 1 2]
a+b:
[[0 2 4]
[3 5 7]]
a = np.arange(2*3*2).reshape((2,3,2))
b = np.arange(3*2).reshape((3,2))
print("a:\n",a)
print("b:\n",b)
print("a+b:\n",a+b)
a:
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]]
b:
[[0 1]
[2 3]
[4 5]]
a+b:
[[[ 0 2]
[ 4 6]
[ 8 10]]
[[ 6 8]
[10 12]
[14 16]]]
a = np.arange(2*3*2).reshape((2,3,2))
b = np.arange(2)
print("a:\n",a)
print("b:",b)
print("a+b:\n",a+b)
a:
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]]
b: [0 1]
a+b:
[[[ 0 2]
[ 2 4]
[ 4 6]]
[[ 6 8]
[ 8 10]
[10 12]]]
Leave a comment