O(N) NxN のコレクションがscipy.sparse.csr_matrix
あり、各スパース行列には N 要素セットのオーダーがあります。これらすべての行列を一緒に追加して、通常の NxN numpy 配列を取得したいと考えています。(N は 1000 のオーダーです)。行列内のゼロ以外の要素の配置は、結果として得られる合計が確かにまばらではないようになっています (事実上ゼロ要素は実際には残っていません)。
現時点では、私はちょうどやっています
reduce(lambda x,y: x+y,[m.toarray() for m in my_sparse_matrices])
これは機能しますが、少し遅いです。もちろん、そこで行われているゼロの無意味な処理の膨大な量は、絶対に恐ろしいものです。
より良い方法はありますか?docsには明らかなことは何もありません。
更新: user545424の提案に従って、疎行列を合計し、疎行列を密行列に合計する代替スキームを試しました。以下のコードは、同等の時間で実行するためのすべてのアプローチを示しています (クアッドコア i7 上の amd64 Debian/Squeeze 上の Python 2.6.6)。
import numpy as np
import numpy.random
import scipy
import scipy.sparse
import time
N=768
S=768
D=3
def mkrandomsparse():
m=np.zeros((S,S),dtype=np.float32)
r=np.random.random_integers(0,S-1,D*S)
c=np.random.random_integers(0,S-1,D*S)
for e in zip(r,c):
m[e[0],e[1]]=1.0
return scipy.sparse.csr_matrix(m)
M=[mkrandomsparse() for i in xrange(N)]
def plus_dense():
return reduce(lambda x,y: x+y,[m.toarray() for m in M])
def plus_sparse():
return reduce(lambda x,y: x+y,M).toarray()
def sum_dense():
return sum([m.toarray() for m in M])
def sum_sparse():
return sum(M[1:],M[0]).toarray()
def sum_combo(): # Sum the sparse matrices 'onto' a dense matrix?
return sum(M,np.zeros((S,S),dtype=np.float32))
def benchmark(fn):
t0=time.time()
fn()
t1=time.time()
print "{0:16}: {1:.3f}s".format(fn.__name__,t1-t0)
for i in xrange(4):
benchmark(plus_dense)
benchmark(plus_sparse)
benchmark(sum_dense)
benchmark(sum_sparse)
benchmark(sum_combo)
print
そしてログアウト
plus_dense : 1.368s
plus_sparse : 1.405s
sum_dense : 1.368s
sum_sparse : 1.406s
sum_combo : 1.039s
N、S、Dパラメーターをいじることで、どちらかのアプローチを2倍程度先に進めることができますが...しかし、数値を考慮することで期待する桁違いの改善のようなものはありませんゼロの追加はスキップできるはずです。