2017-09-21 2 views
2

I haben die folgende Gleichung:numpy Vektorisierung anstelle von loop

enter image description here

wobei v, mu sind | R^3 ist, wobei Sigma ist | R^(3x3) und wo das Ergebnis ist ein Skalarwert . Die Umsetzung dieser in numpy ist kein Problem:

result = np.transpose(v - mu) @ Sigma_inv @ (v - mu) 

Jetzt habe ich eine Reihe von V-Vektoren (nennen wir sie V \ in | R^3XN) und ich würde wie die obige Gleichung in einer vektorisierten Weise auszuführen so dass, wie ein Ergebnis ich einen neuen Vektor Ergebnis \ in | R^1xn erhalten.

# pseudocode 
Result = np.zeros((n, 1)) 
for i,v in V: 
    Result[i,:] = np.transpose(v - mu) @ Sigma_inv @ (v - mu) 

Ich sah np.vectorize aber die Dokumentation schlägt vor, dass seine genauso wie alle Einträge Schleifen über die ich lieber tun würde, nicht zu tun. Was wäre eine elegante vektorisierte Lösung?

Als ein Seitenknoten: n könnte ziemlich groß sein und eine | R^nxn Matrix wird sicherlich nicht in meinen Speicher passen!

edit: Arbeitscodebeispiel

import numpy as np 

S = np.array([[1, 2], [3,4]]) 
V = np.array([[10, 11, 12, 13, 14, 15],[20, 21, 22, 23, 24, 25]]) 

Res = np.zeros((V.shape[1], 1)) 
for i in range(V.shape[1]): 
    v = np.transpose(np.atleast_2d(V[:,i])) 
    Res[i,:] = (np.transpose(v) @ S @ v)[0][0] 

print(Res) 
+0

Es wäre einfacher, wenn Sie ein minimales Arbeits Beispiel dafür, was bieten möchten Sie erreichen möchten, auch wenn Schleifen (zB einschließlich 'import' Aussagen und Definitionen aller verwendeten Symbole). – norok2

+0

True: Ich habe ein minimales Beispiel hinzugefügt – juqa

+5

Ich würde in 'np.einsum' suchen, obwohl ich glaube, dass es eine der kryptischsten Funktion in' numpy' ist, kann es genau das sein, was Sie wollen. – norok2

Antwort

4

eine Kombination von matrix-multiplication Verwendung und np.einsum -

np.einsum('ij,ij->j',V,S.dot(V)) 
+0

Sie brauchen wahrscheinlich am Ende eine Umformung, die dem MWE entspricht, aber ansonsten ist das hervorragend! – norok2

2

macht diese Arbeit für Sie?

res = np.diag(V.T @ S @ V).reshape(-1, 1) 

Es scheint das gleiche Ergebnis zu liefern, wie Sie wollen.

import numpy as np 

S = np.array([[1, 2], [3,4]]) 
V = np.array([[10, 11, 12, 13, 14, 15],[20, 21, 22, 23, 24, 25]]) 

Res = np.zeros((V.shape[1], 1)) 
for i in range(V.shape[1]): 
    v = np.transpose(np.atleast_2d(V[:,i])) 
    Res[i,:] = (np.transpose(v) @ S @ v)[0][0] 

res = np.diag(V.T @ S @ V).reshape(-1, 1) 

print(np.all(np.isclose(Res, res))) 
# output: True 

Obwohl es wahrscheinlich eine speichereffizientere Lösung mit np.einsum gibt.

+1

danke für die Hinweise! Das Problem mit Ihrer Lösung ist, dass "n" in meiner Anwendung ziemlich groß ist, so dass eine Matrix R^{n x n} definitiv nicht in den Speicher passt. – juqa

+0

Die Lösung von @Divarak ist dem überlegen. – norok2

2

ist hier eine einfache Lösung:

import numpy as np 

S = np.array([[1, 2], [3,4]]) 
V = np.array([[10, 11, 12, 13, 14, 15],[20, 21, 22, 23, 24, 25]]) 

Res = np.sum((V.T @ S) * V.T, axis=1) 
+1

Mein Problem war, dass V.T @ S @ V zu groß ist, um in den Speicher zu passen, wie es sein wird | R^{n x n} – juqa

+1

@juqa Ja, ich habe die Antwort geändert, nur n x 2-Arrays zu verwenden. Es ist im Wesentlichen dasselbe wie Divakars Antwort, obwohl einsum vielleicht schneller ist als Multiplikation und Summe. – jdehesa

+1

Danke, ich bewertete beide Lösungen für einen Vektor mit 5.000.000 Einträgen und Ihre Vermutung war richtig: einsum nahm ~ 100ms, während Ihre Lösung ~ 150ms (Benchmarked über mehrere Iterationen). – juqa

0

Dies sind Multiplikationen von Matrix/Vektor-Stacks. numpy.matmul kann das tun, nachdem S und V in die richtige Form zu bringen:

S = S[np.newaxis, :, :] 
VT = V.T[:, np.newaxis, :] 
V = VT.transpose(0, 2, 1)  

tmp = np.matmul(S, V) 
Res = np.matmul(VT, tmp) 

print(Res) 
#[[[2700]] 
# [[3040]] 
# [[3400]] 
# [[3780]] 
# [[4180]] 
# [[4600]]] 
Verwandte Themen