Ich habe einen Satz von 2000 trainierten zufälligen Regressionsbäumen (von scikit lernen, Random Forest Regressor mit n_estimators=1
). Das parallele Trainieren der Bäume (50 Kerne) auf einem großen Datensatz (~ 100000 * 700000 = 70 GB @ 8-Bit) mit multiprocessing
und gemeinsamem Speicher funktioniert wie ein Zauber. Beachten Sie, dass ich die integrierte Multicore-Unterstützung von RF nicht verwende, da ich zuvor die Feature-Auswahl durchführe.
Das Problem: Wenn ich eine große Matrix (~ 20000 * 700000) parallel teste, habe ich immer keinen Speicher mehr (ich habe Zugriff auf einen Server mit 500 GB RAM).
Meine Strategie besteht darin, die Testmatrix im Speicher zu haben und sie unter allen Prozessen zu teilen. Laut einer Aussage eines der Entwickler der Speicherbedarf für das Testen ist 2 * n_jobs * sizeof (X), und in meinem Fall ist ein weiterer Faktor von * 4 relevant, da die 8-Bit-Matrixeinträge innerhalb von RF intern float32 sind.
Nach Zahlen, ich denke zum Testen brauche ich:
14GB, um die Testmatrix im Speicher zu halten + 50 (= n_jobs) * 20000 (n_samples) * 700 (= n_features) * 4 (Upcasting zu floaten) * 2 Bytes = 14 GB + 5.6 gb = ~ 21 GB Speicher.
Aber es geht immer um mehrere hundert GB. Was fehlt mir hier? (Ich bin auf der neuesten Version von scikit-learn, also sollten die alten Speicherprobleme ausgebügelt werden)
Eine Beobachtung:
Die Speicherauslastung eines einzelnen Kerns zum Testen schwankt zwischen 30 und 100 GB (gemessen in free
)
Mein Code:
%Vor% Bearbeiten:
eine weitere Beobachtung:
Beim Chunking der Testdaten läuft das Programm reibungslos mit stark reduzierter Speicherauslastung. Das habe ich benutzt, um das Programm laufen zu lassen.
Code-Snippet für die aktualisierte Funktion predTree
:
Ich bin mir nicht sicher, ob das Speicherproblem nicht mit der Verwendung von itertools.izip
in args = itertools.izip(models, features_idx)
zusammenhängt, was die Erstellung von Kopien des Iterators zusammen mit seinen Argumenten über alle Threads hinweg auslösen könnte. Hast du versucht, einfach zip
zu benutzen?
Eine andere Hypothese könnte eine ineffiziente Garbage Collection sein - nicht ausgelöst, wenn Sie sie benötigen. Ich würde prüfen, ob das Ausführen von gc.collect()
vor model.predict
in predTree
nicht hilft.
Es gibt auch einen dritten möglichen Grund (wahrscheinlich der glaubwürdigste). Lassen Sie mich Python-FAQ zu Wie verwaltet Python den Speicher? :
nennenIn aktuellen Versionen von CPython wird jede neue Zuweisung zu x innerhalb der Schleife die zuvor zugewiesene Ressource freigeben.
In Ihrer Chunked-Funktion machen Sie genau das - weisen Sie sie wiederholt pred_chunked
zu.
Tags und Links python memory-management scikit-learn random-forest python-multiprocessing