1

是否有可能在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

norm 函数仅适用于数组,因此可能这就是 csr_matrix 不起作用的原因,但后来我没有找到另一种有效计算范数的方法。一种可能的解决方案是计算:

norm(asarray(vector1.todense()))

但随后它首先扼杀了使用稀疏向量的目的。作为最后一种方法,我可以遍历向量的每个元素并手动计算范数,但由于效率非常重要,我一直在寻找更快、更容易实现的东西。

提前感谢您的帮助!

编辑:我尝试了所有建议,最好的解决方案是:

(vector1.data ** 2).sum()

来自杜格尔。但是 Cython 解决方案也非常好,并且随着向量在不同零元素数量上的增长,效果更好。感谢大家的帮助!

4

3 回答 3

1
  1. I hope you are not really initializing and setting elements like that, those warnings are raised for a reason, and a 4M temporary list proofs you have plenty of resources left ;).
  2. Calculating a norm by hand is very simple, by just using the underlying data vector1.data directly. You can also use things like vector1.multiply(vector1) plus .sum or vector1.dot(vector1.T) but as Dougal pointed out, that can be much slower for this simple case.
  3. I guess you want to do more, but if you only want vector norms, going through sparse matrices seems like a lot of unnecessary work.
于 2012-09-24T22:53:54.900 回答
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)
于 2012-09-25T12:51:19.807 回答
0

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

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

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

scipy初始化的完整文档

于 2012-09-24T17:30:40.877 回答