Forum: PC-Programmierung KI/Neuronales Netz soll "Splix" spielen lernen - welcher Ansatz?


von Afu (Gast)


Lesenswert?

Hallo zusammen,


tldr;  Ich suche Ideen, Ansätze und Google-Stichworte zu neuronalen 
Netzen und nicht-überwachtem Trainieren.



Mein Ziel ist es einen automatischen Spieler (Bot) zu programmieren, 
gegen den ich das Spiel Splix.io (http://www.splix.io) spielen kann. 
Splix.io ist kurzgesagt vergleichbar mit dem bekannten Spiel "Snake", 
nur ohne Früchte, dafür aber mit dem Ziel Flächen zu besetzen, die durch 
Umranden mit der Schlange erobert werden. Es dürfen viele Spieler 
gleichzeitig auf dem Spielfeld sein (Multiplayer; Multibots).


Da ich keine Strategie einprogrammieren möchte, soll sich mein Bot das 
Spielen selbst beibringen. Hierfür eignen sich ja neuronale Netze. Das 
meiste, was ich so gefunden haben, waren Netze mit Backpropagation als 
Trainingsart. Ich glaube das hilft mir nicht weiter, da ich ja keine 
Trainingsdaten mit Erwartungswerten liefern kann, auf die das Netz 
hintrainieren könnte.


Als Eingangsgröße ins neuronale Netz wollte ich ein "Pixelabbild" des 
Spiels verwenden (also so ca. 20x20Pixel). Als Ausgangsgröße erwarte ich 
eine dieser 3 Reaktionen: "links abbiegen", "rechts abbiegen", "nichts 
tun (=geradeaus weiterlaufen)".

=> 400 Eingangsneuronen, 1..2 hidden layers und der Ausgangslayer dann 
mit 3 Neuronen.


Ich kann aber nicht nach jedem Zug/Schritt schon bewerten 
("Fitnessfunktion"), ob die letzte Aktion gut oder schlecht war - weil 
das schlicht zu diesem Zeitpunkt noch nicht abschätzbar ist. Eigentlich 
müsste ich ca. 20..50 Aktionen/Schritte erstmal laufen lassen und dann 
erst bewerten. Macht man da so? Vermutlich gibt es aber aus den 3^50 
(=10^24) Möglichkeiten dann nur eine handvoll gute 
Abfolgen/Kombinationen...



Ok, angenommen das Problem der Bewertung sei gelöst (eine 
Fitnessfunktion sei verfügbar), wie trainiere ich dann die 
Kantengewichte und Biasse der Neuronen? Meiner Meinung nach bietet sich 
da ein genetischer/evolutionärer Ansatz an. D.h. ich beginne mit 
zufällig initialisiertem Netz und variiere die Kantengewichte 
evolutionär. Das kann ich mir noch so grob vorstellen. Aber dauert das 
dann nicht unendlich lange, bis da was gescheites rauskommt? Und wie 
kann ich steuern, dass da überhaupt irgendwas sinnvolles rauskommt?


In welchem Wertebereich muss ich dann die Kantengewichte variieren? Kann 
man das praktisch irgendwie eingrenzen? (Bei Backpropagation pendelt 
sich der Wert ja quasi von selbst ein, da ja immer Deltas aufaddiert 
werden und so die Abweichung zum Endwert immer kleiner wird; bei 
evolutionär/genetisch muss ich ja selbst den Bereich vorgeben). Liegen 
die Kantengewichte immer bei -1..+1? Wie groß darf der Bias werden?



Die ganzen Beispiele mit SuperMarI/O, Tetris, "Kreaturen lernen laufen" 
lassen sich damit meiner Meinung nach nicht vergleichen, weil diese 
unter einer volldeterministischen Umgebung ("alles ist in jeder 
Simulation immer gleich") ablaufen. Bei meinem Spiel treten ja 
unvorhersehbare Ereignisse/Störungen(?) durch menschliche Spieler ein - 
auf die soll das Netz ja gerade (auch) reagieren lernen.


Übrigens: Das ganze soll mit Javascript, d.h. NodeJS für den Server (und 
die Bots) und Spieler-Anbindung an Webbrowser (JS + p5.js) umgesetzt 
werden.

Ich möchte keinen Bot bauen, der sich mit Splix.io verbindet und dort 
mitspielt, sondern auf meinen eigenen "Splix"-Server (der läuft schon) 
antreten lassen.


Freue mich über Stichworte, Links oder Hinweise, die mir sagen, wie man 
das eigentlich macht... :-)


Danke.

von Noch nicht Rentner (Gast)


Lesenswert?

Tja. ich wuerd einmal etwas herumspielen, und auf eine Idee zum Lernen 
warten. Irgendwie muss ja ein Feedback irgendwo her kommen. 
Wahrscheinlich kommt von selbst nichts. Denn fuer jede Entscheidung muss 
ja eine Bewerten da sein...
Probier's doch mal mit einem normalen Systen.

von Reinforcement Learning (Gast)


Lesenswert?

Der eigentliche Ansatz bei solchen Problemen/Spielen ist, anstatt 
neuronale Netze sog. Reinforcement Learning einzusetzen. Es gibt etliche 
Beispiele, wo man 2D-Spiele mit RL-Methoden "gelöst" hat, Snake, Mario, 
einige Atari-Spiele, Backgammon usw.

Deshalb versuche mal eher in Richtung Reinforcement Learning zu gehen 
anstatt neuronale Netze. Denn so wie du das Spiel beschreibst, klingt es 
nach den klassischen Voraussetzungen für das Reinforcement Learning: man 
hat einen Agenten (Spielfigur), seine Umgebung (Spielfeld), eine Menge 
von Aktionen (Spielzügen: gerade aus, hoch, runter, links, rechts) mit 
denen der Agent mit seiner Umgebung interagiert.
Was dir noch fehlen sind eine sog. Belohnungsfunktion und eine Codierung 
der Zustände des Spielfelds.
Das Ziel ist es, eine Strategie/Vorgehensweise (sog. policy) zu 
entwickeln/erlernen, die die Gesamtbelohnung maximiert, wobei sich diese 
aus der Summe der einzelnen Belohnungen zusammensetzt. Die policy gibt 
an, wann, d.h. in welchem Zustand man welchen Spielzug machen sollte.

Die Belohnungsfunktion bewertet jeden Spielzug/Aktion. Eine einfache 
Belohnungsfunktion wäre zB wenn "nichts passiert" gibt die 
Belohnungsfunktion eine 0, wenn ein Gebiet erorbert wird dann liefert 
sie eine positive Zahl x, wenn man Gebiete verliert dann eine negative 
Zahl y. Die Zaheln x und y könntest du mit der Größe der Gebiete 
korrelieren.
Ziel ist es, die Gesamtbelohnung zu maximieren, wobei sich diese aus der 
Summe der einzelnen Belohnungen zusammensetzt.

Was problematischer wird, ist die Codierung der Zustände des Spielfelds. 
Denn nach jedem Zug ändert sich der Zustand und die Anzahl der Zustände 
ist riesig und man kann die Zustände nicht a priori bestimmen. D.h. man 
müsste die Zustände approximieren.
Auf die Schnelle ist mir nichts eingefallen, wie man die Zustände bzw 
ihre Approximation modellieren kann.
Auf ein ähnliches Problem (Approximation der Zustände) stößt du bei 
Snake auch. In dieser pdf wird deren Approximation vorgestellt
http://cs229.stanford.edu/proj2016spr/report/060.pdf

Was splix komplexer macht, ist, dass ein bereits besetztes Gebiet wieder 
zurückerobert werden kann. Wie das Spiel aber genau funktioniert, habe 
ich auf die Schnelle nicht verstanden.

Vielleicht hilft dir der Ansatz trotzdem.
Wie du schon festgestellt hast, ist die Aufgabe nicht so einfach.

von c-hater (Gast)


Lesenswert?

Afu schrieb:

> Da ich keine Strategie einprogrammieren möchte, soll sich mein Bot das
> Spielen selbst beibringen. Hierfür eignen sich ja neuronale Netze.

Ja, aber der Rechenaufwand, bist diese KI irgendwas sinnvolles liefert, 
ist enorm.

Vergleiche mit einem Menschen: Bis der sich wie ein Erwachsener 
verhalten kann, muß er etliche Jahre zuerst intensivst gehätschelt 
werden und dabei laufend auf die Schnauze fallen.

Im weiteren Verlauf nimmt dann zwar die Notwendigkeit zur Hätschelung 
immer weiter ab, die Notwendigkeit, dauernd auf die Schnauze zu fallen, 
bleibt aber bestehen. Ohne das: kein Lernfortschritt. D.h.: scheinbarer 
Mißerfolg ist immer vor allem eins: ein kleiner Schritt in die richtige 
Richtung. Wenn er denn zum Lernen verwendet wird...

Übertragen auf dein konkretes Problem läuft das ungefähr so:

Die "Hätschelphase": da bringst du dem System erstmal bei, was 
eigentlich das Optimierungsziel ist. Das kann NICHT automatisch 
erfolgen. Das Netz hat NIX, nichtmal die bedingten Reflexe und 
instinktiven Verhaltensweisen, mit denen ein Mensch praktischerweise 
bereits geboren wird und auf die sein Lernen aufbauen kann. Das ist ein 
sehr großes (und bisher für den allgemeinen Fall ungelöstes) Problem 
jeglicher KI!

Erst die zweite Phase ist dann recht gut automatisierbar, aber auch 
nicht so einfach, wie du dir das vorstellst. Das Kernproblem hast du 
immerhin schon erkannt: Erst nach vielen Einzelentscheidungen wird der 
Erfolg der Gesamtstrategie überhaupt erst messbar. Das Problem ist nun: 
Wie kriege ich heraus, welche Einzelentscheidung(en) in dieser Historie 
Scheisse war? Antwort: nur dadurch, daß die Alternativen durchgespielt 
werden. Sprich: ein exponentielles Problem mit dem Potential, etliche 
Großrechner jahrelang zu beschäftigen...

Und selbst dann, wenn das alles jederzeit zu einem schicken und überaus 
erfolgreichen Spiel in der Trainingsmenge führt, schützt es die KI nicht 
davor, bei einem bisher unbekannten Zug des "Gegners" erneut furchtbar 
auf die Schnauze zu fallen...

So ist das nunmal mit der Intelligenz (ganz egal, ob künstlich oder 
natürlich)...

von Afu (Gast)


Lesenswert?

Reinforcement Learning schrieb:
> anstatt neuronale Netze sog. Reinforcement Learning einzusetzen.
Durch deinen Hinweis bin ich dem Thema mal näher nachgegangen.
Ich habe nach ein paar Stunden Youtube-Vorlesungen, jetzt auch eine 
grobe Vorstellung von Reinforcement Learning (RL) insbesondere mit dem 
model-free Ansatz.
Und das Beste ist, man kann den Lernfortschritt selbst noch 
beobachten/einschätzen und die internen Größen verstehen. Ganz im 
Gegensatz zu den unverstehbaren Kantengewichten bei den NNs.

> Was dir noch fehlen sind eine sog. Belohnungsfunktion
Das müsste doch einfach der Punktestand sein (Anzahl der eroberten 
Zellen). Ich muss ja nicht jeden Zug einzeln belohnen. Eine Belohnung 
am Ende reicht aus. Das propagiert sich dann durch das Verfahren auf 
umgekehrtem Wege zurück bis zum aktuellen Zustand.


> und eine Codierung der Zustände des Spielfelds.
Da war die erste Idee mit den 400 Eingangsgrößen eine ganz schlechte, 
weil die Anzahl der Zustände/Kombinationen unüberschaubar wird.

Ich denke/hoffe, dass man als Eingangsgrößen auf ganz wenige Größen 
zurückgreifen kann. Also nicht die vielen Pixelzustände 
auswerten/lernen, sondern daraus schon vorher abstraktere Kenngrößen 
("features") ermitteln, wie z.B. "Abstand zum Gegner", "Größe des (bald) 
eingekesselten Bereichs" usw.. Der Vorteil ist, dass es dann auch egal 
ist, ob sich das dann links oben im Feld oder links unten oder sonstwo 
abspielt.
Hier beschreibt der Dozent, wie man bei der Berechnung der Q-Values 
vorgeht: https://www.youtube.com/watch?v=yNeSFbE1jdY (ab Minute 45).
Ich glaube, dass das ein geeigneter Ansatz wäre - wenn(!) ich den dann 
mal besser überblicke. :-)

> Was splix komplexer macht, ist, dass ein bereits besetztes Gebiet wieder
> zurückerobert werden kann.
Das will ich zunächst mal alles ignorieren. Vermutlich muss man 
verschiedene Spielphasen (neue Zellen erobern, eigene Zellen 
verteidigen, Gegner angreifen...) separat betrachten/lernen und dann im 
geeigneten Moment zwischen den einzeln gelernten Aktionen umschalten. 
Aber das ist ferne Zukunftsmusik. Ich bin schon zufrieden, wenn mein Bot 
Zellen einkesselt, ohne jedesmal selbst sofort gefressen zu werden.

> Vielleicht hilft dir der Ansatz trotzdem.
ja, sehr. Genau das hatte ich mir mit meinem Ausgangspost erhofft - ein 
Schubs in die richtige Richtung. Danke! :-)

von H-G S. (haenschen)


Lesenswert?

Ich würde die KI so programmieren, dass sie genau das gleiche macht was 
der menschliche Spieler bzw. sein Gehirn machen würde.
Dazu muss man sich irgendwie genau beobachten wie man das selber spielt.

Das wird aber dann wohl auf normalen Code hinausgehen, das scheinbar 
komplexe neuronale Zeug interessiert mich aber doch irgendwie ...

von Reinforcement Learning (Gast)


Lesenswert?

Afu schrieb:
> Reinforcement Learning schrieb:
>> anstatt neuronale Netze sog. Reinforcement Learning einzusetzen.
> Durch deinen Hinweis bin ich dem Thema mal näher nachgegangen.
> Ich habe nach ein paar Stunden Youtube-Vorlesungen, jetzt auch eine
> grobe Vorstellung von Reinforcement Learning (RL) insbesondere mit dem
> model-free Ansatz.
> Und das Beste ist, man kann den Lernfortschritt selbst noch
> beobachten/einschätzen und die internen Größen verstehen. Ganz im
> Gegensatz zu den unverstehbaren Kantengewichten bei den NNs.

Wie du festgestellt hast, ist der model-free Ansatz der 
vielsprechendste. Und der Q-Learning-Algo beim RL ist von der Bedeutung 
her mit dem Backpropagation-Algorithmus bei kNN vergleichbar.


>> Was dir noch fehlen sind eine sog. Belohnungsfunktion
> Das müsste doch einfach der Punktestand sein (Anzahl der eroberten
> Zellen). Ich muss ja nicht jeden Zug einzeln belohnen. Eine Belohnung
> am Ende reicht aus. Das propagiert sich dann durch das Verfahren auf
> umgekehrtem Wege zurück bis zum aktuellen Zustand.

Naja du benötigst schon eine Belohnungsfunktion (reward) für jede 
Aktion/Zug. Der Reward ist ja das Kernstück von RL (daher kommt auch der 
Name reinforcement). In jeder Update-Regel (sei es das Update für Q oder 
auch für die Gewichte beim Approximieren der Q-Funktion mittels linearer 
Kombination von feature-Funktionen) kommt der Reward (es ist dieses 
kleine r in den Formeln) vor.


>> und eine Codierung der Zustände des Spielfelds.
> Da war die erste Idee mit den 400 Eingangsgrößen eine ganz schlechte,
> weil die Anzahl der Zustände/Kombinationen unüberschaubar wird.
>
> Ich denke/hoffe, dass man als Eingangsgrößen auf ganz wenige Größen
> zurückgreifen kann. Also nicht die vielen Pixelzustände
> auswerten/lernen, sondern daraus schon vorher abstraktere Kenngrößen
> ("features") ermitteln, wie z.B. "Abstand zum Gegner", "Größe des (bald)
> eingekesselten Bereichs" usw.. Der Vorteil ist, dass es dann auch egal
> ist, ob sich das dann links oben im Feld oder links unten oder sonstwo
> abspielt.
> Hier beschreibt der Dozent, wie man bei der Berechnung der Q-Values
> vorgeht: Youtube-Video "Lecture 11: Reinforcement Learning II" (ab
> Minute 45).
> Ich glaube, dass das ein geeigneter Ansatz wäre - wenn(!) ich den dann
> mal besser überblicke. :-)

Die feature-extraction ist der Schlüssel und auch das schwierigste bei 
ML-Algorithmen.
Ich weiß nicht, wie viel Background du im Bereich der kNN (und allgemein 
mit ML) hast, aber die Bestimmung der sog feature-Vektoren (bei kNN auch 
meist einfach als Input-Vektoren bezeichnet) ist der 
wichtigste/herausfordernste Teil, damit das neuronale Netz gute 
Ergebnisse liefert.
Wenn man eine Lösung für ein spezifisches Problem sucht, dann versucht 
man meistens, manuell feature-Vektoren bzw. beim RL feature-Funktionen 
zu erstellen/definieren.
Möchte man jedoch ein wenig verallgemeinern, dann versucht man ein 
Modell zu entwickeln, welches diese feature-extraction automatisch 
vornimmt. Das ist auch die Essenz von sog. Deep-Learning. Im Bereich der 
Bilderkennung zB erkennen die sog. Hidden-Layers eines deep neural 
networks (sog. convolutional neural networks) sog basis-features wie 
z.B. Kanten.
Das Deep-Learning-Konzept kann man auch bei RL einsetzen, um die 
Q-Funktion zu approximieren, in dem Fall wird die Q-Funktion nicht mehr 
durch Linearkombination von Gewichten und feature-Funktionen 
approximiert, sondern es wird nichtlinear approximiert, wobei die 
approximierende nichtlineare Funktion das deepe-neuronale Netz ist.

>> Was splix komplexer macht, ist, dass ein bereits besetztes Gebiet wieder
>> zurückerobert werden kann.
> Das will ich zunächst mal alles ignorieren. Vermutlich muss man
> verschiedene Spielphasen (neue Zellen erobern, eigene Zellen
> verteidigen, Gegner angreifen...) separat betrachten/lernen und dann im
> geeigneten Moment zwischen den einzeln gelernten Aktionen umschalten.
> Aber das ist ferne Zukunftsmusik. Ich bin schon zufrieden, wenn mein Bot
> Zellen einkesselt, ohne jedesmal selbst sofort gefressen zu werden.
>
>> Vielleicht hilft dir der Ansatz trotzdem.
> ja, sehr. Genau das hatte ich mir mit meinem Ausgangspost erhofft - ein
> Schubs in die richtige Richtung. Danke! :-)

Naja ich würde an deiner Stelle zunächst mal ein einfacheres Problem 
lösen um mit den Algorithmen vertraut zu werden. Ein Beispiel, das du 
durch den klassischen Q-Learning-Algorithmus lösen kannst, ist 
Tic-Tac-Toe (du hast weniger als 9^3 Zustände, d.h. deine Q-Werte kannst 
du in einem Array speichern) - auch die graphische Implementierung wäre 
recht einfach. Danach könntest du, wie in dem Video, Pacman nehmen - 
hierzu gibt es eine freie Python-Implementierung (einfach nach Python 
Pacman googlen).

von Reinforcement Learning (Gast)


Lesenswert?

Reinforcement Learning schrieb:
> Tic-Tac-Toe (du hast weniger als 9^3 Zustände

Kurzer Nachtrag:
Meine Abschätzung war total daneben. Gemeint war eig, dass du deutlich 
weniger als 3^9=19683 Zustände hast. Du hast sogar weniger als 6050 
Zustände. Nichtsdestotrotz kannst du die Q-Werte in einem Array 
speichern.

von Afu (Gast)


Lesenswert?

Kurzer Zwischenstand:
Nachdem ich jetzt einige dieser Featurefunktionen aufgestellt habe, und 
deren Gewichtungsfaktoren einfach pi*Daumen vorgegeben habe, bewegt sich 
der Bot schon recht "interessant" übers Feld. Von Lernen kann noch keine 
Rede sein, weil ich das programmatische Variieren/Anpassen der 
Gewichtungsfaktoren noch nicht ganz durchschaut habe. Naja, gebe ich 
diese halt von Hand vor. Ist dann zwar nix mit Lernen, aber der Bot 
läuft trotzdem (wenn ich die Gewichte sinnvoll einstelle).

Eine Featurefunktion z.B. bewertet die Entfernung zur Homebase. Eine 
andere ermittelt die Anzahl der potentiell einzukesselnden Zellen. 
Weitere kümmern sich darum, dass er keine 180°-Kehren macht (wenig 
sinnvoll, da vom Server sowieso ignoriert), und sich selbst nicht in die 
Spur beißt. Wieder andere belohnen das Weglaufen von der Homebase oder 
verhindern das Überfahren der Spielfeldbegrenzung.

Läßt man den Bot jetzt loslaufen passieren höchst interessante Dinge. 
Ich hatte zunächst erwartet, dass er etwas in den freien Raum reinläuft 
(wird ja belohnt), dann irgendwie abbiegt und wieder zurück zur Homebase 
läuft (nämlich dann, wenn der erwartete Zellenzuwachs die Belohnung fürs 
Rauslaufen übersteigt).
Naja, was ist statt dessen passiert? Er ist genau eine Zelle weit von 
der Homebase weggelaufen und hat die (anfangs quadratische) Homebase im 
Abstand von einer Zelle einmal umrundet. Naja, das gibt gefahrlos eine 
große Fläche, die er da einkesseln kann, aber viele Punkte bekommt er am 
Ende ja nicht, weil die meisten eingekesselten Zellen ja schon 
eingefärbt waren und somit nicht neu/doppelt gezählt werden. Hm, ich 
hatte ja nicht gesagt (bzw. in die Featurefunktion gepackt), dass nur 
neu eingefärbte Zellen zählen, also eindeutig mein Fehler - aber 
"kreativ" fand ich den Bot schon. :-)

Wie gesagt alles ohne echtes ML. Dennoch entwickelt das Teil auch so ein 
"Eigenleben". Ich könnte dem Bot stundenlang zuschauen. Und da die 
Rechnungen ja alle ganz gut nachvollziehbar sind, läßt sich seine 
Reaktion auch immer schön erklären. Noch(!) habe ich das Feintunen der 
Gewichte im Griff. Aber so wirklich sinnvoll spielt er noch nicht und 
ich befürchte, dass mir der Überblick/Vorstellungskraft langsam verloren 
geht. Muss ich mich eben doch nochmal ausführlicher mit der Lernerei 
beschäftigen.

Ich bin mal gespannt, wie das noch weitergeht...

von Basti (Gast)


Lesenswert?

Hallo,

ich mach es mal kurz:

Wenn es zu viele Spielstandsmöglichkeiten gibt und deiner RAM knapp 
werden könnte, macht das Q-Learning mit KNNs Sinn! Ansonsten kann der 
Q-Learner auch alle Kombinationen abspeichern.

Evolution und Fitnessfunktion sind nette Spielzeuge. Q-Learning ist aber 
viel mächtiger. Bleib also dabei.

Das ein Spielzug erst nach 20 Zügen ordentlich bewertet werden kann ist 
kein Problem.

Lies unbedingt dieses Beispiel:
http://outlace.com/Reinforcement-Learning-Part-3/
... dann sollte eigentlich alles klar sein. Ich fande es jedenfalls sehr 
erleuchtend.

VG

Basti

von Basti (Gast)


Lesenswert?

Vielleicht noch das Video als grobe Übersicht:

https://youtu.be/mGYU5t8MO7s

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.