Kumulative Addition / Multiplikation in NumPy

8

Haben Sie einen relativ einfachen Block von Code, der zwei Arrays durchläuft, multipliziert und kumulativ addiert:

%Vor%

Gibt es eine Möglichkeit, dies ohne Iteration zu tun? Ich stelle mir vor, dass cumsum / cumprod verwendet werden könnte, aber ich habe Probleme herauszufinden, wie. Wenn Sie Schritt für Schritt herausfinden, was passiert, sieht es so aus:

%Vor%

Zur Klärung bearbeiten: Bin an der Liste (oder dem Array) c interessiert.

    
triphook 09.12.2015, 15:34
quelle

4 Antworten

4

In jeder Iteration haben Sie -

%Vor%

Also im Wesentlichen -

%Vor%

d. -

%Vor%

Wenn Sie nun diese Formel verwenden, wenn Sie die Ausdrücke für bis n = 2 cases aufschreiben, hätten Sie -

  

d [1] = d [0] * b [0] + K [0]

     

d [2] = d [0] * b [0] * b [1] + K [0] * b [1] + K [1]

     

d [3] = d [0] * b [0] * b [1] * b [2] + K [0] * b [1] * b [2] + K [1] * b [ 2] + K [2]

%Vor%

Sie würden also umgekehrtes cumprood von b benötigen, elementweise Multiplikation mit K array durchführen. Um schließlich c zu erhalten, führen Sie cumsum aus, und da c vor dem Verkleinern um b gespeichert wird, müssen Sie die cumsum Version um das umgekehrte cumprod von b verkleinern.

Die endgültige Implementierung würde so aussehen -

%Vor%

Laufzeittests und Überprüfung der Ausgabe

Funktionsdefinitionen -

%Vor%

Laufzeiten und Überprüfung

Fall # 1: OP Beispielfall

%Vor%

Fall # 2: Großer Eingabefall

%Vor%

Bitte beachten Sie, dass für extrem große Input-Array-Fälle, wenn die b -Elemente so kleine Brüche sind, aufgrund von kumulativen Operationen die anfänglichen Zahlen von b_rev_cumprod als zeros ausgegeben werden, was in NaNs resultiert ursprüngliche Orte.

    
Divakar 09.12.2015, 19:07
quelle
3

Mal sehen, ob wir noch schneller werden können. Ich verlasse nun die reine Python-Welt und zeige, dass diese rein numerischen Probleme noch weiter optimiert werden können.

Die beiden Spieler sind @ Divakars schnelle vektorisierte Version:

%Vor%

und eine Cython-Version:

%Vor%

Die Cython-Version ist ungefähr 5x schneller als die vektorisierte Version:

%timeit vectorized_approach(a,b) - & gt; 10000 loops, best of 3: 43.4 µs per loop

%timeit cython_approach(a,b) - & gt; 100000 loops, best of 3: 7.7 µs per loop

Ein weiteres Plus der Cython-Version ist, dass es viel besser lesbar ist.

Der große Nachteil ist, dass Sie pure Python verlassen und abhängig von Ihrem Anwendungsfall ist das Kompilieren eines Erweiterungsmoduls möglicherweise keine Option für Sie.

    
cel 09.12.2015 21:27
quelle
2

Das hier funktioniert bei mir und ist vektorisiert

%Vor%

Ich stimme zu, es ist nicht leicht zu sehen, was los ist. Ihr Array c kann als eine Matrix-Vektor-Multiplikation b_prod_mat * a geschrieben werden, wobei a Ihr Array ist und b_prod_mat aus spezifischen Produkten von b besteht. Der Schwerpunkt liegt im Wesentlichen darin, b_prod_mat zu erstellen.

    
plonser 09.12.2015 16:26
quelle
1

Ich bin mir nicht sicher, ob das besser ist als eine for-Schleife, aber hier ist ein Weg:

%Vor%

Was es tut, ist die Linie einer großen Matrix A wie folgt erstellen:

%Vor%

Dann multiplizieren Sie einfach den Vektor a mit der Matrix A und Sie erhalten das erwartete Ergebnis.

    
Holt 09.12.2015 16:15
quelle