4

Ich möchte das Element-weise äußere Produkt von zwei 2d-Arrays in numpy tun.numpy elementwise äußere Produkt

A.shape = (100, 3) # A numpy ndarray 
B.shape = (100, 5) # A numpy ndarray 

C = element_wise_outer_product(A, B) # A function that does the trick 
C.shape = (100, 3, 5) # This should be the result 
C[i] = np.outer(A[i], B[i]) # This should be the result 

Eine naive Implementierung kann Folgendes.

tmp = [] 
for i in range(len(A): 
    outer_product = np.outer(A[i], B[i]) 
    tmp.append(outer_product) 
C = np.array(tmp) 

Eine bessere Lösung, die vom Stapelüberlauf inspiriert ist.

Ich bin auf der Suche nach einer vektorisierten Implementierung, die die for-Schleife los wird. Hat jemand eine Idee? Vielen Dank!

+0

Für das, was es wert ist, 'np.multiply.outer (a, b)' ist anders als 'np.outer ', formgebend' 100, 3, 100, 5' – Eric

Antwort

7

Extend A und B zu 3D ihre ersten Achse ausgerichtet zu halten und die neuen Achsen entlang der dritten und zweiten jeweils mit None/np.newaxis einführt und dann miteinander multipliziert. Dies würde broadcasting für eine vektorisierte Lösung ins Spiel bringen.

Somit wäre eine Implementierung sein -

A[:,:,None]*B[:,None,:] 

Wir haben es ein bisschen für A ist durch die Verwendung ellipsis verkürzen könnte: :,: und überspringen die Auflistung der übrig gebliebenen letzten Achse mit B, wie so -

A[...,None]*B[:,None] 

Als ein weiterer vektorisierter Ansatz könnten wir auch np.einsum verwenden, was intuitiver sein könnte, sobald wir die String-Notation überwunden haben Syntax und betrachten diese Notationen Vertreter der Iteratoren beteiligt in einer naiven loopy Umsetzung, wie es zu sein -

np.einsum('ij,ik->ijk',A,B) 
+0

Oder 'np.einsum ('... j, ... k -> ... jk', A, B)' für mehr als 3 Dimensionen zu arbeiten – Eric

+0

Keine dieser Methoden ist schneller als eine Schleife. 'Einsum' benötigt 900ms für ein Array, wobei eine einfache' Schleife' 700ms dauert. 'A [:,:, None] * B [:, None,:]' ist ungefähr 800. – Swift

Verwandte Themen