소개
NumPy 는 Python 에서 과학적 계산을 위한 강력한 라이브러리입니다. NumPy 의 가장 중요한 기능 중 하나는 다양한 유형의 배열 곱셈을 효율적으로 수행할 수 있다는 것입니다.
이 튜토리얼에서는 numpy.multiply, numpy.dot, numpy.matmul, *, 및 @ 연산자를 포함하여 NumPy 에서 사용할 수 있는 다양한 곱셈 연산을 살펴보겠습니다.
시작하기
NumPy 의 다양한 곱셈 연산을 살펴보기 전에, 먼저 터미널에서 다음 명령을 입력하여 Python 셸을 엽니다.
python3
그런 다음 라이브러리를 가져오고 데모에 사용할 샘플 배열을 몇 개 만듭니다.
import numpy as np
## Creating sample arrays
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
두 개의 배열 A와 B를 만들었습니다. 각 배열은 2 개의 행과 2 개의 열을 가지고 있습니다. 이제 NumPy 에서 사용할 수 있는 다양한 곱셈 연산을 살펴보겠습니다.
numpy.multiply 사용법
numpy.multiply 함수는 두 배열 간의 요소별 곱셈을 수행합니다. 두 배열은 동일한 형태 (shape) 를 가져야 합니다. 결과 배열은 입력 배열과 동일한 형태를 갖습니다.
C = np.multiply(A, B)
print(C)
## Output:
## array([[ 5, 12],
## [21, 32]])
이 예제에서 A의 각 요소는 B의 해당 요소와 곱해져 두 배열의 요소별 곱셈이 수행됩니다.
numpy.dot 사용법
numpy.dot 함수는 두 배열 간의 행렬 곱셈을 수행합니다. 첫 번째 배열은 두 번째 배열의 행 수와 동일한 수의 열을 가져야 합니다. 결과 배열은 첫 번째 배열과 동일한 수의 행과 두 번째 배열과 동일한 수의 열을 갖습니다.
C = np.dot(A, B)
print(C)
## Output:
## array([[19, 22],
## [43, 50]])
이 예제에서는 배열 A와 B 간의 행렬 곱셈을 수행했습니다. 결과 배열 C는 예상대로 두 개의 행과 두 개의 열을 갖습니다.
numpy.matmul 사용법
numpy.matmul 함수는 두 배열 간의 행렬 곱셈도 수행하지만, 다차원 배열을 처리하는 데 약간 다른 규칙을 가지고 있습니다. 두 배열은 마지막 두 차원을 제외하고 동일한 형태 (shape) 를 가져야 하며, 이 두 차원은 호환되어야 합니다. 배열 중 하나가 1 차원인 경우, 형태에 1 을 추가하여 행렬로 승격됩니다.
C = np.matmul(A, B)
print(C)
## Output:
## array([[19, 22],
## [43, 50]])
이 예제에서는 numpy.dot과 동일한 결과를 얻습니다. 이는 배열 A와 B가 동일한 형태를 가지므로 numpy.matmul이 numpy.dot과 동일하게 동작하기 때문입니다.
그리고 다른 예시가 있습니다:
## define two 3-D arrays
a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = np.array([[[9, 10], [11, 12]], [[13, 14], [15, 16]]])
c = np.matmul(a, b)
d = np.dot(a, b)
print(c)
## Output:
## array([[[ 31, 34],
## [ 71, 78]],
## [[155, 166],
## [211, 226]]])
print(d)
## Output:
## array([[[[ 31, 34],
## [ 43, 46]],
## [[ 71, 78],
## [ 99, 106]]],
## [[[111, 122],
## [155, 166]],
## [[151, 166],
## [211, 226]]]])
이 예제에서 numpy.matmul은 배치 행렬 곱셈 연산을 수행합니다.
a와 b 모두 3 차원 배열이므로 numpy.dot의 출력은 $(2,2,2,2)$ 차원을 갖습니다. 처음 두 차원은 a와 b의 두 배치 $2\times2$ 행렬에 해당합니다. 다음 두 차원은 배치에서 각 $2\times2$ 행렬 쌍의 점 곱 (dot product) 에 해당합니다:
## the first 2 × 2 result
dot(a[0], b[0]) =
dot([[1, 2],
[3, 4]],
[[9, 10],
[11, 12]]
= [[1*9 + 2*11, 1*10 + 2*12],
[3*9 + 4*11, 3*10 + 4*12]]
= [[31, 34],
[43, 46]]
* 연산자 사용법
* 연산자는 두 배열 간의 요소별 곱셈도 수행하지만, numpy.multiply와 약간 다르게 동작합니다. 두 배열의 형태가 동일한 경우, * 연산자는 numpy.multiply와 마찬가지로 요소별 곱셈을 수행합니다. 그러나 배열 중 하나가 스칼라 값인 경우, * 연산자는 다른 배열의 모든 요소에 대해 스칼라 곱셈을 수행합니다.
C = A * B
D = A * 2
print(C)
## Output:
#array([[ 5, 12],
## [21, 32]])
print(D)
## Output:
## array([[2, 4],
## [6, 8]])
첫 번째 예제에서는 numpy.multiply와 동일한 결과를 얻습니다. 두 번째 예제에서는 배열 A의 모든 요소에 대해 스칼라 곱셈을 수행합니다.
@ 연산자 사용법
@ 연산자는 numpy.dot 및 numpy.matmul과 마찬가지로 행렬 곱셈을 수행합니다. Python 3.5 에서 numpy.matmul의 단축 표현으로 도입되었습니다.
C = A @ B
print(C)
## Output:
## array([[19, 22],
## [43, 50]])
이 예제에서는 @ 연산자를 사용하여 배열 A와 B 간의 행렬 곱셈을 수행합니다. 결과 배열 C는 numpy.dot 및 numpy.matmul과 마찬가지로 두 개의 행과 두 개의 열을 갖습니다.
요약
이 튜토리얼에서는 NumPy 에서 사용할 수 있는 다양한 곱셈 연산을 살펴보았습니다. 각 연산에는 고유한 규칙과 사용 사례가 있으므로 특정 작업에 적합한 연산을 선택하는 것이 중요합니다. 이러한 연산을 숙달함으로써 NumPy 를 사용하여 Python 에서 배열 및 행렬 곱셈을 효율적으로 수행할 수 있습니다.



