矩阵乘法:将矩阵的每一行乘以 Python 中的另一个二维矩阵

LED*_*LED 5 python numpy matrix numpy-einsum array-broadcasting

我试图从这个矩阵乘法中删除循环(并了解更多关于一般优化代码的信息),我想我需要某种形式的np.broadcastingor np.einsum,但是在阅读它们之后,我仍然不确定如何使用它们我的问题。

A = np.array([[1, 2, 3, 4, 5],
         [6, 7, 8, 9, 10],
         [11,12,13,14,15]])
#A is a 3x5 matrix, such that the shape of A is (3, 5) (and A[0] is (5,))

B = np.array([[1,0,0],
         [0,2,0],
         [0,0,3]])
#B is a 3x3 (diagonal) matrix, with a shape of (3, 3)

C = np.zeros(5)
for i in range(5):
    C[i] = np.linalg.multi_dot([A[:,i].T, B, A[:,i]])

#Each row of matrix math is [1x3]*[3x3]*[3x1] to become a scaler value in each row
#C becomes a [5x1] matrix with a shape of (5,)
Run Code Online (Sandbox Code Playgroud)

我知道我不能自己做np.multidot,因为这会导致 (5,5) 数组。

我还发现了这一点:将矩阵乘以 Numpy 中另一个矩阵的每一行,但我不知道这是否与我的问题相同。

hpa*_*ulj 5

In [601]: C
Out[601]: array([436., 534., 644., 766., 900.])
Run Code Online (Sandbox Code Playgroud)

这是很自然的einsum。我i和你一样使用,来表示延续到结果的索引。 jk是用于乘积总和的指数。

In [602]: np.einsum('ji,jk,ki->i',A,B,A)
Out[602]: array([436, 534, 644, 766, 900])
Run Code Online (Sandbox Code Playgroud)

它可能也可以用 来完成mutmul,尽管它可能需要添加一个维度并随后进行压缩。

dot使用的方法diag做了比必要的更多的工作。抛出diag了很多值。

要使用,matmul我们必须将i维度设置为 3d 数组的第一个维度。这就是“被动”带来的结果:

In [603]: A.T[:,None,:]@B@A.T[:,:,None]
Out[603]: 
array([[[436]],     # (5,1,1) result

       [[534]],

       [[644]],

       [[766]],

       [[900]]])
In [604]: (A.T[:,None,:]@B@A.T[:,:,None]).squeeze()
Out[604]: array([436, 534, 644, 766, 900])
Run Code Online (Sandbox Code Playgroud)

或者将额外的维度索引掉:(A.T[:,None,:]@B@A.T[:,:,None])[:,0,0]