2016-06-16 11 views
3

Ich habe ein genetisches Programmiersystem in Python erstellt, habe aber Probleme mit Speichergrenzen. Das Problem besteht darin, alle Personen in meiner Population im Speicher zu speichern. Momentan speichere ich alle Individuen im Speicher und reproduziere dann die Population der nächsten Generation, die dann im Speicher gespeichert wird. Das bedeutet, dass ich zwei Populationen im Wert von Individuen habe, die im Gedächtnis geladen sind. Nach einigen Tests habe ich festgestellt, dass ich die standardmäßige Anwendungsspeichergröße von 2 GB für Windows ziemlich schnell überschreite.Speichern von Objekten in einer Datei statt im Speicher

Derzeit schreibe ich die einzelnen Bäume der gesamten Bevölkerung in eine Datei, die ich dann laden und die Bevölkerung neu erstellen kann, wenn ich will. Was ich in Betracht gezogen habe, ist, anstatt alle Individuen in den Speicher geladen zu haben, auf individuelle Informationen zuzugreifen, indem ich die Person aus der Akte ziehe und nur diese einzelne Person instanziiere. Nach meinem Verständnis der Readline-Funktionalität von Python sollte nur eine einzige Zeile aus der Datei gleichzeitig geladen werden, und nicht die gesamte Datei. Wenn ich das täte, würde ich nur in der Lage sein, die Individuen zu speichern, die ich gerade manipuliere.

Meine Frage ist, gibt es ein Unterstreichungs-Problem mit dem, was ich gerade nicht sehe? Ich verstehe, dass, weil ich mit Daten auf der Festplatte statt im Speicher zu tun habe, meine Leistung einen Schlag bekommen wird, aber für diese Situation ist Speicher wichtiger als Geschwindigkeit. Ich möchte auch nicht die zugewiesenen 2 GB Speicher für Python-Programme erhöhen.

Danke!

+0

Gibt es einen Grund, warum Sie nicht über eine Datenbank nachgedacht haben? –

+0

Das Ziehen eines einzelnen Datensatzes aus der Datei bedeutet das Durchlesen der Datei, bis Sie den richtigen Datensatz gefunden haben. Ich empfehle dringend, zu einem Computer mit einer modernen 64-Bit-Umgebung und einer angemessenen Menge an Arbeitsspeicher zu wechseln. Wenn Sie Ihr Programm trotzdem optimieren möchten, geben Sie bitte [MCVE] (http://stackoverflow.com/help/mcve) an. Wenn es derzeit funktioniert, sollten Sie stattdessen nach Code Review fragen. – TigerhawkT3

+0

@ IgnacioVazquez-Abrams Ich dachte darüber nach, aber nach jeder Generation werden mindestens 95% der Individuen in der Bevölkerung ersetzt. Es schien nicht so, als würde die Verwendung einer Datenbank die richtige Richtung sein, da Datensätze nur für eine sehr kurze Zeit bestehen bleiben. – Tory

Antwort

2

die RAM-Einschränkung gegeben, würde ich die Bevölkerung Modell zu Steady State von Generationswechsel.

Die Idee ist, iterativ ein oder zwei neue Kinder zu züchten, ihre Fitness zu bewerten und sie dann direkt in die Population selbst einzufügen, wobei einige bereits existierende Individuen getötet werden, um Platz für sie zu schaffen.

Steady State verwendet die Hälfte des Speichers eines traditionellen genetischen Algorithmus, weil es nur eine Population gleichzeitig gibt.

Ändern der Implementierung sollte nicht zu schwer sein, aber Sie müssen auf vorzeitige Konvergenz achten (d. H. Optimiert Parameter wie Mutationsrate, Turniergröße ...).

Die Insel Modell ist eine weitere/weitere Möglichkeit: population in getrennte Subpopulationen aufgebrochen wird (Demes). Demes schicken Individuen aneinander, um Nachrichten über neu entdeckte, passende Bereiche des Raums zu verbreiten.

Normalerweise ist es ein asynchronen Mechanismus, aber man könnte einen synchronen Algorithmus, Laden verwenden Demes eins nach dem anderen, mit einer großen Reduktion der benötigten Speicherressourcen.


Natürlich können Sie die Bevölkerung in eine Datei schreiben und Sie können nur die benötigten Personen laden. Wenn Sie diesen Ansatz wählen, ist es wahrscheinlich eine gute Idee, eine Hash-Signatur von Personen zu berechnen, um die Identifizierungs-/Ladegeschwindigkeit zu optimieren.

Trotzdem sollten Sie bedenken, dass Sie je nach Aufgabe, die Ihr GP-System ausführt, einen massiven Leistungseinbruch registrieren können.

+0

Ich denke, Steady-State könnte die Richtung, in die ich gehen werde. Also, weil Sie nicht wirklich Generationen haben, müssen Sie jedes Individuum als ihre Fitness berechnet haben oder nicht berechnet, und dann einmal pro Iterationsschleife berechnen die falsch markiert die Fitness der Person oder, sobald die Person der Bevölkerung hinzugefügt wird, ihre Fitness berechnen? – Tory

+0

@Tory Wenn Sie eine Form von Elitismus verwenden, benötigen Sie sofort die Fitness (Sie müssen die neue Person mit derjenigen vergleichen, die Sie ersetzen möchten). – manlio

0

Denken Sie daran, dass Sie, wenn Sie Steady State verwenden, eine Methode benötigen, um die Wahrscheinlichkeit zu erhöhen, dass die Stärksten sich kreuzen, um höher zu sein als die weniger fitten Individuen.

Ein paar zusätzliche Optionen, die Sie denken konnte, sind:

a) Verwendung SQLLite. (https://docs.python.org/2/library/sqlite3.html). Dies hätte alle Leistungsvorteile einer Datenbank (wahrscheinlich mehr) und die Einfachheit und Benutzerfreundlichkeit der Verwendung einer Datei.

b) Es gibt ein hybrides Nicht-Steady-State-Modell, das eine große, unbewertete Polulation, Größe M und ein "Survivor Set" der geeignetsten Individuen der Größe N erlaubt, wobei M >> N ist. Population ist eine Queue von Lösungsobjekten, aber SurvivorSet ist eine begrenzte Größe Heap von "EvaluatedSolutions" (eine mit Fitness ausgestattete Lösung). Also nehmen Sie weiterhin Lösungen aus der allgemeinen Bevölkerung, werten sie aus, legen sie dann in den EvaluatedSolution Heap (nach Fitness absteigend sortiert) und schneiden die Top N Elemente ab. Auf diese Weise bleibt Ihr Speicherverbrauch konstant, aber Sie haben das Konzept der Elites eingebaut. Dies ermöglicht auch, coole Tricks wie "Zucht" zu machen, indem nur die Elite als Zuchtpopulation verwendet wird.