46

2次元の疎配列があるとします。私の実際のユースケースでは、行数と列数の両方がはるかに大きい (たとえば 20000 と 50000) ため、密な表現を使用するとメモリに収まりません。

>>> import numpy as np
>>> import scipy.sparse as ssp

>>> a = ssp.lil_matrix((5, 3))
>>> a[1, 2] = -1
>>> a[4, 1] = 2
>>> a.todense()
matrix([[ 0.,  0.,  0.],
        [ 0.,  0., -1.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  2.,  0.]])

ここで、サイズが 3 (または実際のケースでは 50000) のすべての非ゼロ コンポーネントを含む密な 1 次元配列があるとします。

>>> d = np.ones(3) * 3
>>> d
array([ 3.,  3.,  3.])

numpy の通常のブロードキャスト セマンティクスを使用して、a と d の要素ごとの乗算を計算したいと思います。ただし、scipy のスパース行列は np.matrix のものです。「*」演算子は、要素ごとの乗算ではなく行列乗算のように動作するようにオーバーロードされています。

>>> a * d
array([ 0., -3.,  0.,  0.,  6.])

1 つの解決策は、'a' を '*' 演算子の配列セマンティクスに切り替えることです。これにより、期待される結果が得られます。

>>> a.toarray() * d
array([[ 0.,  0.,  0.],
       [ 0.,  0., -3.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  6.,  0.]])

しかし、 toarray() への呼び出しは、メモリに収まらない「a」の密なバージョンを具体化するため、それを行うことはできません (結果も密になります):

>>> ssp.issparse(a.toarray())
False

まばらなデータ構造のみを保持しながら、「a」の列で非効率的な python ループを実行する必要なく、これを構築する方法はありますか?

4

3 に答える 3

49

私もscipy.orgで返信しましたが、他の人が検索時にこのページを見つけた場合に備えて、ここに回答を追加する必要があると思いました。

ベクトルをスパース対角行列に変換してから、行列の乗算(*を使用)を使用して、ブロードキャストと同じことを効率的に行うことができます。

>>> d = ssp.lil_matrix((3,3))
>>> d.setdiag(np.ones(3)*3)
>>> a*d
<5x3 sparse matrix of type '<type 'numpy.float64'>'
 with 2 stored elements in Compressed Sparse Row format>
>>> (a*d).todense()
matrix([[ 0.,  0.,  0.],
        [ 0.,  0., -3.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  6.,  0.]])

お役に立てば幸いです。

于 2010-07-28T21:27:58.890 に答える
27

A.multiply(B) は scipy sparse で動作するはずです。メソッドmultiplyは、行列の乗算ではなく、「点ごとの」乗算を行います。

HTH

于 2010-12-21T20:01:07.003 に答える
1

さて、ここにあなたが望むことをする簡単なコードがあります。それがあなたが望むほど効率的であるかどうかはわかりませんので、それを取るか、それを残してください:

import scipy.sparse as ssp
def pointmult(a,b):
    x = a.copy()
    for i in xrange(a.shape[0]):
        if x.data[i]:
            for j in xrange(len(x.data[i])):
                x.data[i] *= b[x.rows[i]]
    return x

これはlil行列でのみ機能するため、他の形式で機能させるには、いくつかの変更を加える必要があります。

于 2010-07-18T22:34:09.900 に答える