我正在寻找一种快速计算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)
将它们相加。然而,这很慢,我想知道是否有一个矢量化函数可以用来加速它。
如果有人有任何建议,我会非常感激!
答案 0 :(得分:9)
在我看来,您需要做的就是更改换位顺序,然后A.T * B
代替A * B.T
。
如果那不是你想要的,那么看看np.einsum
,它可以做一些非常强大的伏都教。对于上面的示例,您可以执行以下操作:
np.einsum('ij,ik->jk', A, B)
答案 1 :(得分:2)
另请考虑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 * B
或A * B.T
成功广播。