import numpy as np
a = np.random.randomint(-5,5,(5,))
b = np.random.randomint(-5,5,(5,))
a+b -> element-wise addition
Numpy를 사용하여 좋은 점
__add__ , __sub__ ,__mul__ 모두 원소별 연산이다
심지어 True False도 element-wise로 가능하다
a > b ---> [False, False, True, False, True]
대신 조심할 것은 비교하는 두 변수가 Type이 맞아야한다.
Array의 원하는 부분만 남기거나 제거하는 기술을 마스킹이라고 한다.
이 기능은 maxpooling을 딥러닝에서 할때 자주 쓰이게 된다.
import numpy as np
a = np.arange(5)
mask = np.array([0, 1, 0, 1, 0])
a -> [0 1 2 3 4]
a*b -> [0 1 0 3 0]
서로 다른 shape의 array를 서로 연산할 수 있게 해준다. 원래라면 연산이 불가능한 상황에서 shape을 자동으로 맞춰줌으로써 연산을 가능하게 하는 것이다. 연산이 안되는 것을 가능하도록 만들어줌으로써 매우 편리하지만 의도치 않은 버그를 만들수 있다.
import numpy as np
A = np.arange(9).reshape(3,3)
B = 10 * np.arange(3).reshape((-1,1))
C = A + B
print("A: {}/{}\n{}".format(A.ndim, A.shape, A))
A: 2/(3,3)
[[0 1 2]
[3 4 5]
[6 7 8]]
print("B: {}/{}\n{}".format(B.ndim, B.shape, B))
B: 2/(3,1)
[[0]
[10]
[20]]
print("A + B: {}/{}\n".format(A.ndim, C.shape, C))
A + B: 2/(3,3)
[[0 1 2]
[13 14 15]
[26 27 28]]
column이 a에 맞게 copy되어 shape을 맞춘 후 연산이 된다.
(3,1) + (1,3)은 (3,1)의 column이 (1,3)에 맞춰지고 (1,3)의 row가 (3,1)에 맞춰진다. 꼭 하나만 broadcasting 되는 것이 아니다.
import numpy as np
A = np.arange(18).reshape((2,3,3))
B = 10 * np.arange(6).reshape((2,1,3))
C = A + B
A
[[0 1 2]
[3 4 5]
[6 7 8]]
[[9 10 11]
[12 13 14]
[15 16 17]]
B
[[0 10 20]] [[0 10 20] [0 10 20] [0 10 20]]
->
[[30 40 50]] [[30 40 50] [30 40 50] [30 40 50]]
import numpy as np
a = np.array(3) shape:()
u = np.arange(5) shape:(5,)
a*u : [0 3 6 9 12]
작은 차원이 큰 차원에 맞춰진다. 또한 오른쪽부터 차원값이 맞춰진다.
a: 3 -> [3 3 3 3]
b: [1 2 3 4]
a + b: [4 5 6 7]
a > b: [True True False False]
(3,2)와 (2,)을 연산하기 위해서는 1차원 벡터가 2차원 벡터의 안쪽 차원/ 오른쪽 차원과 맞아야만 연산이 가능하다. 따라서 (2,)이 row를 따라 3번 복사되어 (3,2)가 만들어진다. 따라서 (3,)과는 연산이 이루어지지 않는다.
(2,3,4)는 안쪽 차원인 (3,4)와 맞는 모양에만 broadcasting이 된다.
ex) (3,4), (4,)
Tip:
텐서를 오른쪽 정렬하게 되면 실수를 줄일 수 있게 된다