是否可以有效地获得python中稀疏向量的范数?
我尝试了以下方法:
from scipy import sparse
from numpy.linalg import norm
vector1 = sparse.csr_matrix([ 0 for i in xrange(4000000) ], dtype = float64)
#just to test I set a few points to a value higher than 0
vector1[ (0, 10) ] = 5
vector1[ (0, 1500) ] = 80
vector1[ (0, 2000000) ] = 6
n = norm(t1)
但随后我收到错误:
ValueError: dimension mismatch
范数函数仅适用于数组,所以可能这就是csr_matrix不起作用的原因,但后来我没有找到另一种有效计算范数的方法。一种可能的解决方案是计算:
norm(asarray(vector1.todense()))
但随后它首先扼杀了使用稀疏向量的目的。作为最后一种方法,我可以遍历向量的每个元素并手动计算范数,但由于效率非常重要,我正在寻找更快、更容易实现的东西。
提前感谢任何帮助!
编辑:我尝试了所有建议,最好的解决方案是:
(vector1.data ** 2).sum()
来自杜格尔。但是 Cython 解决方案也非常好,并且随着向量在不同于零的元素数量上增长而效果更好。感谢大家的帮助!
- 我希望你没有真正初始化和设置这样的元素,这些警告是有原因的,4M 临时列表证明你还有很多资源;)。
- 手动计算范数非常简单,只需直接使用基础数据
vector1.data
即可。你也可以使用vector1.multiply(vector1)
加.sum
或vector1.dot(vector1.T)
的东西,但正如Dougal指出的那样,对于这个简单的情况来说,这可能会慢得多。 - 我想你想做更多,但如果你只想要向量范数,那么遍历稀疏矩阵似乎是很多不必要的工作。
我在这里遇到了同样的问题,我在cython中实现了一个函数来提高这个简单操作的速度。我用一个 4M 的稀疏向量测试了它,其中包含 100k 个非零元素的双精度。使用 sqrt(vector.multiply(vector).sum()) 的方法使用 874us,我的函数使用 205us。
# sparseLib.pyx
#cython: boundscheck=False
from cython.parallel cimport prange
from cython.view cimport array as cvarray
import numpy as np
from libc.math cimport sqrt
cpdef double sparseNorm2(double [:] data) nogil:
cdef long i
cdef double value = 0.0
for i in xrange(data.shape[0]):
value += data[i]*data[i]
return sqrt(value)
我不认为你的初始化正在做你认为的事情。
为了使范数起作用,您需要有一个方形数组。如果你想做一个有400万个元素的方阵,你想做
csr_matrix( (2000,2000), dtype=float64)
SCIPY 进行初始化的完整文档