【发布时间】:2012-06-30 12:57:53
【问题描述】:
我有一个 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 的建议,我尝试了对稀疏矩阵求和的替代方案,并将稀疏矩阵求和到密集矩阵上。下面的代码显示了在可比时间内运行的所有方法(amd64 Debian 上的 Python 2.6.6/四核 i7 上的 Squeeze)
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 倍左右...但没有什么比您希望看到的数量级改进考虑到零添加的数量,应该可以跳过。
【问题讨论】:
标签: python optimization numpy scipy sparse-matrix