15

我希望在 python (numpy) 中执行以下操作。

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

矩阵乘法 AB = C,其中 C 是 M x 1 x R 矩阵。本质上,A 的每个 M x N 层(其中 R 层)都是矩阵独立地乘以 B 中的每个 N x 1 向量。我确信这是一个单行。我一直在尝试使用 tensordot(),但我似乎给了我意想不到的答案。

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

4

3 回答 3

18

很抱歉,使用无价的 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”轴。

于 2014-01-28T09:01:40.987 回答
10

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)

会更有效率(虽然更难掌握)。

于 2011-03-17T20:39:01.227 回答
2

另一种方法是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)
于 2020-05-02T12:20:51.987 回答