2016-05-17 19 views
0

Ich muss zwei dünn besetzte Matrizen (elementweise) unterschiedlicher Größe multiplizieren. Hier sind die Matrizen:multiplizieren `csr` dünn besetzte Matrizen unterschiedlicher Größe python

matrix1 = (1, 2) 30.0 
(2, 3) 20.0 
(4, 5) 10.0 
(6, 7) 80 

matrix2 = (1, 2) 2.0 
(2, 3) 1.0 
(4, 5) 5.0 

Wie Sie sehen können, matrix1 größer als matrix2. Ich brauche sie so zu vermehren, dass die Elemente, die in matrix2 nicht vorhanden sind (in diesem Fall Elemente (6, 7) gleich bleiben Die Ausgabe, die ich brauche, ist wie folgt:.

final_matrix = (1, 2) 60.0 
(2, 3) 20.0 
(4, 5) 50.0 
(6, 7) 80 

Für die realen Daten, die ich arbeite mit die Matrizen sind sehr groß. Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

Dank!

+0

Die Matrizen müssen nicht so groß sein, wie Sie das Problem definiert haben ... einfach eine '1' setzen, wo Sie keinen passenden Eintrag in der zweiten Matrix haben. Um sie elementweise zu multiplizieren, müssen die Dimensionen der Ersatzmatrizen gleich sein. – gariepy

+0

Großartig, wie schlägst du vor, ich habe eine "1" überall, wo ich keinen passenden Eintrag habe? Denken Sie daran, dass meine Matrizen sehr groß sind - das Iterieren dauert lange. –

+0

Ich bin versucht, dies ein Duplikat Ihrer anderen Frage über das Hinzufügen von Matrizen unterschiedlicher Form zu nennen. Die gleichen Probleme und mögliche Lösungen gelten: http://stackoverflow.com/questions/37231163/adding-two-csc-sparse-matrices-of-different-shapes-in-python – hpaulj

Antwort

1

Für ein dichtes Array ist es relativ einfach, diese Art der Multiplikation durchzuführen. Und schnell, da Aufschneiden schnell

In [453]: x=np.arange(24).reshape(4,6) 
In [454]: y=np.arange(10,22).reshape(3,4) 

In [457]: x[:3,:4] *= y 

In [458]: x 
Out[458]: 
array([[ 0, 11, 24, 39, 4, 5], 
     [ 84, 105, 128, 153, 10, 11], 
     [216, 247, 280, 315, 16, 17], 
     [ 18, 19, 20, 21, 22, 23]]) 

Mit den spärlichen Mitteln

In [460]: xM=sparse.csr_matrix(x) 
In [462]: yM=sparse.csr_matrix(y) 

Geschnittene mehrfach funktioniert:

In [468]: z= xM[:3,:4].multiply(yM) # z.A matches the dense block 

Aber wir bekommen eine Warnung, wenn versucht wird, diesen Wert zuweisen zurück auf xM

In [469]: xM[:3,:4] = xM[:3,:4].multiply(yM) 
/usr/lib/python3/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient. 
    SparseEfficiencyWarning) 

In [471]: xL=sparse.lil_matrix(x) 
In [472]: yL=sparse.lil_matrix(y) 
In [475]: xL[:3,:4]=xL[:3,:4].multiply(yL) 

xL.multiply Code ist eigentlich: return self.tocsr().multiply(other)

Ich weiß nicht, welche Kombination von Formaten am effizientesten ist.

[Wir könnten die CSR-Sparsity-Warnung umgehen, indem wir erkennen, dass xM[:3,:4].multiply(yM) weniger, nicht mehr Elemente ungleich Null haben wird. Also könnten wir zumindest vorübergehend einige Werte von xM.data auf 0 setzen, ohne die anderen Attribute zu ändern. Wir können später mit eliminate_zeros aufzuräumen.]


Eine Alternative zur geschnitten Zuordnung, y auf die Größe des x zu erweitern ist, und die vollständige Multiplikation durchzuführen. In diesem Fall müssen wir y mit 1en auffüllen.

würde die dichte Version sein:

In [478]: z=np.ones_like(x) 
In [479]: z[:3,:4]=y 
In [480]: x*z 

Mit dünn besetzten Matrizen wir bei der erforderlichen Polsterung suchen. Wenn yM nur wenige Zeilen und/oder Spalten kleiner als xM ist, vermute ich, dass wir sparse.vstack und hstack effizient verwenden können. Wenn es viel Padding gibt, wird das Ergebnis viele von Null verschiedene Werte haben, also können wir auch das dichte z machen.

In [503]: zM = sparse.vstack((yM,np.ones((1,4),int))) 
In [504]: zM = sparse.hstack((zM,np.ones((4,2),int))) 

In [505]: zM.shape 
Out[505]: (4, 6) 

In [507]: zM.A 
Out[507]: 
array([[10, 11, 12, 13, 1, 1], 
     [14, 15, 16, 17, 1, 1], 
     [18, 19, 20, 21, 1, 1], 
     [ 1, 1, 1, 1, 1, 1]], dtype=int32) 

In [511]: xM.multiply(zM).A 
Out[511]: 
array([[ 0, 11, 24, 39, 4, 5], 
     [ 84, 105, 128, 153, 10, 11], 
     [216, 247, 280, 315, 16, 17], 
     [ 18, 19, 20, 21, 22, 23]], dtype=int32) 

Ein anderer Weg, dies mit yMsparse.bmat erweitert zu bauen, das eine neue Matrix aus Blöcken macht. bmat funktioniert durch Konstruieren coo formatieren Matrizen und verketten alle ihre row, col, data Attribute, und daraus eine neue Matrix.

Wie sich herausstellt vstack verwendet bmat

return bmat([[b] for b in blocks], format=format, dtype=dtype) 

Diese Konstrukte die gleiche 4x6-Matrix:

In [520]: zM = sparse.bmat([[yM, np.ones((3,2),int)], 
        [np.ones((1,4),int), np.ones((1,2),int)]]) 

=================

Eine andere Möglichkeit ist die Anpassung von @ Vadims dok Ansatz von sum Problem

https://stackoverflow.com/a/37241977/901925

Es ist iterativ und stark abhängig von der Anzahl der Nicht-Null-Elemente der kleineren Matrix - aber es ist ziemlich flexibel.

+0

Darüber hinaus muss das Auffüllen von "y" nicht alle 1s sein; nur 1s entspricht den Nicht-Null-Elementen von "x". – hpaulj

0

Es gibt wahrscheinlich einen pythonic Weg, dies zu tun, aber mathematisch, das ist ein ziemlich einfacher Ansatz.

from scipy.sparse import csc_matrix, lil_matrix, find 

## create example matrices, A, B, assume B has values that are not in A 
A = csc_matrix((5,5)) 
A[1,1] = 3.0 
A[2,2] = 2.0 
B = csc_matrix((5,5)) 
B[1,1] = 5.0 
B[2,2] = 10.0 
B[3,3] = 50.0 

C = lil_matrix((5,5)) ## C will be a modification of A; 
## more efficient to do this with lil_matrix than csc_matrix; 
## you can convert later if needed 

(I,J,V) = find(A) ## get nonzero indices of A 
(M,N,P) = find(B) ## get nonzero indices of B 
C[M,N] = 1.0 ## set all B-corresponding elements to 1.0 
C[I,J] = A[I,J] ## overwrite with corresponding elements in A 

D = C.multiply(B) ## EDIT: per hpaulj's suggestion, using multiply(), which works with most any sparse matrix type 
+0

Für 'csc'-Matrizen mit übereinstimmender Größe gibt es eine effiziente (kompilierte) Element-für-Element-Multiplikation. "A.mehr (B)". – hpaulj

Verwandte Themen