2014-07-19 20 views
8

Gegeben zwei MatrizenPython - Matrix äußere Produkt

A: m * r 
B: n * r 

Ich möchte eine andere Matrix C: m * n, wobei jeder Eintrag erzeugen C_ij eine Matrix durch das äußere Produkt von A_i und B_j berechnet wird.

Zum Beispiel

A: [[1, 2], 
    [3, 4]] 

B: [[3, 1], 
    [1, 2]] 

gibt

C: [[[3, 1], [[1 ,2], 
    [6, 2]], [2 ,4]], 
    [9, 3], [[3, 6], 
    [12,4]], [4, 8]]] 

ich es für Loops tun können, wie

for i in range (A.shape(0)): 
     for j in range (B.shape(0)): 
     C_ij = np.outer(A_i, B_j) 

Ich frage mich, ob es diese Berechnung zu tun, eine vektorisierte Weg ist um es zu beschleunigen?

+2

Haben Sie eine 4D wollen, '(m, n, r, r)' -Form Array, oder möchten Sie ein 2D wollen, '(m, n) '-shape Array von' Objekt' dtype wo jedes Element ein anderes Array ist? Ich würde dringend die erste Option empfehlen, aber Ihre Beschreibung klingt näher an der Sekunde. – user2357112

+0

Sorry für die Verwirrung, aber ich bevorzuge die erste, eine 4D '(m, n, r, r)' - Form-Array. –

Antwort

6
temp = numpy.multiply.outer(A, B) 
C = numpy.swapaxes(temp, 1, 2) 

NumPy ufuncs, wie multiply, haben eine outer Methode, die fast das tut, was Sie wollen. Folgendes ist:

erzeugt ein Ergebnis, so dass temp[a, b, c, d] == A[a, b] * B[c, d]. Sie wollen C[a, b, c, d] == A[a, c] * B[b, d]. Der swapaxes Aufruf ordnet temp neu an, um es in der Reihenfolge anzuordnen, die Sie möchten.

0

Verwendung numpy;

In [1]: import numpy as np 

In [2]: A = np.array([[1, 2], [3, 4]]) 

In [3]: B = np.array([[3, 1], [1, 2]]) 

In [4]: C = np.outer(A, B) 

In [5]: C 
Out[5]: 
array([[ 3, 1, 1, 2], 
     [ 6, 2, 2, 4], 
     [ 9, 3, 3, 6], 
     [12, 4, 4, 8]]) 

Sobald Sie das gewünschte Ergebnis haben, können Sie numpy.reshape() verwenden es zu formen in fast jede gewünschte Form;

In [6]: C.reshape([4,2,2]) 
Out[6]: 
array([[[ 3, 1], 
     [ 1, 2]], 

     [[ 6, 2], 
     [ 2, 4]], 

     [[ 9, 3], 
     [ 3, 6]], 

     [[12, 4], 
     [ 4, 8]]]) 
+0

Ich bin irgendwie überrascht, dass das optisch so nah dran ist, was das OP will, aber trotz der Ähnlichkeit ist es immer noch nicht ganz richtig. Wenn Sie das gewünschte Ergebnis als großes 2D-Gitter mit kleinen 2D-Gittern in den Zellen visualisieren, erhalten Sie das, wenn Sie alle kleinen Gitter an den Kanten zusammenkleben, um ein Gitter zu erhalten. – user2357112

+0

Ja, stimme mit dir überein. Vielleicht zuerst 'np.outer (A, B)' und dann in kleinere Gitter teilen? –

+0

Aber das wird ein anderes Ergebnis geben. Ich wollte, dass die inneren Matrizen "[[3, 1], [6, 2]]", "[[1, 2], [2, 4]]", [[9, 3], [12, 4]] 'und' [[3, 6], [4, 8]] '. –

13

Die Einstein-Notation dieses Problem drückt schön

In [85]: np.einsum('ac,bd->abcd',A,B) 
Out[85]: 
array([[[[ 3, 1], 
     [ 6, 2]], 

     [[ 1, 2], 
     [ 2, 4]]], 


     [[[ 9, 3], 
     [12, 4]], 

     [[ 3, 6], 
     [ 4, 8]]]]) 
+0

Mann, ich sollte diese Notation lernen. Jedes Mal, wenn jemand eine Antwort postet, ist es immer viel kürzer als das, was mir einfällt. Wahrscheinlich auch verständlicher, wenn Sie die Einstein-Summierungskonvention kennen. – user2357112