Numpy 带einsum的张量积

Numpy 带einsum的张量积,numpy,numpy-einsum,Numpy,Numpy Einsum,我有一个张量phi=np.random.rand(n,n,3)和一个矩阵D=np.random.rand(3,3)。我想将矩阵D沿着phi的最后一个轴相乘,这样输出就具有形状(n,n,3)。我试过这个 np.einsum("klj,ij->kli", phi, D) 但我对这个符号一点也不自信。基本上我想做 res = np.zeros_like(phi) for i in range(n): for j in range(n):

我有一个张量
phi=np.random.rand(n,n,3)
和一个矩阵
D=np.random.rand(3,3)
。我想将矩阵
D
沿着
phi
的最后一个轴相乘,这样输出就具有形状
(n,n,3)
。我试过这个

np.einsum("klj,ij->kli", phi, D)
但我对这个符号一点也不自信。基本上我想做

res = np.zeros_like(phi)           
for i in range(n):
    for j in range(n):
        res[i, j, :] = D.dot(phi[i, j, :])

您将
phi
视为向量的
n,n
数组,每个向量都要左乘以
D
。因此,您希望保持形状的
n,n
部分保持原样。向量的最后(唯一)维度应与矩阵的最后维度相乘并求和(向量隐式为3x1):

使用
np.matmul
@
操作员)进行广播可能要简单得多:


如果您不介意末尾的额外单位尺寸,可以省略挤压。

哪些轴应相乘,哪些轴应通过求和减少?从所需的输出形状来看,似乎要将每个数组中的最后一个轴相乘,并减少
D
中的第一个轴?这个问题的符号应该是
ijk,lk->ijk
(这几乎与您所写的相同)。您在问题中所写的是将两个数组中的最后一个轴相乘,同时减少两个数组中的最后一个轴。什么是转换?从特定轴的乘法和求和的角度考虑。每个下标将表示一个轴。通过在两个操作数中重复一个下标,可以告诉einsum将这两个轴相乘。通过在所需输出中省略一个下标,您告诉einsum沿此轴求和。谢谢,但预期的操作不正是您使用einsum解决方案所做的吗?
np.einsum(“klj,ij->kli”,phi,D)
?或者,您是在寻找有关其工作原理的解释吗?对于一个小的
n
,您可以比较两种计算。@dba。在第一个einsum中有一个拼写错误,现在已修复。
np.einsum('ijk,lk->ijl', phi, D)
np.einsum('ij,klj->kli', D, phi)
np.squeeze(D @ phi[..., None])