2016-07-01 24 views
2

I haben Arrays e, (Form q durch l) f (Form n durch l) und w (Form n durch l), und ich möchte ein Array erstellen M wo M[s,i,j] = np.sum(w[s, :] * e[i, :] * e[j, :]) und ein Array F, wobei F[s,j] = np.sum(w[s, :] * f[s, :] * e[j, :]).numpy: Rundsenden in mehrere Skalarprodukte und Inversen

Beide sind einfach genug, zum Beispiel durch das Durchschleifen von Elementen von M, aber ich möchte effizienter sein (meine realen Daten hat so etwas wie 1M Einträge der Länge 5k). Für F kann ich F = np.inner(w * f, e) verwenden (was ich verifiziert habe, erzeugt die gleiche Antwort wie die Schleife). M ist schwieriger, so der erste Schritt ist, durch Dimension Null von mit einem Listenverständnis zu durchlaufen, sagen, dass M = np.stack([np.inner(r[:] * e, e) for r in w]) (Ich habe verifiziert, das funktioniert auch das gleiche wie die Schleife). np.inner() nimmt keine Achsenargumente, deshalb ist es mir nicht klar, wie man den Arrays sagt, dass sie nur über alle Zeilen von w senden sollen.

Schließlich muss ich Elemente M und F verwenden, um eine Matrix A zu erstellen, wo A[s,i] = np.sum(np.linalg.inv(M[s, :, :])[i, :] * F[i, :]). Das sieht auch innerlich-isch aus, aber das Nehmen vieler individueller Inverses ist zeitaufwendig. Gibt es also eine Möglichkeit, Inverses von Slices zu berechnen, ohne Looping?

sind einige Testwerte in meine Arrays wie folgt:

e = array([[-0.9840087 , -0.17812043], 
      [ 0.17812043, -0.9840087 ]]) 

w = array([[ 1.12545297e+01, 1.48690140e+02], 
      [ 7.30718244e+00, 4.07840612e+02], 
      [ 2.62753065e+02, 2.27085711e+02], 
      [ 1.53045364e+01, 5.63025281e+02], 
      [ 8.00555079e+00, 2.16207407e+02], 
      [ 1.54070190e+01, 1.87213209e+06], 
      [ 2.71802081e+01, 1.06392902e+02], 
      [ 3.46300255e+01, 1.29404438e+03], 
      [ 7.77638140e+00, 4.18759293e+03], 
      [ 1.12874849e+01, 5.75023379e+02]]) 

f = array([[ 0.48907404, 0.06111084], 
      [-0.21899297, -0.02207311], 
      [ 0.58688524, 0.05156326], 
      [ 0.57407751, 0.10004592], 
      [ 0.94172351, 0.03895357], 
      [-0.7489003 , -0.08911183], 
      [-0.7043736 , -0.19014227], 
      [ 0.58950925, 0.16587887], 
      [-0.35557142, -0.14530267], 
      [ 0.24548714, 0.03221844]]) 
+1

In 'M [s, i, j] = np.sum (w [s] * e [i] * e [j])' Was ist die Summe? Ich sehe 'i, j, s' auf beiden Seiten. Ist es "(w [s, k] * e [i, k] * e [j, k]). Summe (Achse = k)"? – hpaulj

+2

'np.einsum' ist ein schnelles und einfaches Werkzeug für diese Art von Produkten. Die 's, i, j' Gleichungen schreiben sich fast selbst. – hpaulj

+0

Zeilen von 'w',' f' und 'e' sind length-'l' Vektoren, also wird das elementweise Produkt der drei über seine einzige Achse summiert – DathosPachy

Antwort

3
M[s,i,j] = np.sum(w[s, :] * e[i, :] * e[j, :]) 

übersetzt

M = np.einsum('sk,ik,jk->sij',w,e,e) 

und

F[s,j] = np.sum(w[s, :] * f[s, :] * e[j, :]) 
F = np.einsum('sk,sk,jk->sj', w, f, e) 

ich diese mit Ihren Proben nicht getestet , aber die Übersetzung ist einfach genug.

Bei wirklich großen Arrays müssen Sie die Ausdrücke möglicherweise in einzelne Teile zerlegen. Bei 4 Iterationsvariablen kann der gesamte Iterationsraum sehr groß sein. Aber zuerst, sehen Sie, ob diese Ausdrücke mit bescheidenen Arrays arbeiten.

Was

A[s,i] = np.sum(np.linalg.inv(M[s, :, :])[i, :] * F[i, :]) 

I sieht aus wie np.linalg.inv(M) Werke, die s Durchführung i x i Umkehrungen

Wenn ja, dann

IM = np.linalg.inv(M) 
A = np.einsum('skm,ik,im->si', IM, F) 

Ich bin hier mehr zu raten.

Auch hier kann die Dimension zu groß werden, aber versuchen Sie es zuerst klein.

Typischerweise lineare Gleichung Lösungen werden über direkte Umkehrungen zu empfehlen, so etwas wie

A = F/M 
    A = np.linalg.solve(M, F) 

da Sie wahrscheinlich A so dass [email protected]=F (@ Matrixprodukt) möchten. Aber ich bin in diesen Dingen etwas eingerostet. Überprüfen Sie auch tensorsolve und tensorinv.

+0

'A = np.einsum ('skm, ik, im> SI', IM, F)' hat zu viele Indizes, aber 'A = np.linalg.solve (M, F)' erzeugt ein Array mit dem richtigen Dimensionen, das ist die halbe Miete. – DathosPachy

+0

Ist 'sij, ij-> si' besser? – hpaulj

+0

Nein, diese Indexanpassung verursacht einen Fehler beim erneuten Senden des Operanden '[original-> remapped]: (50,2,2) -> (50,2,2) (50,2) -> (50,2) '. Mit der Implementierung "np.linalg.solve()" erzeugt diese Methode jedoch die gleiche Antwort wie "f.dot (e.T)", wenn "w" überall eins ist. Dies ist das erwartete Verhalten, also bin ich mir ziemlich sicher, dass es funktioniert. – DathosPachy