快速计算所有行之间的点积

3

我有一个2d numpy数组 X = (xrows, xcols),我想对数组的每行组合应用点积,以获得另一个形状为 P = (xrow, xrow) 的数组。

代码如下:

P = np.zeros((xrow, xrow))
for i in range(xrow):
   for j in range(xrow):
      P[i, j] = numpy.dot(X[i], X[j])

如果数组X很小,则这种方法效果很好,但对于大型的X来说可能需要花费大量时间。有没有更快的方法或者更符合Python语言特性的方式来加速处理呢?

2个回答

6

通过执行 result = X.dot(X.T) 获得。

当数组变得很大时,可以按块完成,但根据您的numpy后端,这应该已经尽可能地并行化了线程。看起来这就是你要寻找的。

如果出于某种原因,您不想依赖它,并最终采用多进程,您可以尝试类似以下方式:

import numpy as np
X = np.random.randn(1000, 100000)
block_size = 10000
from sklearn.externals.joblib import Parallel, delayed
products = Parallel(n_jobs=10)(delayed(np.dot)(X[:, pos:pos + block_size], X.T[pos:pos + block_size]) for pos in range(0, X.shape[1], block_size))
product = np.sum(products, axis=0)

我认为对于相对较小的数组,这并不太有用。有时使用线程可以更好地解决这个问题。


块大小为10k还是1k样本的总数? - Abhishek Thakur
块在特征空间中,因此对于100k个特征,需要10k个块。正如我所说,在大多数情况下,X.dot(X.T)基本上可以解决问题。 - eickenberg
X.dot(X.T) 的内存消耗如何? - Abhishek Thakur
它应该分配 np.zeros((X.shape[0],) * 2) 并写入其中。在不产生太多内存开销的情况下,这个操作是完全可能的。我无法告诉你 numpy 是如何实现的。如果内存是您的使用案例的问题,请提供一些维度。 - eickenberg
你可以从“Parallel”中提取迭代并将其写成一个for循环,直接保存到结果数组(上面的“zeros”),避免在内存中拥有所有中间矩阵。 - eickenberg

0

这在我的机器上比循环快10%:

numpy.matrix(X) * numpy.matrix(X.T)

但仍有50%的冗余。


1
人们通常避免使用 numpy.matrix,而更喜欢使用 numpy.dot。否则我同意这个观点,因为我基本上也建议这样做 ;) - eickenberg

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