2011-03-17 85 views
6

我正在寻找在python(numpy)中执行以下操作。Python中的空洞3D矩阵乘法

Matrix A is M x N x R 
Matrix B is N x 1 x R 

矩阵乘法AB = C,其中C是一个M×1×R矩阵。 本质上,每个M×N层的A(它们中的R)是由B中每个N×1向量独立乘上的矩阵。我相信这是一个单行线。我一直在尝试使用tensordot(),但我似乎给我的答案,我不期望。

我一直在Igor Pro编程近10年,现在我正试图将它的页面转换为python。

回答

8

numpy.tensordot()是做正确的方式:

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) 

编辑:这样做的第一个版本是错误的,这个版本计算更涵它应该和扔掉大部分。也许上一个轴上的Python循环是更好的方法。

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

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

会更有效率(尽管更难掌握)。

+0

谢谢你很快回到我身边。至少,它会让我开始。我将要尝试编写的大部分代码都是以矩阵操作为导向的......所以我应该真正理解这里发生了什么。话虽如此,代码有两部分让我困惑。首先是在tensordot里面调用“轴”。我对实际上做了什么感到困惑,因为我希望x b应该给你c(就像我上面描述的那样),而不用声明任何特殊的东西。也许一旦我明白了,我会明白为什么有必要使用.diagonal。 – Jason 2011-03-18 00:55:45

+0

这很聪明......我不知道需要多长时间才能做出这样的事情(看起来你创建了一个新的轴来乘法和,然后基本上重新组合),我非常感谢你的时间,谢谢许多! – Jason 2011-03-18 18:33:32

+1

如果第一维是矩阵列表(R),第二维是公共矩阵维(N),即a(4,3,2)的形状和b是(4)的形状,则更容易想到这一点。 ,3,1)。乘法运算成为(a * b).sum(axis = 1)。 (a * b)是矩阵中每个元素的行和列的乘积,您需要对每行求和以获得最终矩阵。就像你手动多个矩阵一样。 – 2013-09-25 23:25:36

10

对不起死灵,但这个答案可以大大改善,使用无价的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的收缩。

但也许更重要的是,它的可读性很强。毫无疑问,这段代码是正确的;而且你可以在没有任何问题的情况下使它变得复杂得多。

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

+0

我看到np.dot()也可以做一些多维操作,但是在一些奇怪的规则下工作。你有什么知识吗? – Martian2049 2016-01-28 06:18:02

+0

我的知识可以被最好地总结为'使用艾尔辛姆代替'。可能会稍微冗长些,但在我看来,“明确优于隐含”从来没有应用过更多。 – 2017-08-29 20:14:05