2017-06-20 8 views
0

Ich habe eine dünne Matrix M und ein Array a von Standorten, wo ich M um eins erhöhen möchte. Dieses Array kann a Dubletten enthalten und immer dann, wenn ein Element n mal in a ist, würde Ich mag in Mn an der entsprechenden Position hinzuzufügen. Ich habe diese auf folgende Weise:Unerwartete Verhalten bei der Anpassung spärlich Matrix

from scipy import sparse as sp 
M = sp.csr_matrix((3, 4), dtype=float) 
M[[0,0,0,0,0], [0,1,0,1,0]] += 1 

Aber wenn ich diese laufen, M[0,0] nur um eins erhöht, ist es eine einfache Methode, um dies anzupassen?

+0

Bitte beachten Sie numpy die und scipy der docs zu lesen verstehe, was hier passiert. Die grundlegende Pipeline von Berechnungen (für einen vektorisierten Ansatz) könnte also wie folgt aussehen: A: Sortiere deine Orte (lex), B: erzeuge 1d-vec von Einsen, kombiniere Duples in A und summiere B parallel (Bs Dimension könnte abnehmen; einige Einträge können von 1 bis N wachsen, C: Fügen Sie diese B-Werte hinzu, indem Sie mit A indizieren. Ein viel einfacherer (schleifenbasierter Ansatz): greifen Sie einfach jeden Ort in einer Schleife und inkrementieren Sie (nacheinander). – sascha

+0

Okay, danke. So habe ich es gemacht, aber ich habe erwartet, dass es eine schnellere Methode geben würde. Ich komme von MATLAB, also erwarte ich immer, dass Matrix-Operationen schneller sind als Schleifen. – HolyMonk

+0

Ja in den meisten Fällen. Dann probiere einfach meinen ersten Ansatz (oder warte auf einige Experten, um etwas besseres zu präsentieren). – sascha

Antwort

0

Wie geht MATLAB damit um?

numpy hat eine besondere Funktion dieses wiederholte Index Fall zu behandeln, die add.at

Using ufunc.at on matrix

Dies hat für scipy.sparse nicht umgesetzt worden.

Da sparse Summen Koordinaten wiederholt, wenn von einem coo Format csr eine Umwandlung, vermute ich, dieses Problem in einer Weise gegossen werden könnte, der Vorteil, dass statt. In der Tat hat die csr Matrix eine M.sum_duplicates Methode.

Ich müsste herumspielen, um die Details zu erarbeiten.


In [876]: M = sparse.csr_matrix((3, 4), dtype=float) 
In [877]: M 
Out[877]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>' 
    with 0 stored elements in Compressed Sparse Row format> 

demonstriert die np.add.at Aktion:

In [878]: arr = M.A 
In [879]: arr[[0,0,0,0,0],[0,1,0,1,0]] += 1 
In [880]: arr 
Out[880]: 
array([[ 1., 1., 0., 0.], 
     [ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.]]) 

In [883]: arr = M.A 
In [884]: np.add.at(arr,[[0,0,0,0,0],[0,1,0,1,0]],1) 
In [885]: arr 
Out[885]: 
array([[ 3., 2., 0., 0.], 
     [ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.]]) 

zu M Hinzufügen erzeugt die gleiche Wirkung gepuffert - mit einer Warnung. Die Veränderung der Seltenheit einer Matrix ist relativ teuer.

In [886]: M[[0,0,0,0,0],[0,1,0,1,0]] += 1 
.... 
    SparseEfficiencyWarning) 
In [887]: M 
Out[887]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>' 
    with 2 stored elements in Compressed Sparse Row format> 
In [888]: M.A 
Out[888]: 
array([[ 1., 1., 0., 0.], 
     [ 0., 0., 0., 0.], 
     [ 0., 0., 0., 0.]]) 

Der richtige Weg, um diese zusätzlich zu tun ist, eine neue Sparse Matrix mit den Werten zu machen, die hinzugefügt werden müssen. Wir können die Vorteile aus der Tatsache ziehen, dass coo Stil Eingängen Summe mit umgewandelten Duplikaten zu csr:

In [895]: m = sparse.csr_matrix((np.ones(5,int),([0,0,0,0,0],[0,1,0,1,0])), shape=M.shape) 
In [896]: m 
Out[896]: 
<3x4 sparse matrix of type '<class 'numpy.int32'>' 
    with 2 stored elements in Compressed Sparse Row format> 
In [897]: m.A 
Out[897]: 
array([[3, 2, 0, 0], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0]], dtype=int32) 

jetzt können wir das Original und die neuen hinzufügen:

In [898]: M = sparse.csr_matrix((3, 4), dtype=float) 
In [899]: M+m 
Out[899]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>' 
    with 2 stored elements in Compressed Sparse Row format> 
Verwandte Themen