Эффективное накопление набора разреженных scipy-матриц

У меня есть набор из 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])

который работает, но немного медленно :, конечно, количество бессмысленной обработки нулей, происходящее там, просто ужасно.

Есть ли способ лучше ? В документах для меня нет ничего очевидного.

Обновление:по предложению пользователя 545424 я попробовал альтернативную схему суммирования разреженных матриц, а также суммирования разреженных матриц на плотную матрицу. В приведенном ниже коде показаны все подходы для запуска за сравнимое время (Python 2.6.6 на AMD64 Debian/Squeeze на четырехъядерном -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

и выходит из системы

plus_dense      :  1.368s
plus_sparse     :  1.405s
sum_dense       :  1.368s
sum_sparse      :  1.406s
sum_combo       :  1.039s

хотя вы можете получить тот или иной подход, чтобы выйти вперед примерно в 2 раза, возившись с параметрами N, S, D... но ничего похожего на улучшение порядка величины, которое вы надеетесь увидеть, рассматривая число нулевых добавлений должна быть возможность пропустить.

7
задан timday 29 June 2012 в 13:46
поделиться