
- Diesmal ist das Spiel "Snake" ausgewählt.
- Eine Bibliothek für das Go-Netzwerk wurde erstellt.
- Das Prinzip des Lernens, abhängig von der "Tiefe" des Gedächtnisses, wird gefunden.
- Für das Spiel wird ein Server zwischen Entwicklern geschrieben.
Die Essenz des Spiels
Vielleicht erinnern sich viele Leute an das Spiel "Snake", das eine Standardanwendung auf Nokia-Handys war. Seine Essenz ist folgende: Eine Schlange bewegt sich über das Feld, die abnimmt, wenn sie keine Nahrung findet, oder zunimmt, wenn sie findet. Wenn eine Schlange gegen ein Hindernis stößt, stirbt sie.
Ich habe die Regeln ein wenig geändert: Die Schlange stirbt nicht, wenn sie abstürzt, sondern stoppt einfach und nimmt weiter ab. Zusätzlich kann die Schlange in zwei Hälften geteilt werden. Wenn die Schlange noch eine Zelle im Körper hat und in 10 Zügen keine Nahrung finden konnte, stirbt sie und verwandelt sich in Nahrung.
Wir werden den Bot trainieren, der die Schlange kontrolliert. Wenn sich die Schlange teilt, erhält der Bot eine weitere Schlange unter Kontrolle, die sich ebenfalls teilen kann.
Grundlage ist das Experiment mit den Schlangen des Cyberbiologen Mikhail Tsarkov.
Neuronales Netz
Im Rahmen der Aufgabe wurde eine Bibliothek für das neuronale Netz in der Sprache Go geschrieben. Ich studiere die Arbeit des neuronalen Netzwerks und verwende das
foo52ru-Videotagebuch und das Buch von Tariq Rashid - Erstellen Sie ein neuronales Netzwerk.
Die
CreateLayer(L []int)
Funktion
CreateLayer(L []int)
erstellt ein neuronales Netzwerk mit der erforderlichen Anzahl von Ebenen und deren Größe. Auf jeder Schicht mit Ausnahme der letzten wird ein Verschiebungsneuron hinzugefügt. Wir geben Daten an die erste Ebene weiter und erhalten das Ergebnis aus der letzten Ebene.
Ein Beispiel:
CreateLayer([]int{9, 57, 3, 1})
Hier haben wir ein neuronales Netzwerk mit neun Eingängen erstellt. Zwei versteckte Schichten von 57 und 3 Neuronen und ein Neuron, um das Ergebnis zu erhalten. Verschiebungsneuronen werden automatisch durch das Plus zu den von uns festgelegten hinzugefügt.
In der Bibliothek können Sie:
- Senden Sie Daten an den Netzwerkeingang.
- Erhalten Sie das Ergebnis, indem Sie auf die letzte Ebene zugreifen.
- Fragen Sie nach den richtigen Antworten und führen Sie das Training durch, indem Sie das Gewicht der Krawatten anpassen.
Die anfänglichen Bindungsgewichte werden durch Zufallswerte nahe Null angegeben. Zur Aktivierung haben wir die Logistikfunktion verwendet.
Bot Training
Der Bot erhält am Eingang ein 9x9 Quadratmeter großes Feld, in dessen Mitte sich der Kopf einer Schlange befindet. Dementsprechend wird unser neuronales Netzwerk 81 Eingänge haben. Die Reihenfolge der dem Eingang zugeführten Zellen spielt keine Rolle. Während des Trainings wird das Netzwerk selbst herausfinden, wo sich das befindet.
Um Hindernisse und andere Schlangen anzuzeigen, habe ich Werte von -1 bis 0 (nicht inklusive) verwendet. Leere Zellen wurden mit einem Wert von 0,01 und Nahrung mit 0,99 bezeichnet.
Am Ausgang des neuronalen Netzwerks wurden 5 Neuronen für Aktionen verwendet:
- bewege dich entlang der X-Achse nach links;
- rechts;
- die y-Achse hinauf;
- unten;
- in zwei Hälften geteilt.
Die Bewegung des Bots wurde vom Neuron bestimmt, das am Ausgang den größten Wert hat.
Schritt 0. Randomizer
Zunächst wurde ein Bot-Randomizer erstellt. Also rufe ich einen Bot an, der zufällig geht. Es ist notwendig, die Wirksamkeit des neuronalen Netzwerks zu überprüfen. Bei richtigem Training sollte ein neuronales Netzwerk es leicht schlagen können.
Schritt 1. Lernen ohne Gedächtnis
Nach jeder Bewegung passen wir die Gewichte der Bindungen für das Ausgangsneuron an, das den höchsten Wert anzeigt. Wir berühren keine anderen Ausgangsneuronen.
Die folgenden Werte wurden für das Training angegeben:
- gefundenes Essen: 0,99
- machte eine Bewegung in jede Richtung: 0,5
- eine Körperzelle verloren, ohne Nahrung zu finden (dafür werden 10 Züge gegeben): 0,2
- steht still (stößt auf ein Hindernis oder steckt fest): 0.1
- Stillstand mit einer Körperzelle: 0,01
Nach einem solchen Training begannen die Bots schnell, den Randomizer zu schlagen, und ich stellte die Aufgabe: Bots zu erstellen, die diese schlagen.
A / B-Tests
Um diese Aufgabe zu erfüllen, wurde ein Programm erstellt, das Schlangen je nach Konfiguration des neuronalen Netzwerks in zwei Teile unterteilt. Auf dem Feld wurden 20 Schlangen jeder Konfiguration hergestellt.
Alle von einem Bot kontrollierten Schlangen hatten das gleiche neuronale Netzwerk. Je mehr Schlangen in seinem Management waren und je häufiger sie unterschiedlichen Aufgaben gegenüberstanden, desto schneller fand das Training statt. Wenn zum Beispiel eine Schlange gelernt hat, Deadlocks zu vermeiden oder sich in zwei Hälften zu teilen, wenn sie eine Sackgasse erreicht hat, haben automatisch alle Schlangen dieses Bots diese Fähigkeiten erworben.
Durch Ändern der Konfiguration des neuronalen Netzwerks können Sie gute Ergebnisse erzielen, dies reicht jedoch nicht aus. Um den Algorithmus weiter zu verbessern, habe ich beschlossen, Speicher für mehrere Züge zu verwenden.
Schritt 2. Lernen mit dem Gedächtnis
Für jeden Bot habe ich einen Speicher für 8 Züge erstellt. Der Status des Feldes und die vom Bot vorgeschlagene Bewegung wurden im Speicher aufgezeichnet. Danach habe ich die Gewichte für alle acht Zustände vor dem Umzug angepasst. Dafür habe ich einen einzigen Korrekturfaktor verwendet, unabhängig von der Fahrtiefe. Somit führte jede Bewegung zur Einstellung der Gewichte nicht nur einmal, sondern acht.
Wie erwartet schlugen Memory Bots schnell Bots, die ohne Speicher trainierten.
Schritt 3. Verringern Sie den Korrekturkoeffizienten in Abhängigkeit von der Speichertiefe
Als nächstes habe ich versucht, den Korrekturfaktor abhängig von der Speichertiefe zu reduzieren. Für den letzten Schritt wurde der größte Koeffizient zum Einstellen der Gewichte festgelegt. In dem vorhergehenden Verlauf nahm der Korrekturfaktor im gesamten Speicher ab und so weiter.

Eine lineare Abnahme des Korrekturkoeffizienten in Abhängigkeit von der Speichertiefe führte dazu, dass neue Bots diejenigen zu schlagen begannen, die einen einzelnen Koeffizienten verwendeten.
Als nächstes habe ich versucht, die logarithmische Reduktion des Korrekturfaktors zu verwenden. Der Koeffizient verringerte sich je nach Speichertiefe für jede Bewegung um die Hälfte. Daher hatten Bewegungen, die "vor langer Zeit" ausgeführt wurden, einen wesentlich geringeren Einfluss auf das Lernen als "frische" Bewegungen.
Bots mit einer logarithmischen Verringerung des Korrekturkoeffizienten begannen, Bots mit einer linearen Beziehung zu besiegen.
Server für Bots
Wie sich herausstellte, kann die Verbesserung des "Pumping" -Bots unendlich sein. Und ich habe beschlossen, einen Server zu erstellen, auf dem Entwickler (unabhängig von der Programmiersprache) miteinander konkurrieren können, um einen effektiven Algorithmus für Snakes zu schreiben.
Protokoll
Zur Autorisierung müssen Sie eine GET-Anfrage an das Verzeichnis "game" senden und einen Benutzernamen angeben, zum Beispiel:
.../game/?user=masterdak
Anstelle von "..." müssen Sie die Standortadresse und den Port angeben, an dem der Server bereitgestellt wird.
Als Nächstes gibt der Server eine Antwort im JSON-Format aus, die die Sitzung angibt:
{"answer":"Hellow, masterdak!","session":"f4f559d1d2ed97e0616023fb4a84f984"}
Danach können Sie eine Karte und die Koordinaten der Schlange auf dem Feld anfordern und der Anfrage eine Sitzung hinzufügen:
.../game/?user=masterdak&session=f4f559d1d2ed97e0616023fb4a84f984
Der Server zeigt ungefähr Folgendes an:
{ "answer": "Sent game data.", "data": { "area": [ ["... ..."] ], "snakes": [ { "num": 0, "body": [ { "x": 19, "y": 24 }, { "x": 19, "y": 24 }, { "x": 19, "y": 24 } ], "energe": 4, "dead": false } ] } }
Das
Bereichsfeld zeigt den Status des Spielfelds mit den folgenden Werten an:
0
Darauf folgt ein Array mit Schlangen, die Sie kontrollieren können.
Der Körper der Schlange befindet sich im
Körperarray . Wie Sie sehen können, befindet sich der gesamte Körper der Schlange (einschließlich des Kopfes - der ersten Zelle) am Anfang an derselben Position "x": 19, "y": 24. Dies liegt daran, dass zu Beginn des Spiels die Schlangen aus dem Loch kommen, das von einer Zelle auf dem Spielfeld definiert wird . Außerdem sind die Koordinaten von Körper und Kopf unterschiedlich.
Die folgenden Strukturen (ein Beispiel in Go) definieren alle Serverantwortoptionen:
type respData struct { Answer string Session string Data struct { Area [][]int Snakes []struct { Num int Body []Cell Energe int Dead bool } } } type Cell struct { X int Y int }
Als nächstes müssen Sie die Bewegung senden, die die Schlange ausführt, indem Sie der GET-Anforderung eine
Bewegung hinzufügen, zum Beispiel:
...&move=u
u - bedeutet Befehl auf;
d - runter;
l - links;
r - rechts;
/ - halbieren.
Der Befehl für mehrere Schlangen (zum Beispiel für sieben) sieht folgendermaßen aus:
...&move=ud/urld
Ein Charakter - ein Team. Die Antwort sollte einen Befehl für alle Schlangen enthalten, die unter Ihrer Kontrolle stehen. Andernfalls erhalten einige Schlangen möglicherweise keinen Befehl und setzen die alte Aktion fort.
Das Feld wird in Intervallen von 150 ms aktualisiert. Wenn innerhalb von 60 Sekunden kein Befehl empfangen wird, schließt der Server die Verbindung.
Referenzen
Senden Sie mir eine Nachricht, um den Habraeffekt zu vermeiden. Als Antwort sende ich die IP-Adresse meines Servers. Oder Sie können Ihren Server mithilfe des Quellcodes des Programms bereitstellen.
Ich bin weder Spezialist für Programmierung noch für neuronale Netze. Daher kann ich Fehler machen. Ich verbreite den Code "wie er ist". Ich würde mich freuen, wenn erfahrene Entwickler die gemachten Fehler zeigen würden.
- Bibliothek für das neuronale Netz zusammen mit dem Spiel "Tic Tac Toe"
- Snake Master - Server
- Schlangenmeister - Bot
- Snakeworld2
UPDLaden Sie
die Server-IP-Adresse vorübergehend hoch. Jetzt wird dort nur noch ein Bot Randomizer (SnakeBot0) gestartet. Ich hoffe der Server stürzt nicht so schnell ab.