[FIXED] wie man numpy-ähnliche Vektorisierung richtig verwendet, um die komplexe Zustandsauswertung in pandas dataframe apply-Funktionen zu beschleunigen

Ausgabe

Numpy/Pandas sind berühmt für ihre zugrunde liegende Beschleunigung, dh Vektorisierung.

Bedingungsauswertung sind allgemeine Ausdrücke, die überall in Codes vorkommen.

Bei applyintuitiver Verwendung der Pandas-Datenrahmenfunktion scheint die Zustandsbewertung jedoch sehr langsam zu sein.

Ein Beispiel für meinen applyCode sieht so aus:

 def condition_eval(df):
        x=df['x']
        a=df['a']
        b=df['b']
        if x <= a:
            d = round((x-a)/0.01)-1
            if d <- 10:
                d = -10
        elif x >= b:
            d = round((x-b)/0.01)+1
            if d > 10:
                d = 10
        else:
            d = 0 
        return d
df['eval_result'] = df.apply(condition_eval, axis=1)

Die Eigenschaften solcher Probleme könnten sein:

  1. Das Ergebnis kann nur mit seinen eigenen Zeilendaten und immer mit mehreren Spalten berechnet werden.
  2. Jede Zeile hat denselben Berechnungsalgorithmus.
  3. der Algorithmus kann komplexe bedingte Verzweigungen enthalten.

Was ist die beste Vorgehensweise in numpy/pandas, um solche Probleme zu lösen?


Noch ein paar Gedanken.

Einer der Gründe, warum die Vektorisierungsbeschleunigung meiner Meinung nach effektiv sein kann, liegt darin, dass die zugrunde liegende CPU über eine Art Vektoranweisungen (z. B. SIMD, Intel avx) verfügt, die auf der Wahrheit beruhen, dass die Rechenanweisungen ein deterministisches Verhalten haben, dh egal wie Die Eingabedaten sind, das Ergebnis könnte nach einer festen Anzahl von CPU-Zyklen erfasst werden. Daher ist die Parallelisierung solcher Operationen einfach.

Die Ausführung von Zweigen in der CPU ist jedoch viel komplizierter. Erstens haben unterschiedliche Zweige derselben Bedingungsauswertung unterschiedliche Ausführungspfade und können daher zu unterschiedlichen CPU-Zyklen führen. Moderne CPUs nutzen sogar viele Tricks wie die Verzweigungsvorhersage, die mehr Unsicherheiten erzeugen.

Ich frage mich also, ob und wie Pandas versuchen, solche Operationen zur Auswertung von Vektorbedingungen zu beschleunigen, und ob sie eine bessere Methode sind, um an solchen Rechenlasten zu arbeiten.

Lösung

Das sollte äquivalent sein:

import pandas as pd
import numpy as np

def get_eval_result(df):
    conditions = (
        df.x.le(df.a),
        df.x.gt(df.b),
    )
    choices = (
        np.where((d := df.x.sub(df.a).div(0.01).round().sub(1)).lt(-10), -10, d),
        np.where((d := df.x.sub(df.b).div(0.01).round().add(1)).gt(10), 10, d), 
    )
    return np.select(conditions, choices, 0)

df = df.assign(eval_result=get_eval_result)

Meine Antwort berechnet im Grunde die Ergebnisse jeder Verzweigung und verwendet dann die numpy-Syntax, um anzugeben, welche dieser Ergebnisse verwendet werden sollen. Dies könnte leicht optimiert werden, aber da es eine rein vektorisierte Funktion verwendet, sollte es viel schneller sein als die Verwendung von .apply.


Beantwortet von –
BeRT2me


Antwort geprüft von –
Mary Flores (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like