fad*_*sen 5 python numpy linear-algebra matrix-multiplication numpy-broadcasting
我试图理解为什么numpy的dot函数表现如下:
M = np.ones((9, 9))
V1 = np.ones((9,))
V2 = np.ones((9, 5))
V3 = np.ones((2, 9, 5))
V4 = np.ones((3, 2, 9, 5))
Run Code Online (Sandbox Code Playgroud)
现在np.dot(M, V1),np.dot(M, V2)并按预期行事.但对于V3和V4结果令我感到奇怪:
>>> np.dot(M, V3).shape
(9, 2, 5)
>>> np.dot(M, V4).shape
(9, 3, 2, 5)
Run Code Online (Sandbox Code Playgroud)
我期待(2, 9, 5)和(3, 2, 9, 5)分别.另一方面,np.matmul
我的期望是什么:矩阵乘法在第二个参数的前N-2维上广播,结果具有相同的形状:
>>> np.matmul(M, V3).shape
(2, 9, 5)
>>> np.matmul(M, V4).shape
(3, 2, 9, 5)
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:np.dot行为的理由
是什么?它是出于某种特定目的,还是应用一般规则的结果?
来自以下文档np.dot:
对于2-D阵列,它相当于矩阵乘法,对于1-D阵列相当于矢量的内积(没有复共轭).对于N维,它是在最后一个轴和倒数第二个轴上的和积:
abRun Code Online (Sandbox Code Playgroud)dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
对于np.dot(M, V3),
(9,9), (2,9, 5) --> (9, 2, 5)
对于np.dot(M, V4),
(9,9), (3, 2,9, 5) --> (9, 3, 2, 5)
删除表示总结的维度,因此不存在于结果中.
相反,np.matmul将N维数组视为2D矩阵的"堆栈":
行为取决于以下方式的参数.
- 如果两个参数都是2-D,它们就像传统矩阵一样相乘.
- 如果任一参数是ND,N> 2,则将其视为驻留在最后两个索引中的矩阵堆栈并相应地进行广播.
在两种情况下都执行相同的减少,但轴的顺序是不同的.np.matmul基本上相当于:
for ii in range(V3.shape[0]):
out1[ii, :, :] = np.dot(M[:, :], V3[ii, :, :])
Run Code Online (Sandbox Code Playgroud)
和
for ii in range(V4.shape[0]):
for jj in range(V4.shape[1]):
out2[ii, jj, :, :] = np.dot(M[:, :], V4[ii, jj, :, :])
Run Code Online (Sandbox Code Playgroud)
来自以下文档numpy.matmul:
matmul与 的不同之处dot有两个重要方面。
- 不允许与标量相乘。
- 矩阵堆栈一起广播,就好像矩阵是元素一样。
总之,这是您期望的标准矩阵-矩阵乘法。
另一方面,numpy.dot仅相当于二维数组的矩阵-矩阵乘法。对于较大尺寸,...
它是 a 的最后一个轴与 b 的倒数第二个轴的和积:
Run Code Online (Sandbox Code Playgroud)dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
[来源:文档numpy.dot]
这类似于内(点)积。如果是向量,numpy.dot则返回点积。数组被视为向量的集合,并返回它们的点积。