Python - 快速计算外积的方法?

9

我希望能够快速计算n个外积的总和。

基本上,我从正态分布生成了两个矩阵 - 共有n个长度为v的向量:

A = np.random.normal(size = (n, v))
B = np.random.normal(size = (n, v))

我希望能够计算A和B中每个大小为v的向量的外积,并将它们加在一起。
请注意,A*B.T不起作用——A的大小为n x v,而B的大小为v x n。
我能做的最好的办法是创建一个循环,在其中构造外积,然后稍后进行求和。我已经这样做了:
outers = np.array([A[i] * B[i].T])

这会创建一个n x v x v的数组(循环在列表推导式中,随后转换为数组),然后我可以使用np.sum(outers, axis = 0)将其相加。然而,这样做速度相当慢,我想知道是否有向量化函数可以加速。

如果有人有任何建议,我会非常感激!

2个回答

15

在我看来,你只需要改变转置的顺序,用 A.T * B 替代 A * B.T

如果这还不是你想要的,请查看np.einsum,它可以进行一些非常强大的矩阵运算。对于上面的示例,你应该这样做:

np.einsum('ij,ik->jk', A, B)

5

还可以考虑使用np.outer

np.array([np.outer(A, B) for i in xrange(n)]).sum(0)

尽管 @Jamie 建议使用 np.einsum,但它仍是明显的胜者。
In [63]: %timeit np.einsum('ij,ik->jk', A, B)
100000 loops, best of 3: 4.61 us per loop

In [64]: %timeit np.array([np.outer(A[i], B[i]) for i in xrange(n)]).sum(0)
10000 loops, best of 3: 169 us per loop

而且,可以确定的是,它们的结果是相同的:

In [65]: np.testing.assert_allclose(method_outer, method_einsum)

但是,顺带一提,我发现A.T * BA * B.T无法成功广播。


1
他正在对np.matrix对象进行乘法运算,而不是np.ndarrayA * B.T等同于np.dot(A, B.T)A.T * B等同于np.dot(A.T, B)。它应该非常接近np.einsum的速度。 - Jaime
1
+1 是因为你很好地比较了这两种方法。 - elaRosca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接