2013-01-24 12 views
8

Ich habe eine Reihe von dünn besetzten Matrizen, die mit booleschen Werten gefüllt sind, für die ich logische Operationen ausführen muss (meistens elementweises ODER).Boolesche Operationen auf scipy.sparse-Matrizen

wie in numpy, Summieren Matrizen mit dtype ‚Bool‘ = gibt das Element weise oder aber es ist eine unangenehme Nebenwirkung:

>>> 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> 

Der Datentyp ‚int8‘ geändert wird, was bewirkt, Probleme für zukünftige Operationen.

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

Aber ich habe den Eindruck, dass dies alles Typänderung eine Performance-Einbußen führen würde: Dies könnte mit den Worten herumgesprochen werden.

Warum unterscheidet sich der dtype des Ergebnisses von den Operanden?
Und gibt es eine bessere Möglichkeit, logische Operationen auf dünn besetzten Matrizen in Python zu tun?

Antwort

5

Logische Operationen werden für dünn besetzte Matrizen nicht unterstützt, aber die Konvertierung zurück zu einem "Bool" ist nicht allzu teuer. Eigentlich, wenn LIL Format Matrizen verwenden, kann die Umwandlung erscheinen negativ Zeit in Anspruch nehmen wegen Leistungsschwankungen:

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 

Sie haben vielleicht bemerkt, dass Ihre LIL Matrizen zu CSR-Format konvertiert wurden, bevor sie zusammen Zugabe, Blick auf die Rückkehr Format. Wenn Sie bereits CSR-Format waren mit zu beginnen, dann wird die Umwandlung Aufwand bemerkbar:

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 (und CSC) Matrizen haben ein data Attribut, das ein 1D-Array ist, dass die tatsächlichen Nicht-Null-Einträge hält der Sparse-Matrix, so dass die Kosten der Neufassung Ihrer Sparse-Matrix von der Anzahl der Nicht-Null-Einträge Ihrer Matrix abhängen, nicht von ihrer Größe:

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