平方数组求和

Fre*_*Foo 9 python numpy linear-algebra

作为批量欧几里德距离计算的一部分,我正在计算

(X * X).sum(axis=1)
Run Code Online (Sandbox Code Playgroud)

哪里X是一个相当大的二维数组.这工作正常,但它构造了一个与之相同大小的临时数组X.有没有办法摆脱这种暂时的,但保留矢量化操作的效率?

明显的候选人,

np.array([np.dot(row, row) for row in X])
Run Code Online (Sandbox Code Playgroud)

工作,但使用Python列表作为临时,使其相当慢.

没有axis,记忆效率的形式将是

(X * X).sum()  =>  np.dot(X.ravel(), X.ravel())
Run Code Online (Sandbox Code Playgroud)

而且我知道,什么时候axis=1,它相当于

np.diag(np.dot(X, X.T))
Run Code Online (Sandbox Code Playgroud)

这让我寻找到的概括dot,如np.inner,np.tensordotnp.einsum,但我想不出他们将如何解决我的问题.

YXD*_*YXD 11

einsum等效是:

np.einsum('ij,ij->i', X, X)
Run Code Online (Sandbox Code Playgroud)

虽然我不确定这是如何在内部工作所以它可能会或可能不会解决您的问题.

  • Einsum可能是numpy处理大型数组的最佳函数之一.它完全用C编译并利用`SSE2`,numpy的ufuncs直到1.8才会使用.它也试图避免在内存中保存大的numpy中间体.源代码是[这里](https://github.com/numpy/numpy/blob/6f9a41276153187a4c6e45eb0b8a9999d946608d/numpy/core/src/multiarray/einsum.c.src). (5认同)
  • 另一种选择是`inner1d`:`numpy.core.umath_tests import inner1d; inner1d(X,X)`,但是`np.einsum`在大多数情况下或者在大多数系统上都比较快. (5认同)
  • 我认为它仍然是实验性的,但它仍然存在.`inner1d`和`matrix_multiply`是gufuncs的两个第一个实例,其中'g'代表'generalized',[这是API文档所说的](http://docs.scipy.org/doc/numpy/reference /c-api.generalized-ufuncs.html).在numpy 1.8中将有一整批线性代数gufunc,包括那两个,[浏览PR](https://github.com/numpy/numpy/pull/2954/files)以查看将添加的内容.gufuncs的最佳之处在于,当你处理更复杂的算法时,它们确实很容易用C扩展numpy. (2认同)