2013-01-24 20 views
8

Ho una serie di matrici sparse piene di valori booleani su cui ho bisogno di eseguire operazioni logiche su (principalmente OR per elementi).Operazioni booleane su matrici scipy.sparse

come in NumPy, sommando matrici con DTYPE = 'bool' dà l'elemento-saggio o, comunque c'è un brutto effetto collaterale:

>>> from scipy import sparse 
>>> [a,b] = [sparse.rand(5,5,density=0.1,format='lil').astype('bool') 
... for x in range(2)] 
>>> b 
<5x5 sparse matrix of type '<class 'numpy.bool_'>' 
    with 2 stored elements in LInked List format> 
>>> a+b 
<5x5 sparse matrix of type '<class 'numpy.int8'>' 
    with 4 stored elements in Compressed Sparse Row format> 

Il tipo di dati viene cambiato in 'int8', che provoca problemi per le operazioni future. Questo potrebbe essere ottenuto in giro con dicendo:

(a+b).astype('bool') 

Ma ho l'impressione che tutto questo tipo di cambiamento potrebbe causare un calo di prestazioni.

Perché il dtype del risultato è diverso dagli operandi?
E c'è un modo migliore per eseguire operazioni logiche su matrici sparse in python?

risposta

5

Le operazioni logiche non sono supportate per le matrici sparse, ma la conversione di nuovo in "bool" non è molto costosa. In realtà, se si utilizza matrici formato LIL, la conversione può apparire a prendere tempo negativo a causa di fluttuazioni delle prestazioni:

a = scipy.sparse.rand(10000, 10000, density=0.001, format='lil').astype('bool') 
b = scipy.sparse.rand(10000, 10000, density=0.001, format='lil').astype('bool') 

In [2]: %timeit a+b 
10 loops, best of 3: 61.2 ms per loop 

In [3]: %timeit (a+b).astype('bool') 
10 loops, best of 3: 60.4 ms per loop 

Avrete notato che i vostri matrici LIL sono stati convertiti in formato CSR prima di aggiungere insieme, guardano al ritorno formato. Se si era già stato utilizzando il formato CSR per cominciare, allora l'overhead conversione diventa più evidente:

In [14]: %timeit a+b 
100 loops, best of 3: 2.28 ms per loop 

In [15]: %timeit (a+b).astype(bool) 
100 loops, best of 3: 2.96 ms per loop 

CSR (e CSC) matrici hanno un attributo data che è un array 1D che contiene le voci non-zero attuale della matrice sparsa, quindi il costo di rifusione della matrice sparsa dipenderà dal numero di voci non zero della matrice, non dalle sue dimensioni:

a = scipy.sparse.rand(10000, 10000, density=0.0005, format='csr').astype('int8') 
b = scipy.sparse.rand(1000, 1000, density=0.5, format='csr').astype('int8') 

In [4]: %timeit a.astype('bool') # a is 10,000x10,000 with 50,000 non-zero entries 
10000 loops, best of 3: 93.3 us per loop 

In [5]: %timeit b.astype('bool') # b is 1,000x1,000 with 500,000 non-zero entries 
1000 loops, best of 3: 1.7 ms per loop 
Problemi correlati