Mam zbiór O (N) NxN scipy.sparse.csr_matrix
, a każda rzadka macierz ma zestaw N elementów. Chcę dodać wszystkie te macierze, aby uzyskać regularną tablicę NxN. (N jest rzędu 1000). Rozmieszczenie niezerowych elementów w macierzach jest takie, że wynikowa suma z pewnością nie jest rzadka (właściwie nie ma już zerowych elementów).Efektywnie gromadzi kolekcję rzadkich macierzy scipy
W tej chwili jestem po prostu robi
reduce(lambda x,y: x+y,[m.toarray() for m in my_sparse_matrices])
który działa, ale jest nieco powolny: oczywiście ogromna ilość bezcelowym przetwarzania zer, które się tam dzieje jest absolutnie przerażające.
Czy istnieje lepszy sposób? Nie ma nic oczywistego w docs.
Aktualizacja: zgodnie z sugestią użytkownika 545424, wypróbowałem alternatywny schemat sumowania rzadkich macierzy, a także sumowania rzadkich macierzy na gęstej macierzy. Poniższy kod pokazuje wszystkie podejścia do uruchomienia w porównywalnym czasie (Python 2.6.6 na amd64 Debian/Squeeze na quad-core i7)
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
i wylogowuje
plus_dense : 1.368s
plus_sparse : 1.405s
sum_dense : 1.368s
sum_sparse : 1.406s
sum_combo : 1.039s
choć można dostać jeden podejście lub inne, aby wyjść z wyprzedzeniem przez współczynnik 2 lub więcej, bawiąc się z parametrami N, S, D ... ale nic takiego jak poprawa wielkości magii, którą byś oczekiwał patrząc na liczbę zerową, powinno to być możliwym do pominięcia.
Ah, doskonale! Jest to rodzaj wydajnego algorytmu, którego oczekiwałbym; tylko szkoda, że nie wydaje się, że jest już dostarczony jako jeszcze bardziej efektywny "wbudowany". Wypróbuje to wkrótce ... – timday
Tak, zależy trochę od gęstości, ale poprawa szybkości X10 jest typowa dla tego rodzaju numerów, które mnie interesują. – timday
Niesamowite. Właśnie stosowałem ten sam wzorzec w kilku innych miejscach, w których mam rzadko spotykane interakcje - zazwyczaj typu produktów typu dot - i za każdym razem uzyskuję znaczne przyspieszenia (x2-x3). – timday