numpy dot ()과 Python 3.5+ 행렬 곱셈의 차이점 @
저는 최근에 Python 3.5로 이동했고 새로운 행렬 곱셈 연산자 (@)가 때때로 numpy 도트 연산자 와 다르게 작동 하는 것을 발견했습니다 . 예를 들어 3D 배열의 경우 :
import numpy as np
a = np.random.rand(8,13,13)
b = np.random.rand(8,13,13)
c = a @ b # Python 3.5+
d = np.dot(a, b)
@
연산자 형태의 배열을 반환
c.shape
(8, 13, 13)
np.dot()
함수가 반환 하는 동안 :
d.shape
(8, 13, 8, 13)
numpy dot으로 동일한 결과를 어떻게 재현 할 수 있습니까? 다른 중요한 차이점이 있습니까?
@
연산자는 배열의 호출 __matmul__
방법 없습니다 dot
. 이 메소드는 API에도 함수로 존재합니다 np.matmul
.
>>> a = np.random.rand(8,13,13)
>>> b = np.random.rand(8,13,13)
>>> np.matmul(a, b).shape
(8, 13, 13)
문서에서 :
matmul
dot
두 가지 중요한 점에서 다릅니다 .
- 스칼라에 의한 곱셈은 허용되지 않습니다.
- 행렬의 스택은 마치 행렬이 요소 인 것처럼 함께 브로드 캐스트됩니다.
마지막 요점은 3D (또는 더 높은 차원의) 배열을 전달할 때 dot
및 matmul
메서드가 다르게 작동 한다는 것을 분명히 합니다. 문서에서 좀 더 인용하면 :
대상 matmul
:
인수 중 하나가 ND, N> 2이면 마지막 두 인덱스에있는 행렬 스택으로 처리되고 그에 따라 브로드 캐스트됩니다.
대상 np.dot
:
2 차원 배열의 경우 행렬 곱셈과 동일하고 1 차원 배열의 경우 벡터의 내적 (복소 켤레 없음)에 해당합니다. N 차원의 경우 a의 마지막 축과 b의 마지막에서 두 번째 축에 대한 합계 제품입니다.
@ajcr의 대답은 dot
및 matmul
( @
기호로 호출 됨 )가 어떻게 다른지 설명합니다 . 간단한 예를 살펴보면 'stacks of matricies'또는 tensor에서 작동 할 때 두 가지가 어떻게 다르게 작동하는지 분명히 알 수 있습니다.
차이점을 명확히하기 위해 4x4 배열을 사용하고 2x4x3 'stack of matricies'또는 tensor로 dot
제품과 matmul
제품을 반환합니다 .
import numpy as np
fourbyfour = np.array([
[1,2,3,4],
[3,2,1,4],
[5,4,6,7],
[11,12,13,14]
])
twobyfourbythree = np.array([
[[2,3],[11,9],[32,21],[28,17]],
[[2,3],[1,9],[3,21],[28,7]],
[[2,3],[1,9],[3,21],[28,7]],
])
print('4x4*4x2x3 dot:\n {}\n'.format(np.dot(fourbyfour,twobyfourbythree)))
print('4x4*4x2x3 matmul:\n {}\n'.format(np.matmul(fourbyfour,twobyfourbythree)))
각 작업의 제품은 다음과 같습니다. 내적이 어떤지 주목하세요.
... a의 마지막 축과 b의 마지막에서 두 번째 축에 대한 합계 곱
및 매트릭스를 함께 브로드 캐스트하여 매트릭스 제품이 형성되는 방법.
4x4*4x2x3 dot:
[[[232 152]
[125 112]
[125 112]]
[[172 116]
[123 76]
[123 76]]
[[442 296]
[228 226]
[228 226]]
[[962 652]
[465 512]
[465 512]]]
4x4*4x2x3 matmul:
[[[232 152]
[172 116]
[442 296]
[962 652]]
[[125 112]
[123 76]
[228 226]
[465 512]]
[[125 112]
[123 76]
[228 226]
[465 512]]]
수학에서, 내가 생각하는 점 NumPy와에서 더 의미가 있습니다
점 (a, b) _ {i, j, k, a, b, c} = \ sum_m a_ {i, j, k, m} b_ {a, b, m, c}
since it gives the dot product when a and b are vectors, or the matrix multiplication when a and b are matrices
As for matmul operation in numpy, it consists of parts of dot result, and it can be defined as
matmul(a,b)_{i,j,k,c} = \sum_m a_{i,j,k,m}b_{i,j,m,c}
So, you can see that matmul(a,b) returns an array with a small shape, which has smaller memory consumption and make more sense in applications. In particular, combining with broadcasting, you can get
matmul(a,b)_{i,j,k,l} = \sum_m a_{i,j,k,m}b_{j,m,l}
for example.
From the above two definitions, you can see the requirements to use those two operations. Assume a.shape=(s1,s2,s3,s4) and b.shape=(t1,t2,t3,t4)
To use dot(a,b) you need
1. **t3=s4**;
To use matmul(a,b) you need
- t3=s4
- t2=s2, or one of t2 and s2 is 1
- t1=s1, or one of t1 and s1 is 1
Use the following piece of code to convince yourself.
Code sample
import numpy as np
for it in xrange(10000):
a = np.random.rand(5,6,2,4)
b = np.random.rand(6,4,3)
c = np.matmul(a,b)
d = np.dot(a,b)
#print 'c shape: ', c.shape,'d shape:', d.shape
for i in range(5):
for j in range(6):
for k in range(2):
for l in range(3):
if not c[i,j,k,l] == d[i,j,k,j,l]:
print it,i,j,k,l,c[i,j,k,l]==d[i,j,k,j,l] #you will not see them
Just FYI, @
and its numpy equivalents dot
and matmul
are all roughly equally fast. (Plot created with perfplot, a project of mine.)
Code to reproduce the plot:
import perfplot
import numpy
def setup(n):
A = numpy.random.rand(n, n)
x = numpy.random.rand(n)
return A, x
def at(data):
A, x = data
return A @ x
def numpy_dot(data):
A, x = data
return numpy.dot(A, x)
def numpy_matmul(data):
A, x = data
return numpy.matmul(A, x)
perfplot.show(
setup=setup,
kernels=[at, numpy_dot, numpy_matmul],
n_range=[2 ** k for k in range(12)],
logx=True,
logy=True,
)
'IT story' 카테고리의 다른 글
AngularJS 시드 : JavaScript를 별도의 파일 (app.js, controllers.js, directives.js, filters.js, services.js)에 넣기 (0) | 2020.08.30 |
---|---|
AngularJS : ngInclude 대 지시문 (0) | 2020.08.30 |
Rails : 컨트롤러 클래스 이름을 기반으로 모델 클래스 이름을 얻는 방법은 무엇입니까? (0) | 2020.08.29 |
C ++에서 비공개 정적 const 맵을 초기화하는 방법은 무엇입니까? (0) | 2020.08.29 |
초점을 잃어버린 DOM에서 사라지는 html 요소를 어떻게 검사 할 수 있습니까? (0) | 2020.08.29 |