稀疏python向量的规范

时间:2012-09-24 17:09:29

标签: python numpy scipy sparse-array

是否有可能在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()
来自Dougal的

但是Cython解决方案也非常好,并且随着向量增长的元素数量不同而变得更好。谢谢大家的帮助!

3 个答案:

答案 0 :(得分:1)

  1. 我希望你没有真正初始化和设置这样的元素,这些警告是出于某种原因而提出的,而4M临时列表证明你有足够的资源;)。
  2. 通过直接使用基础数据vector1.data,手动计算规范非常简单。您还可以使用vector1.multiply(vector1).sumvector1.dot(vector1.T)之类的内容,但正如Dougal指出的那样,对于这种简单的情况,这可能会慢得多。
  3. 我想你想做更多,但如果你只想要矢量规范,那么通过稀疏矩阵似乎需要做很多不必要的工作。

答案 1 :(得分:1)

我在这里遇到了同样的问题,我在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)

答案 2 :(得分:0)

我不认为你的初始化正在做你认为的那样。

要使规范正常工作,您需要一个正方形数组。如果你想制作一个有400万个元素的正方形数组,你想做

csr_matrix( (2000,2000), dtype=float64)

scipy

初始化的完整文档