python中的无环3D矩阵乘法

python中的无环3D矩阵乘法,python,matrix,numpy,operation,Python,Matrix,Numpy,Operation,我希望用python(numpy)执行以下操作 矩阵乘AB=C,其中C是M x 1 x R矩阵。 基本上,A的每个M x N层(其中的R层)都是矩阵乘以B中的每个N x 1向量。我确信这是一条线性。我一直在尝试使用tensordot(),但我发现它似乎给了我意想不到的答案 我已经在igorpro中编程近10年了,现在我正在尝试将其中的页面转换为python。是正确的方法: a = numpy.arange(24).reshape(2, 3, 4) b = numpy.arange(12).res

我希望用python(numpy)执行以下操作

矩阵乘AB=C,其中C是M x 1 x R矩阵。 基本上,A的每个M x N层(其中的R层)都是矩阵乘以B中的每个N x 1向量。我确信这是一条线性。我一直在尝试使用tensordot(),但我发现它似乎给了我意想不到的答案

我已经在igorpro中编程近10年了,现在我正在尝试将其中的页面转换为python。

是正确的方法:

a = numpy.arange(24).reshape(2, 3, 4)
b = numpy.arange(12).reshape(3, 1, 4)
c = numpy.tensordot(a, b, axes=[1, 0]).diagonal(axis1=1, axis2=3)
编辑:此版本的第一个版本有错误,此版本计算的han比它应该的多,并且丢弃了大部分han。也许在最后一个轴上进行Python循环是更好的方法

另一次编辑:我得出结论,
numpy.tensordot()
不是这里的最佳解决方案

c = (a[:,:,None] * b).sum(axis=1)

将更有效(尽管更难掌握)。

对于巫术很抱歉,但是这个答案可以通过使用非常宝贵的np.einsum进行大幅改进

import numpy as np

D,M,N,R = 1,2,3,4
A = np.random.rand(M,N,R)
B = np.random.rand(N,D,R)

print np.einsum('mnr,ndr->mdr', A, B).shape
请注意,它有几个优点:首先,它速度快。np.einsum通常都经过了很好的优化,但此外,np.einsum足够聪明,可以避免创建MxNxR临时数组,但直接对N执行压缩

但也许更重要的是,它非常可读。毫无疑问,该代码是正确的;你可以毫不费力地把它弄得更复杂

请注意,如果您愿意,可以简单地从B和einsum语句中删除虚拟“D”轴。

另一种方法是
np.matmul()
。重要的是在最后两个索引中有匹配的维度((M,N)x(N,1))。对于这种用法
np.transpose()
示例:

M, N, R = 4, 3, 10
A = np.ones((M, N, R))
B = np.ones((N, 1, R))

# have the matching dimensions at the very end
C = np.matmul(np.transpose(A, (2, 0, 1)), np.transpose(B, (2, 0, 1))) 
C = np.transpose(C, (1, 2, 0))

print(A.shape)
# out: #(4, 3, 10)
print(B.shape)
# out: #(3, 1, 10)
print(C.shape)
# out: #(4, 1, 10)

谢谢你这么快回复我。至少,它会让我开始。我将尝试编写的大部分代码都是面向矩阵运算的。。。所以我真的应该试着去理解这里发生了什么。话虽如此,代码中有两个部分让我感到困惑。首先是调用tensordot内部的“轴”。我对它的实际作用感到困惑,因为我希望a x b应该只给出c(正如我上面描述的那样),而不声明任何特殊的东西。也许一旦我明白了这一点,我就会明白为什么有必要使用对角线。这很聪明。。。我不知道我花了多长时间做这样的事情(看起来你创建了一个新的轴来进行乘法和,然后基本上重新组合)我真的很感谢你的时间,谢谢!如果第一个维度是矩阵列表(R),第二个维度是公共矩阵维度(N),即a的形状是(4,3,2),b的形状是(4,3,1),则更容易想到这一点。然后乘法运算变成(a*b).sum(轴=1)。(a*b)是矩阵中每个元素的行和列的乘积,您需要对每行求和以得到最终矩阵。就像你手动多重矩阵一样。我看到np.dot()也可以做一些多维运算,但在一些奇怪的规则下工作。你知道这方面的知识吗?我的知识可以概括为“改用einsum”。可能有点冗长,但在我看来,“显式优于隐式”从未应用得更多。
M, N, R = 4, 3, 10
A = np.ones((M, N, R))
B = np.ones((N, 1, R))

# have the matching dimensions at the very end
C = np.matmul(np.transpose(A, (2, 0, 1)), np.transpose(B, (2, 0, 1))) 
C = np.transpose(C, (1, 2, 0))

print(A.shape)
# out: #(4, 3, 10)
print(B.shape)
# out: #(3, 1, 10)
print(C.shape)
# out: #(4, 1, 10)