Using a sparse matrix versus numpy array
The scipy
sparse matrix package, and similar ones in MATLAB, was based on ideas developed from linear algebra problems, such as solving large sparse linear equations (ex.finite difference and finite element implementations). そのため、行列積 (numpy 配列の dot
積) や方程式ソルバーといったものがよく開発されています。
私のおおよその経験では、疎な csr
行列積が、同等の密な dot
操作よりも速くなるには 1%の疎性を持つ必要があります – 言い換えれば、99 のゼロに対して非ゼロをひとつという意味です。 (ただし、以下のテストを参照)
しかし、人々はメモリを節約するために疎な行列を使用しようとします。 しかし、そのような行列は値の 3 つの配列を保存しなければならないことに注意してください (少なくとも coo
フォーマットでは)。 つまり,メモリを節約するためには,スパース性が1/3以下でなければならないのです. 5086>
scipy
パッケージは多くのスパースフォーマットを実装しています。 coo
フォーマットが最も理解しやすく、構築しやすいものです。 ドキュメントに従って構築し、.data
, .row
, .col
属性 (3 つの 1 次元配列) を見てください。
csr
と csc
は通常 coo
形式から構築され、データを少し圧縮しているので少し理解しにくいものになっています。 5086>
csr
フォーマットのインデックスを作成することも可能ですが、一般にこれは同等の密な行列/配列の場合よりも遅くなります。 値の変更 (特に 0 から非ゼロへ) や連結、インクリメンタルな増加といった他の操作も遅くなります。
lil
(リストのリスト) も理解しやすく、インクリメンタルに構築するには最良です。 dok
は実際には辞書のサブクラスです。
重要な点は、疎行列は 2 次元に限定され、多くの点で np.matrix
クラスのように動作する (サブクラスではありませんが) ことです。
これらの行列を使うことの利点/欠点を見つけるには、scikit-learn
と sparse
を使った他の質問を検索することが最もよい方法かもしれません。 何度も回答していますが、「学習」側より「疎」側の方がよくわかります。 便利だとは思うのですが、フィット感が必ずしもベストではないというのが実感です。 カスタマイズはlearn
側で。 今のところ sparse
パッケージはこの用途に最適化されていません。
指定したスパース性を持つスパース行列を作成するために sparse.random
メソッドを使用して、いくつかの行列積テストを試したところ、sparse.random
メソッドを使用することがわかりました。 スパース行列の乗算は、私が予想していたよりも良いパフォーマンスを示しました。
In : M=sparse.random(1000,1000,.5)In : timeit M1=M*M1 loops, best of 3: 2.78 s per loopIn : timeit Ma=M.toarray(); M2=Ma.dot(Ma)1 loops, best of 3: 4.28 s per loop
これはサイズの問題です。小さい行列では密な dot
が高速です
In : M=sparse.random(100,100,.5)In : timeit M1=M*M100 loops, best of 3: 3.24 ms per loopIn : timeit Ma=M.toarray(); M2=Ma.dot(Ma)1000 loops, best of 3: 1.44 ms per loop
ただし、インデックス作成を比較してください
In : timeit M.tocsr()10 loops, best of 3: 86.4 ms per loopIn : timeit Ma1000000 loops, best of 3: 318 ns per loopIn : timeit Ma=M.toarray();Ma10 loops, best of 3: 23.6 ms per loop
。