为什么numpy.dot会以这种方式运行?

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)并按预期行事.但对于V3V4结果令我感到奇怪:

>>> 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行为的理由 是什么?它是出于某种特定目的,还是应用一般规则的结果?

ali*_*i_m 7

来自以下文档np.dot:

对于2-D阵列,它相当于矩阵乘法,对于1-D阵列相当于矢量的内积(没有复共轭).对于N维,它是在最后一个轴倒数第二个轴上的:ab

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
Run Code Online (Sandbox Code Playgroud)

对于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.matmulN维数组视为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)


Ale*_*ogt 4

来自以下文档numpy.matmul

matmul与 的不同之处dot有两个重要方面。

  • 不允许与标量相乘。
  • 矩阵堆栈一起广播,就好像矩阵是元素一样。

总之,这是您期望的标准矩阵-矩阵乘法。

另一方面,numpy.dot仅相当于二维数组的矩阵-矩阵乘法。对于较大尺寸,...

它是 a 的最后一个轴与 b 的倒数第二个轴的和积:

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])
Run Code Online (Sandbox Code Playgroud)

[来源:文档numpy.dot]

这类似于内(点)积。如果是向量,numpy.dot则返回点积。数组被视为向量的集合,并返回它们的点积。