我希望在python(numpy)中执行以下操作。
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 x 1向量独立地矩阵相乘。我确信这是一个单行。我一直在尝试使用tensordot(),但我似乎在给我答案,我没想到。
我已经在Igor Pro中编程了近10年,现在我正在尝试将它的页面转换为python。
答案 0 :(得分:14)
对不起来表示不满,但使用无价的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”轴。
答案 1 :(得分: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)
编辑:这个版本的第一个版本有问题,而且这个版本计算的应该是更多的han并将其中的大部分内容丢掉。也许最后一个轴上的Python循环是更好的方法。
另一个编辑:我得出的结论是numpy.tensordot()
不是这里的最佳解决方案。
c = (a[:,:,None] * b).sum(axis=1)
会更有效率(虽然更难掌握)。
答案 2 :(得分:1)
另一种实现方法(对于像我这样不熟悉爱因斯坦符号的人来说更容易)是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)