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 的大小为 nxv,而 B 的大小为 vx n。

我能做的最好的事情是创建一个循环,在其中构造外部产品,然后再求和。我有这样的:

outers = np.array([A[i] * B[i].T])

这将创建一个 nxvxv 数组(循环在列表推导中,随后转换为数组),然后我可以使用np.sum(outers, axis = 0). 但是,这很慢,我想知道是否有一个矢量化函数可以用来加快速度。

如果有人有任何建议,我将不胜感激!

4

2 回答 2

15

在我看来,你需要做的就是改变转置的顺序,并做A.T * B而不是A * B.T.

如果这不是您所追求的,请看一下np.einsum,它可以做一些非常强大的巫术。对于上面的示例,您将执行以下操作:

np.einsum('ij,ik->jk', A, B)
于 2013-07-02T23:49:43.213 回答
5

还要考虑np.outer

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

尽管np.einsum@Jamie 建议是明显的赢家。

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广播成功。

于 2013-07-03T00:17:31.080 回答