30

大きなスパース行列の行を正規化する関数を作成したいと思います(合計が1になるように)。

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

合理的に単純な解決策はありますか?私はこれを見てきましたが、実際に除算を行う方法がまだはっきりしていません。

4

5 に答える 5

46

これはscikit-learnsklearn.preprocessing.normalizeに実装されています。

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

axis=1列で正規化するには、行で正規化する必要がありaxis=0ます。オプションの引数copy=Falseを使用して、マトリックスを所定の位置に変更します。

于 2012-09-12T22:20:02.580 に答える
3

アーロンズの答えは正しいですが、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のソリューションとは対照的に、この方法では、行列を高密度形式にキャストする必要がなく(メモリの問題が発生する可能性があります)、行列の乗算も必要ありません。形状のスパース行列(35'000、486'000)でメソッドをテストしましたが、約18秒かかりました。

于 2019-01-22T10:45:30.930 に答える
2

これが私の解決策です。

  • 転置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()
    
于 2013-01-17T11:07:04.223 に答える
1

これは、組み込み関数を使用せずにそれを行うためのエレガントな方法であることがわかりました。

import scipy.sparse as sp

def normalize(W):
    #Find the row scalars as a Matrix_(n,1)
    rowSumW = sp.csr_matrix(W.sum(axis=1))
    rowSumW.data = 1/rowSumW.data

    #Find the diagonal matrix to scale the rows
    rowSumW = rowSumW.transpose()
    scaling_matrix = sp.diags(rowSumW.toarray()[0])

    return scaling_matrix.dot(W)  
于 2019-12-16T23:04:06.137 に答える
0

sklearnをインポートせずに、密行列または乗算行列に変換し、csr行列のデータ表現を活用します。

from scipy.sparse import isspmatrix_csr

def normalize(W):
    """ row normalize scipy sparse csr matrices inplace.
    """
    if not isspmatrix_csr(W):
        raise ValueError('W must be in CSR format.')
    else:
        for i in range(W.shape[0]):
            row_sum = W.data[W.indptr[i]:W.indptr[i+1]].sum()
            if row_sum != 0:
                W.data[W.indptr[i]:W.indptr[i+1]] /= row_sum

W.indicesは列インデックス W.dataの配列であり、対応する非ゼロ値の配列でありW.indptr、インデックスとデータの行の開始点を指していることを忘れないでください。

numpy.abs()L1ノルムが必要な場合、numpy.max()または行ごとの最大値で正規化するために使用する場合は、合計をとるときにを追加できます。

于 2019-05-02T13:15:51.370 に答える