web-dev-qa-db-ja.com

Scipyでスパース行列をスライス-どのタイプが最も効果的ですか?

SciPy スパースマトリックスチュートリアル は非常に優れていますが、実際にはスライスされていない(開発されていない)スライスに関するセクションは残っています(まだアウトライン形式です-「スパースマトリックスの処理」を参照してください)。

この質問に答えたら、チュートリアルを更新します。

大きなスパースマトリックスがあります-現在はdok_matrix形式です。

_import numpy as np
from scipy import sparse
M = sparse.dok_matrix((10**6, 10**6))
_

さまざまな方法で列をスライスしたい場合や、行をスライスしたい場合があります。理想的には、次のように、スパース行列Mをスライスするために高度なインデックス付け(つまり、ブールベクトル_bool_vect_)を使用します。

_bool_vect = np.arange(10**6)%2  # every even index
out = M[bool_vect,:]            # Want to select every even row
_

または

_out = M[:,bool_vect] # Want to select every even column
_

まず、dok_matricesはこれをサポートしていません-sparse.lil_matrix(M)を介して最初にlil_matricesにキャストすると、(ゆっくり)機能すると思います

チュートリアルから収集できる限り、列をスライスするにはCSCを使用し、行をスライスするにはCSRをスライスします。つまり、次のようにして行列Mをキャストする必要があります。

_M.tocsc()[:,bool_vect]
_

または

_M.tocsr()[bool_vect,:]
_

私はここでちょっと推測していますが、コードが遅いためにコードが遅くなります。これがどのように機能するかを理解している誰かからの助けがあれば幸いです。前もって感謝します。

結局のところ、ブール配列を使用してマトリックスにインデックスを付けるのではなく、整数(インデックス)のリストを作成する必要があります。これもまた、私が見つけて嬉しいことです。どちらがより効率的です。

最後に-これは大きなマトリックスなので、これがその場で/放送とともに発生する可能性がある場合、ボーナスポイントが得られます。

26
gabe

わかりましたので、これを行う「正しい」方法は確かです。列をスライスする場合は、tocsc()を使用し、整数のリスト/配列を使用してスライスします。ブールベクトルは、疎行列でトリックを実行しないようです-numpyのndarrayで行う方法です。それが答えです。

indices = np.where(bool_vect)[0]
out1 = M.tocsc()[:,indices]
out2 = M.tocsr()[indices,:]

しかし、質問:これは最良の方法ですか?これは適切ですか?

実際には、これは適切に行われているように見えます。以前の試み(lil_matrixを使用)よりもはるかに高速です。

44
gabe