이번 포스트에서는 기본적인 넘파이 연산들에 대해 다뤄볼 것이다.
a = np.array([20, 30, 40, 50])
b = np.arange(4)
c = a - b
# 1 Operation
print(b)
>>>
array([0, 1, 2, 3])
# 2 Operation
print(c)
>>>
array([20, 29, 38, 47])
# 3 Operation
print(b**2)
>>>
array([0, 1, 4, 9])
# 4 Operation
print(10 * np.sin(a))
>>>
array([ 9.12945251, -9.88031624, 7.4511316 , -2.62374854])
# 5 Operation
print(a < 35)
>>>
array([ True, True, False, False])
넘파이에서 산술 연산은 원소끼리(elementwise) 적용된다. 즉, 같은 차원에 존재하는 값들끼리 연산된다는 의미이다. 그리고, 연산의 결과는 새로운 배열이 생성되고 값이 채워지는 형태로 나타난다.
- 2, 3, 4, 5 Operation을 보면 같은 shape을 가지고 있는 배열 a와 b가 elementwise 연산을 수행한 것이다.
- 4 Operation을 보면 np.sin(a)는 (4,) shape를 가지고 있는 배열인데 각각의 원소에 10을 곱한 것이다. (브로드 캐스팅, 이 부분은 추후 포스팅에서 더 자세히 다룰 예정)
A = np.array([[1, 1],
[0, 1]])
B = np.array([[2, 0],
[3, 4]])
# elementwise product
print(A * B)
>>>
array([[2, 0],
[0, 4]])
# matrix product
print(A @ B)
>>>
array([[5, 4],
[3, 4]])
# another matrix product
print(A.dot(B))
>>>
array([[5, 4],
[3, 4]])
* 연산은 elementwise 곱으로 (Hadamard product) 행렬 A와 B사이의 같은 차원의 값들끼리 곱해졌다. 반면, 일반적인 행렬곱을 수행하려면 @ 연산자나 .dot() 메소드를 사용하면 된다.
import numpy as np
rg = np.random.default_rng(1) # create instance of default random number generator
a = np.ones((2, 3), dtype=int)
b = rg.random((2, 3))
print(a)
>>>
array([[1, 1, 1],
[1, 1, 1]])
print(b)
>>>
array([[0.51182162, 0.9504637 , 0.14415961],
[0.94864945, 0.31183145, 0.42332645]])
a *= 3
print(a)
>>>
array([[3, 3, 3],
[3, 3, 3]])
b += a
print(b)
>>>
array([[3.51182162, 3.9504637 , 3.14415961],
[3.94864945, 3.31183145, 3.42332645]])
a += b
>>>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int32') with casting rule 'same_kind'
- np.random.defualt_rng(seed)는 랜덤으로 번호를 생성해주는 제너레이터이다.
- b += a 연산의 경우에는 float64 데이터 타입의 행렬 b에 int32 데이터 타입의 행렬 a를 더하는 연산을 수행하므로 캐스팅 오류가 나지않는다. (행렬 a의 데이터 타입을 float64 데이터 타입으로 캐스팅 하는데에 문제가 없음.)
- 반면, a += b 연산의 경우에는 int32 데이터 타입 행렬 a에 float64 데이터 타입의 행렬 b를 더하는 것이므로, float64 타입의 행렬 b를 int32 데이터 타입으로 캐스팅할 때 문제가 발생한다. (64비트를 32비트의 메모리에 할당할 때에 누수 현상이 발생)
import numpy as np
a = np.ones(3, dtype=np.int32)
b = np.linspace(0, np.pi, 3)
print(b)
>>>
array([0. , 1.57079633, 3.14159265])
print(b.dtype)
>>>
dtype('float64')
print(b.dtype.name)
>>>
'float64'
c = a + b
print(c)
>>>
array([1. , 2.57079633, 4.14159265])
d = np.exp(c * 1j)
print(d)
>>>
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
-0.54030231-0.84147098j])
print(d.dtype.name)
>>>
'complex128'
print(type(d.dtype))
>>>
<class 'numpy.dtype'>
- np.exp() 메소드를 사용하여 자연 상수를 밑으로 취할 수 있다.
- 넘파이 배열에 dtype 필드를 호출하면 numpy.dtype 클래스 타입의 객체가 반환된다. 해당 객체는 name 프로퍼티를 사용하여 데이터 타입을 문자열로 얻을 수 있다.
rg = np.random.default_rng(1)
a = rg.random((2, 3))
print(a)
>>>
array([[0.51182162, 0.9504637 , 0.14415961],
[0.94864945, 0.31183145, 0.42332645]])
print(a.sum())
>>>
3.290252281866131
print(a.min())
>>>
0.14415961271963373
print(a.max())
>>>
0.9504636963259353
랜덤 제너레이터 인스턴스 rg를 통해 (2, 3) shape의 난수 배열 a를 생성했다.
- sum() : 모든 원소의 합
- min() : 모든 원소에서 최소값
- max() : 모든 원소에서 최대값
b = np.arange(12).reshape(3, 4)
print(b)
>>>
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# sum of each column
print(b.sum(axis=0))
>>>
array([12, 15, 18, 21])
# min of each row
print(b.min(axis=1))
>>>
array([0, 4, 8])
# cumulative sum along each row
print(b.cumsum(axis=1))
>>>
array([[ 0, 1, 3, 6],
[ 4, 9, 15, 22],
[ 8, 17, 27, 38]])
- 행렬 b의 shape은 (3, 4)이다. 여기서 axis=0은 첫 번째 차원인 3을, axis=1은 두 번째 차원인 4를 의미한다.
- sum(axis=0)은 첫 번째 차원인 3행에 대한 합을 의미한다. 즉, 3개 행의 원소들을 합해야 한다는 의미이므로 세로로 원소를 합하면 된다. array([12, 15, 18, 21])를 보면, 12는 0 + 4 + 8 / 15는 1 + 5 + 9 ..
- min(axis=1)은 두 번째 차원인 4열에 대한 최소값을 의미한다. 즉, 4개 열에서 최소값을 찾는 것이기 때문에 가로(행)로 최소값을 찾으면 된다. 각 행에서 최소값은 0, 4, 8이다.
- cumsum(axis=1)은 두 번째 차원인 4열에 대한 누적합(accumulate sum)을 의미한다. 즉, 4개 열의 원소들을 누적해나가면 되는것이기 때문에 [0, 1, 3, 6]을 보면 0은 0 / 1은 0 + 1 / 3은 0 + 1 + 2 / 6은 0 + 1 + 2 + 3
참고
https://numpy.org/devdocs/user/quickstart.html
'[Library] - Numpy > Quick Start' 카테고리의 다른 글
# 5. Universal functions (0) | 2022.02.25 |
---|---|
# 3. Printing Arrays (0) | 2022.02.19 |
# 1. Numpy Array Creation (0) | 2022.01.09 |
# 0. Numpy 기초 (0) | 2022.01.07 |
댓글