高效归一化Scipy稀疏矩阵的方法

2024-03-29 10:09:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我想写一个函数来规范化一个大型稀疏矩阵的行(这样它们加起来就是一个)。

from pylab import *
import scipy.sparse as sp

def normalize(W):
    z = W.sum(0)
    z[z < 1e-6] = 1e-6
    return W / z[None,:]

w = (rand(10,10)<0.1)*rand(10,10)
w = sp.csr_matrix(w)
w = normalize(w)

但是,这会导致以下异常:

File "/usr/lib/python2.6/dist-packages/scipy/sparse/base.py", line 325, in __div__
     return self.__truediv__(other)
File "/usr/lib/python2.6/dist-packages/scipy/sparse/compressed.py", line 230, in  __truediv__
   raise NotImplementedError

有没有合理简单的解决办法?我已经看了this,但是还不清楚如何实际进行除法。


Tags: inpyimportreturnlibpackagesusrdist
3条回答

这已在scikit-learn sklearn.preprocessing.normalize中实现。

from sklearn.preprocessing import normalize
w_normalized = normalize(w, norm='l1', axis=1)

axis=1应按行规格化,axis=0应按列规格化。使用可选参数copy=False就地修改矩阵。

这是我的解决办法。

  • 转置A
  • 计算每列的总和
  • 求和倒数的对角矩阵B格式
  • A*B等于标准化
  • 转置C

    import scipy.sparse as sp
    import numpy as np
    import math
    
    minf = 0.0001
    
    A = sp.lil_matrix((5,5))
    b = np.arange(0,5)
    A.setdiag(b[:-1], k=1)
    A.setdiag(b)
    print A.todense()
    A = A.T
    print A.todense()
    
    sum_of_col = A.sum(0).tolist()
    print sum_of_col
    c = []
    for i in sum_of_col:
        for j in i:
            if math.fabs(j)<minf:
                c.append(0)
            else:
                c.append(1/j)
    
    print c
    
    B = sp.lil_matrix((5,5))
    B.setdiag(c)
    print B.todense()
    
    C = A*B
    print C.todense()
    C = C.T
    print C.todense()
    

虽然Aarons的回答是正确的,但我实现了一个解决方案,当时我想规范化绝对值的最大值,sklearn没有提供这个值。我的方法使用非零项并在csr_matrix.data数组中找到它们,以便快速替换其中的值。

def normalize_sparse(csr_matrix):
    nonzero_rows = csr_matrix.nonzero()[0]
    for idx in np.unique(nonzero_rows):
        data_idx = np.where(nonzero_rows==idx)[0]
        abs_max = np.max(np.abs(csr_matrix.data[data_idx]))
        if abs_max != 0:
            csr_matrix.data[data_idx] = 1./abs_max * csr_matrix.data[data_idx]

与sunan的解决方案相反,这种方法不需要将矩阵转换成密集格式(这可能会引起内存问题),也不需要矩阵乘法。我在一个稀疏的形状矩阵(350000486000)上测试了这个方法,花了大约18秒。

相关问题 更多 >