Download the joeBOT sources
Die kompletten Quellen des JoeBOT sind jetzt auch verfügbar
(c) Johannes Lampel 1999-2002
Für etwaige Weiterverwendungen dieses Textes setzen sich sie bitte mit mir via email in Kontakt..
Bücherlinks bei www.amazon.de | |||||||||||||||
| |||||||||||||||
| |||||||||||||||
The Game Programming Gems Series - gut aber teuer |
FriedrichSchiller-Gymnasium Preetz / Holst.
AmIhlsol 10-12
24211Preetz
Namedes Schülers :
JohannesLampel
Themader besonderen Lernleistung :
Einsatzvon Neuronalen Netzen in einem Bot für Counterstrike
BetreuendeLehrkraft :
FrauDr. E. Rabe
Terminder endgültigen Festlegung des Themas : Februar 2001
Terminder endgültigen Formulierung des Themas : 14. Nov. 2001
Abgabetermin: 16.Nov. 2001
Bewertung:
Info zum Titelbild:Das Bild ist entstanden, indem alle Gewichte der Neuronen einer SOM mit einem 2dimensionalen Eingabevektor während der Lernphase aufgezeichnet wurden. Die SOMsollte Eingaben lernen, die gleichmäßig über ein quadratisches Gebiet verteiltwaren. Die Kreuzform entstand durch einen topologischen Defekt. Das Bild wurdeim Nachhinein noch mit einem Bildbearbeitungsprogramm verändert.
Inhalt
2.1Prinzipieller Aufbau biologischer neuronaler Netze
2.2Prinzipieller Aufbau künstlicher neuronaler Netze
2.2.1Interne Funktionen eines Neurons
2.3 Lernen
2.3.1 Überwachtes Lernen (Supervised Learning)
2.3.2 BestärkendesLernen (Reinforcement Learning)
2.3.3Unüberwachtes Lernen (Unsupervised Learning)
2.4.3.1.Herleitung der Backpropagation Regel
2.4.3.3.Flat Spot Elimination
2.5 SOM(Self organizing map)
3.Prinzipieller Aufbau der Simulatoren
3.1.Simulator für Feedforward-Netze (LSNNSI)
4.Praktischer Einsatz der Neuronalen Netze im Bot
4.1 Aufgabendes neuronalen Netzes
4.2 Gewinnungder Trainingsdaten
4.3Technische Einzelheiten bei der Implementierung des Bots
B.1Quelltext des (Feedforward-) NN-Simulators
(Anmerkung: Seit dem Beginn meiner Arbeiten anmeinem Bot ist mittlerweile eine zweite und dritte Version der HPB-Templateerschienen. Mein Bot basiert auf der Version1 und ich beziehe mich in diesemText, wenn ich vom Templatecode spreche auf diese Version.)
Abbildung1 :Verschiedene Arten von Neuronen. Von links nach rechts: 1. Bipolare Neuronen,um Neuronen untereinander zu verbinden; 2. Unipolare Neuronen, die sensorischeDaten übermitteln; 3. Multipolares Neuron, z.B. bei der motorischenSignalweiterleitung zu finden; 4. Ein pyramidales Neuron, das bspw. im Gehirnzu finden ist.
KünstlicheNeuronen besitzen wie ihre biologischen Vorbilder einen oder mehrere ‚Eingänge’und einen ‚Ausgang’, zwischen denen eine meist einfache Verarbeitung desImpulse nach einfachen Regeln erfolgt.
Abbildung2 : Variablender Neuronen
|
| Formel 2.1 |
- Die binäre Aktivierung
- Sigmoide Aktivierungsfunktion
o
bzw.mit Temperatur-Parameter T
o
Diese Aktivierungsfunktion wird gerne in Zusammenhang mit dem LernverfahrenBackpropagation verwendet, da hier auch ein inaktives Neuron ( oi= -1) im Gegensatz zur logistischen Aktivierungsfunktion nicht 0 ist und somiteine in beide Richtungen Gewichtsänderung möglich ist.
Ineinigen Fällen wird aus simulationstechnischen Gründen der Schwellenwert durchein sogenanntes ‚on-Neuron’ ersetzt. Dieses besondere Neuron ist immeraktiviert und durch seine gewichteten und durch das Lernen veränderbarenVerbindungen zu jedem Neuron ein Ersatz für die expliziten, internenSchwellenwerte. Bei der Simulation müssen die Schwellenwerte nicht extraberechnet werden, sondern können zusammen mit den anderen Gewichten verändertwerden. Allerdings steht diesem Vorteil ein großer Nachteil gegenüber: Bei derVisualisierung der Netze werden diese leicht unübersichtlich.
Auchfür die Berechnung der Ausgabe kann es eine eigene Funktion geben, die allerdingsoft mit der Aktivierungsfunktion zusammengefasst wird.
|
| Formel 2.2 |
DiePropagierungsfunktion bezeichnet die Vorschrift, mit der die Netzeingabeweiterverarbeitet wird
|
| Formel 2.3 |
Abbildung3 : Einvollständig ebenenweise verbundenes 2-stufiges 5-7-5 Feedforward–Netz
- Direkte Rückkopplung
Durch die direkte Rückkopplung können sich die Neuronen selbst hemmen bzw.aktivieren und somit kleine Eingangssignale in bestimmten Bereichen verstärken.
- Indirekte Rückkopplung
Verbindungen von höheren Schichten zu niedrigeren können beispielsweise zurAufmerksamkeitssteuerung eingesetzt werden. Hierbei wird die ursprünglicheEingabe verarbeitet und mit einer Ausgabe assoziiert, die wieder dazu benutztwerden kann, bestimmte Eigenschaften der Eingabe besonders zu beachten.
- Rückkopplung innerhalb einer Schicht.(lateral feedback)
Die Rückkopplung innerhalb einer Schicht wird oft dann eingesetzt, wenn nur einNeuron in der gesamten Schicht aktiv sein soll. Um das zu erreichen, hemmenalle Neuronen alle anderen Neuronen und versuchen sich selbst noch weiter zuaktivieren. Das Neuron mit der ursprünglich höchsten Aktivierung bleibt am Endeals Gewinner, während alle anderen Neuronen nicht mehr aktiviert sind. Deshalbheißen solche Netztopologien auch winner-takes-all Netzwerke.
- Vollständig verbundene Netze
Bei vollständig verbundenen Netzen ist jedes Neuron mit jedem Neuron verbunden.Bekanntester Vertreter dieser Art sind die Hopfield-Netze, die beiOptimierungsproblemen wie dem Travelling-Salesman-Problem eingesetzt werdenkönnen.
- Präsentation der Eingabe durchentsprechende Aktivierung der Neuronen der Eingabeschicht
- Propagierung des Netzes, sodass eineAusgabe erzeugt wird
- Vergleich der Ausgabe mit dergewünschten Ausgabe
- Bei Netzen mit mehreren Schichten:Rückwärtspropagierung der Fehler der Ausgabeschicht zu Neuronen in verdecktenSchichten.
- Änderung der Gewichte, um den Fehler zuminimieren
Abbildung4 : Ein64-14-26 feedforward Netz, das ich mit Hilfe des überwachten LernverfahrensBackpropagation zur Erkennung von großen Druckbuchstaben verwendet habe. ( dieFarben der Verbindungen stellen das Gewicht, die der Neuronen derenSchwellenwert dar )
Beidiesem Lernverfahren wird dem Netz zusammen mit der Eingabe nicht der kompletteAusgabevektor, sondern nur wenige Informationen, richtig / falsch oder auch derGrad des Fehlers, präsentiert. Dieses Verfahren ist auch biologisch plausiblerals überwachtes Lernen, da Vorgänge wie ‚Erfolg’ oder ‚Misserfolg’ auch in derNatur zu finden sind. Allgemein ist dieses Verfahren jedoch sehr zeitaufwändig,da dem Netz nur wenige Informationen zur Verfügung stehen.
BeimUnüberwachten Lernen werden dem Netz eine Trainingsmenge von Eingabevektorenpräsentiert, die es ohne direkte Vorgaben von außen in Gruppen einteilt. Diebekanntesten Netze, die nach einem Unüberwachten Lernverfahren arbeiten, sinddie Selbstorganisierenden Karten (Self Organizing Maps).Bei SOM beeinflussen aktive Neuronen ihre räumlich nahen Nachbarneuronen undbewirken damit, dass sich ähnliche Muster an bestimmten Stellen ‚sammeln’,Gruppen bilden. Den SOMs ähnliche Strukturen wurden im visuellen Kortex vonSäugetieren gefunden, sodass diese Modelle auch biologisch plausibel sind. Diefür dieses Lernverfahren nötige Suche nach dem am stärksten aktivierten Neuronwird allerdings bei der Simulation fast immer durch eine einfache Maximumsucherealisiert, da ein rekurrentes Netz, das die gleiche Aufgabe erfüllen soll,immer mehr Zeit benötigt, einen stabilen Punkt zu erreichen, bzw. keinenfindet, also ständig oszilliert.
- Präsentation der Eingabe durchentsprechende Aktivierung der Eingabeneuronen
- Propagierung
- Suche nach dem am stärksten aktiviertenNeuron ( winner-takes-all)
- Änderung der Gewichte anhand derEntfernung vom zu aktualisierenden Neuron zum Gewinnerneuron
AlsFeedforward-Netze werden neuronale Netze bezeichnet, bei denen die Eingabe nur inRichtung der Ausgabeschicht propagiert wird.
h ist in den folgenden Fällen alsLernrate definiert, also eine Variable, die die Geschwindigkeit mit der dieGewichte verändert werden, angibt. Wird h zu klein gewählt, dauert dasTraining unnötig lange und es findet in lokalen Minima einen stabilen Punkt.Wird die Lernrate jedoch zu groß gewählt, kann es vorkommen, dass derLernvorgang nicht optimal verläuft.
Die Hebb-und Deltaregeln gelten nur für einstufige Netze.
DieHebbsche Lernregel ist die Grundlage für viele andere Lernregeln. Sie besagt,dass wenn zwei verbundene Neuronen stark aktiviert sind, das Gewicht derVerbindung erhöht werden soll.
|
| Formel 2.4 |
DieseLernregel wird meistens bei binären Aktivierungsfunktionen benutzt, wobei oft jedoch–1 und 1 als Aktivierungen verwendet werden, um auch eine Verminderung derBeträge der Gewichte zu ermöglichen.
Beidieser Lernregel ist die Veränderung proportional zur Differenz
|
| Formel 2.5 |
DieDelta-Regel ist außerdem ein Sonderfall, der bei 1-stufigen Netzen auftritt,von dem nun folgenden Lernverfahren Backpropagation.
DasLernverfahren Backpropagation (BP) ist eine Verallgemeinerung der Delta-Regelfür mehrstufige Netze. Hierbei wird der Fehler, der in der Ausgabeschichtdirekt berechnet werden kann, zurückpropagiert, d.h. es werden alle Fehler derNeuronen, mit denen das betreffende Neuron in einer höheren Schicht verbundenist, unter Beachtung der Gewichte der entsprechenden Verbindungen, addiert. Dadie Aktivierungsfunktion bei der Vorwärtspropagierung und somit auch bei derRückwärtspropagierung eine Rolle spielt, muss auch sie mit in die Rechnungeinbezogen werden.
|
| Formel 2.6 |
|
| Formel 2.7 |
Backpropagationist ein sogenanntes Gradientenabstiegsverfahren. Wenn man sich die Fehlerflächeeines neuronalen Netzes bildlich vorstellt, so sucht dieses Verfahren stets denkürzesten Weg ins Tal. Dies tut es indem es sich entgegen der Steigung andieser Stelle bewegt. Die Fehlerfläche eines Netzes ist aber nicht 2dimensional, sondern hat so viele Dimensionen wie es Gewichte gibt. ( InAnlehnung an [ZellSNN97])
DieGesamtfehlerfunktion ist wie folgt definiert :
|
| Formel 2.8 |
|
| Formel 2.9 |
|
| Formel 2.10 |
|
| Formel 2.11 |
|
| Formel 2.12 |
|
| Formel 2.13 |
|
| Formel 2.14 |
|
| Formel 2.15 |
|
| Formel 2.16 |
|
| Formel 2.17 |
|
| Formel 2.18 |
|
| Formel 2.19 |
|
| Formel 2.20 |
|
| Formel 2.21 |
|
| Formel 2.22 |
|
| Formel 2.23 |
|
| Formel 2.24 |
|
| Formel 2.25 |
|
| Formel 2.26 |
|
| Formel 2.27 |
|
| Formel 2.28 |
|
| Formel 2.29 |
|
| Formel 2.30 |
|
| Formel 2.31 |
Abbildung5 : Das 2Spiralen Problem, ein beliebtes Benchmarkverfahren um die Leistungsfähigkeiteines Lernalgorithmus zu testen. Ein neuronales Netz, das aus zwei Eingabe-,einer unbestimmten Anzahl Schichten verdeckter Neuronen und einem Ausgabeneuronaufgebaut ist, soll anhand der Position eines Punktes, die als Eingabevorgelegt wird, entscheiden, zu welcher der beiden Spiralen dieser Punktgehört, durch die schwarzen und weißen Punkte auf der rechten Seitesymbolisiert.
Füreinige Trainingsmuster sind Abänderungen teilweise vorteilhaft. Eine solcheErweiterung ist der Momentum-Term. Dieser Term beachtet die letzteGewichtsänderung bei der neuen Berechnung. Er bewirkt eine Beschleunigung der Gewichtsänderungenauf weiten Plateaus der Fehlerfläche und bremst in zerklüfteten Gebieten ab, dahier die ‚alten’ Gewichtsänderungen oft ein anderes Vorzeichen haben.
|
| Formel 2.32 |
EinProblem ist, dass sich Neuronen bei den oben beschriebenen Verfahren in denextremen Aktivierungsbereichen nur langsam ändern können. Die Ursache liegt beider Ableitung der Aktivierungsfunktion, die bei der Fehlerberechnung benutztwird. In diesen Bereichen ist die hat die Ableitungsfunktion einen Wert nahe 0.Um dieses Verhalten zu verbessern kann man zu jedem Wert der Ableitung einenfesten Wert (0.1 genügt oft schon) addieren. Auch eine feste Zuweisung verbessertteilweise die Konvergenz des Netzes, die variable Variante ist jedoch meistschneller.
Ineigenen Versuchen mit einem 10-5-10 De/Encoder konnte ich eine 40% Senkung der zutrainierenden Epochen mit dieser Variante gegenüber der unveränderter Ableitungerreichen.
Abbildung6 :Funktionsgraph der Ableitung der Aktivierungsfunktion ohne ( g(x) ) und mitFlat Spot Elimination ( h(x) ). In den roten Bereichen, den extremenAktivierungsbereichen, wird g(x) sehr klein und somit werden auch dieVeränderungen während des Lernvorgangs sehr klein, da fact(netj)als Faktor bei der Berechnung der Fehler der einzelnen Neuronen vorkommt. Somit ist es für ein Neuron, das sich in einem solchen Bereich befindet, diesennur langsam wieder zu verlassen. Wenn man zu dieser Funktion immer einenfesten Wert hinzuzählt oder auch diese auf einen festen Wert setzt, sindüberall ausreichende Gewichtsänderungen möglich. ( h(x) )
SelbstorganisierendeKarten sind aus einer Eingabeschicht und einer Schicht aktiver Neuronenaufgebaut und werden mit einem unüberwachten Lernverfahren trainiert. DieNeuronen besitzen untereinander Nachbarschaftsbeziehungen, und sie sind ineinem n-dimensionalen Gitter angeordnet. Um die Visualisierung zu vereinfachen,werden meist rechteckige oder teilweise auch hexagonale 1,2 oder 3 - dimensionaleGitter benutzt. [Kohonen]
DieNeuronen der aktiven Schicht besitzen jeweils einen Gewichtsvektor Wj,der so viele Dimensionen hat, wie der Eingabevektor E.
Abbildung7 :Prinzipieller Aufbau einer SOM. Unten sind die 3 Eingabeneuronen, oben die 25Neuronen, die die eigentliche selbstorganisierende Karte darstellen. In der Naturbesitzen ähnlich aufgebaute Netze noch laterale rekurrente Verbindungen, inSimulatoren, werden diese jedoch oft durch eine Maximumsuche ersetzt. Auch dieEingabeneuronen existieren nicht immer explizit in den Simulatorstrukturen, dadie eigentlichen Bestandteile des Netzes die, in diesem Fall, oberen Neuronensind.
DasLernen läuft so ab, dass dem Netz zuerst ein Trainingsmuster präsentiert wird.Danach folgt eine Art Propagierung, allerdings keine Berechnung einzelnerAktivierungen aus Schwellenwert und Netzeingabe, sondern eine Suche nach demkleinsten Unterschied zwischen Eingabe und Gewichtsvektor eines Neurons. ZumVergleich werden meist die euklidische Norm oder das Skalarprodukt beinormalisierten Vektoren verwendet. Danach werden die Gewichtsvektoren zumEingabevektor hin verändert, wobei mit steigendem Abstand die Stärke derVeränderungen abnimmt.
|
| Formel 2.33 |
|
| Formel 2.34 |
|
| Formel 2.35 |
|
| Formel 2.36 |
|
| Formel 2.37 |
|
| Formel 2.38 |
|
| Formel 2.39 |
|
| Formel 2.40 |
Abbildung9 : Eine‚explodierende’ Karte nach 15 Epochen, die hgauss2 benutzte. Die rotenLinien zeigen die Grenzen des Eingaberaums. Nach weiteren Epochen waren nurnoch wenige Neuronen sichtbar.
|
|
|
|
|
|
Abbildung10 :Entfaltung einer Karte (Sx = 30; Sy=30) nach dem Trainingvon 0,5,10,20,40,69 Epochen (
Abbildung 11 : Endform eines Netzes, das mit einer konstanten Lernrate trainiert wurde und die oben genannten Merkmale zeigt. |
Wennder Parameter d zu klein initialisiert wird, oder zu schnell absinkt, kann esvorkommen, dass sich weiter entfernte Neuronen nicht mehr beeinflussen könnenund somit nur Teilbereiche korrekt klassifiziert werden können. Diesen Effektnennt man topologischen Defekt.
Abbildung 12 : Ein topologischer Defekt (bzw. eigentlich sogar zwei Defekte) |
Abbildung 13 : Eine Karte, die einen kreuzförmigen Eingabebereich abbildet. Sie hat keine topologischen Defekte. |
Klasse | Bedeutung / Funktion | Dateien |
NeuronBase | Dieser Datentyp beinhaltet alle grundlegenden Variablen eines Neuronen in einem Feedforward-Netz. Neben den Variablen für die Aktivierung, dem Schwellenwert, dem zurückpropagierten Fehler, der Netzeingabe, der Position im Netz und Zeiger auf die Aktivierungsfunktion und ihre Ableitung gibt es je eine Liste mit Zeigern auf die mit diesem Neuron verbundenen Neuronen und Indices für die dazugehörigen Gewichte. Es gibt eine Liste für die Neuronen, von denen Signale kommen und zu denen Signale ‚gesendet’ werden. | NeuronBase.h |
NeuronBProp | Dieser Datentyp ist vom Datentyp NeuronBase abgeleitet. Er erweitert ihn um die Propagierungsfunktion und die Funktion zur Berechnung des Fehlers d. | NeuralNetBProp.h NeuralNetBPropDef.h |
LinkBase | Eine Datenstruktur, die einen Zeiger auf ein Neuron und einen Index für das dazugehörige Gewicht in der Liste der Gewichte enthält. | LinkBase.h LinkBaseDef.h |
WeightBase | Diese Klasse besitzt einen Zahlenwert für das Gewicht und einen Zähler für die Anzahl der Benutzungen in einem Netz, um gekoppelte Gewichte zu ermöglichen. | WeightBase.h WeightBaseDef.h |
WeightBProp | Dieser Datentyp ist von WeightBase abgeleitet, aber hat keine Funktionen oder Variablen, die ihn erweitern | NeuralNetBProp.h NeuralNetBPropDef.h |
NeuralNetBase | Basisklasse für alle in diesem Simulator verwendeten Typen neuronaler Netze. Sie liefert Versionsinformationen und definiert mit Hilfe rein virtueller Funktionen, welche Funktionen in einer abgeleiteten Klasse implementiert werden müssen. Zudem enthält sie Funktionen zur Berechnung der Gesamtfehler des Netzes. | NeuralNetBase.h NeuralNetBaseDef.h |
NeuralNetBProp | Klasse, die ein vollständiges NN beinhaltet. Ein Feld enthält die Listen der Neuronen auf jeweils einer Schicht. Außerdem sind alle Gewichte der Verbindungen in einer Liste gespeichert. | NeuralNetBProp.h NeuralNetBPropDef.h |
(Allerelevanten Klassen besitzen Funktionen, die das Speichern der Daten in Dateienunterstützen)
DieKlassen NeuralNetBPropM für Backpropagation mit Momentum-Term und NeuralNetTDNNBPropMfür Time Delay Neural Networks mit Momentum-Term sind größtenteils mit NeuralNetBPropidentisch. Der gesamte Simulator ist in C++ geschrieben, jedoch habe ich nichtganz streng objektorientiert, was man daran sieht, dass NeuralNetBPropM nichtvon NeuralNetBProp abgeleitet ist. Als ich den Simulator geschrieben habe, habeich diesen Aufbau aus Performancegründen gewählt.( Dies wäre sicherlich durchZeiger die auf erweiternde Datenelemente zeigen oder durch Anwendung vonPolymorphismus zu lösen gewesen, jedoch hatte ich zu dem Zeitpunkt noch nichtdie nötige Erfahrung. ) Ein großer Teil der Arbeit an dem Simulator bestanddarin, die Geschwindigkeit zu optimieren. Mit Hilfe vieler Veränderungen war esdann letztendlich möglich, die Geschwindigkeit von ungefähr einem kCUPS
DieGewichte der Verbindungen des neuronalen Netzes werden in einer Listegespeichert, die Verbindungen besitzen nur einen Gewichtsindex. Die Gewichteals oft benutzte Daten liegen so zusammen und können schnell erreicht werden.
AmAnfang der Entwicklung des Simulators benutzte ich noch einfach verketteListen. Diese Listen hatten jedoch bei einer größeren Länge den Nachteil, dasssie extrem langsam wurden. Daraufhin habe ich eine Listenklasse entwickelt, dieauf verketteten Feldern basiert. Dieser Ansatz hat zwar den Nachteil, dass oftviel Speicher reserviert wird, dafür aber umso schneller ist. Man kann dieGröße der Felder in der Liste anpassen, sodass man ein Mittelmaß zwischenSpeichernutzung und Geschwindigkeit finden kann. Eine Festlegung derSchichtgrößen der Netze von vornherein, bzw. bei Anfang des Trainings wollteich nicht vornehmen um auch während des Trainings das einfache Hinzufügen vonNeuronen und Verbindungen zu ermöglichen (zur einfachen Realisierung vonCascade-Correlation, einem Lernverfahren, dass auf dem Verändern von Gewichtenbei gleichzeitigem Hinzufügen von Neuronen basiert). Als Feldgrößen bieten sich2er Potenzen an, da diese von den meisten Compilern als einfacheVerschiebeoperationen übersetzt werden, die wesentlich schneller als Divisionenoder Multiplikationen und Verschiebungen auszuführen sind.
Berechnung mit Hilfe des Verschiebeoperators SAR und SHL, der 3 Zyklen benötigt (Feldgröße 210 = 1024) | Berechnung mit dem mit Verschiebe, Additions- und Multiplikationsbefehlen (Feldgröße 875) |
mov esi, DWORD PTR [ebx+8] cdq and edx, 1023 push edi add eax, edx mov edi, ecx sar eax, 10 mov edx, eax shl edx, 10 sub edi, edx | mov eax, 628292359 dec ecx push ebp imul ecx sar edx, 7 mov eax, edx push esi shr eax, 31 add edx, eax mov esi, DWORD PTR [ebx+8] push edi mov edi, ecx lea eax, DWORD PTR [edx*8] sub eax, edx lea eax, DWORD PTR [eax+eax*4] lea eax, DWORD PTR [eax+eax*4] lea eax, DWORD PTR [eax+eax*4] sub edi, eax |
Klasse | Bedeutung / Funktion | Dateien |
nVec | Dieser Datentyp ermöglicht das Rechnen mit n-dimensionalen Vektoren, wie sie bei der Simulation von SOMs benötigt werden. Diese Klasse beinhaltet Funktionen zur Addition, Subtraktion, Normalisierung und Streckung. Außerdem wurde ein spezieller Mechanismus implementiert, der es erlaubt, auf Datensätze zuzugreifen, ohne sie zeitaufwändig kopieren zu müssen. | nVec.h nVec.cpp nVecErr.h |
qSOM2d | Diese Klasse ist der Datentyp, der die Daten und Funktionen zur Simulation Self Organizing Maps bereitstellt. Die Schnittstelle wurde auf möglichst wenige Funktionen beschränkt. Durch sie können die Lernrate, der Distanzparameter, das aktuelle Gewinnerneuron und einzelne Gewichtsvektoren abgefragt bzw. festgesetzt werden. | CqSOM2d.h CqSOM2d.cpp NSOMErr.h |
SOMPattern | Diese Klasse verwaltet Trainingsdaten für SOMs. Sie können manipuliert und als Datei gespeichert werden. | SOMPattern.h SOMPattern.cpp |
(Allerelevanten Klassen besitzen Funktionen, die das Speichern der Daten in Dateienunterstützen)
DieKlasse qSOM2d beinhaltet ein Feld Zeiger auf die Gewichtsvektoren vom Typ nVec.Die Klasse SOMPattern greift über einen internen Zeiger, der einmal zurLaufzeit gesetzt werden muss, auf die Klasse qSOM2d zu, um bspw. eine Epoche zutrainieren. Die Trainingsdaten werden in der Klasse SOMPatternElem gespeichert,die selbst von nVec abgeleitet ist. Während des Trainings werden zusätzlich dieKategorisierungsfehler in einer Variable innerhalb von SOMPatternElemgespeichert, um im Nachhinein eine Aussage über das Lernverhalten der Karte inBezug auf bestimmte Datensätze machen zu können.
qSOM2dbesitzt als Besonderheit zwei Funktionen zur Kategorisierung von Eingabedaten :qSOM2d::Categorize und qSOM2d::CategorizeFast. Die erste Funktion geht alleNeuronen durch, berechnet ihren Abstand zum Gewinnerneuron und passt dieGewichte entsprechend an. Die zweite Funktionen zur Kategorisierung berechnetnur die Neuronen, die sich innerhalb eines Quadrates, dessen Seitenlänge doppeltso groß ist wie der Distanzparameter, und dessen Mittelpunkt im Gewinnerneuronliegt, befinden. Diese Funktion ist bei den Nachbarschaftsfunktionen gutanzuwenden, bei denen der Funktionswert 0 ist, wenn die Distanz größer als derDistanzparameter ist. Bei der sonst gut konvergierenden Nachbarschaftsfunktionfgauss1 ist diese beschleunigte Funktion meiner Erfahrung nach nichtohne eine Verschlechterung der Kategorisierung anzuwenden.
In denoben genannten Funktionen ist noch eine technische Besonderheit zu beobachten :Die Neuberechnung der Gewichte erfolgt nicht mit einer lokalen Kopie der Datendes zu verändernden Gewichts, sondern direkt im Speicher. Dies wird dadurcherreicht, dass die entsprechende Instanz von nVec nicht selber Speicherallokiert, sondern nur einen Zeiger auf die Position der Daten im Speicher undeine entsprechende interne Variable setzt, um später nicht zu versuchen diesenSpeicher im Destruktor wieder freizugeben.
Das neuronale Netz des Bots wird (bis jetzt)offline, d.h. außerhalb des Spiels, trainiert. Ein online-Training wäre zwarrein zeitlich möglich, jedoch müssen die Trainingsmuster so sortiert werden,dass bestimmte Muster, die zwar selten auftreten, aber dennoch wichtig sind,gut genug gelernt werden können. Diese Selektierung würde Zeit in Anspruchnehmen und auch eine automatische Generierung der gewünschten Ausgaben ist problematisch: Welchen Zweck sollte dieser Vorgang haben? Die Ausgaben würden entweder nachbestimmten Kriterien ausgewählt werden, könnten also auch von Anfang an offlinegelernt werden, oder das NN soll sich an die Art des Spielens der Gegneranpassen. Um Letzteres zu ermöglichen müssten auch Muster gefunden werden, diedem Bot Vorteile bringen könnten. Diese neuartigen, ‚kreativen’ Trainingsmusterkönnten vielleicht mit Hilfe eines evolutionären Algorithmus, also mit Hilfevon Mutationen und Kreuzungen meist erfolgreicher Bots, gewonnen werden. Einevolutionärer Algorithmus benötigt auch immer eine sogenannte Fitnessfunktion,die die Fähigkeiten des Bots bewertet. Als Möglichkeit wäre anzunehmen, dassder Wert der Fitnessfunktion von der Anzahl der Frags
Abbildung14 : Kampf-NNdes Bots (6-6-6-5)
Aufgrundder oben genannten Schwierigkeiten habe ich mich bei diesem Bot für eineinfaches NN für die Kampfentscheidungen entschieden, dass offline trainiertwird. Zurzeit hat das Netz eine Größe von 6-6-6-5 und wird mit demunmodifizierten Lernverfahren Backpropagation trainiert. Das Netz zurVermeidung von Kollisionen ist ein 3-3-1 Feedforward-Netz.
Zeitweisehabe ich versucht, das neuronale Netz während des Spiels mit Daten aus demSpiel zu trainieren. Wenn ein Bot bspw. gegen einen Gegner gewonnen hatte odermit dem Leben davongekommen war, so trainierte ich das Netz mit den Eingabe undAusgabedaten der letzten maximal 2 Sekunden, wobei die Ausgabedaten verstärktwurden, d.h. wenn eine Ausgabe den Wert 0.8 hatte, so wurde sie auf 1.0gesetzt. Für diesen Zweck verwendete ich ein größeres Netz ( 5-10-10-5 ), um zuermöglichen, dass das Netz mehr verschiedene Situationen lernen kann. Wenn ichdas mit den offline gewonnenen Trainingsdaten trainierte Netz als Ausgangsnetzverwendete, so kam es vor, dass die Bots anfingen sehr defensiv zu spielen – siewurden ja immer ‚belohnt’, wenn sie überlebten – oder es kam auch vor, dass dieAktivierung der Ausgabeneuronen immer nahe Null lag, und diese auch nicht mehrstark von der Aktivierung der Eingabeneuronen abhing, obwohl dieVerbindungsgewichte nicht alle gleich 0 waren, sondern die Signale sichaufhuben. Dies war vor allem der Fall, wenn das Netz bei dem Tod eines Botsdessen Trainingsdaten verlernen sollte. ( Dem Netz wurden die Eingabedaten unddie inversen Ausgabedaten zum Lernen repräsentiert. Als Lernverfahren fandBackpropagation Anwendung, was eigentlich ja nicht für diesen Zweck gedachtwar). Auch mit einem zufälligen Netz war auch nur eine Konvergenz derAusgabedaten gegen 0 zu beobachten.
Die einzelnenVerhaltensweisen des Bots stehen in der nachfolgend dargestellten Beziehung :
Hide : Verhaltensweise, die bewirkt, dass sich der Bot versteckt. Die Entscheidung über diesen Sachverhalt trifft das allgemeine Kampf-NN. (CBotBase.cpp : CBotBase::SearchHidingPlace(edict_t *) bzw. CBotCS_combat.cpp / CBotDOD_combat.cpp : CBotCS::Fight(void)) |
|
|
|
|
Combat : In Kampfsituationen werden bis auf die Ausnahme des Versteckens alle Bewegungen durch das Kampf-NN gesteuert. (CBotCS_combat.cpp / CBotDOD_combat.cpp : CBotCS::Fight (void)) |
| |||
AvoidTK : Dieser Teil ist dafür verantwortlich, das versehentliche Angreifen von Teammitglieder während Kämpfen zu vermeiden. (CBotDOD_combat.cpp / CbotCS_combat.cpp : CBotCS::FireWeapon(void)) | ||||
SpEnt : (für ‚special Entity’) Dieser Teil bewirkt, dass der Bot versucht bestimmte Gegenstände, die für ihn interessant sind, zu erreichen. Dies sind bspw. Geiseln oder auch eine frei herumliegende Bombe. (CBotCS_navigate.cpp / CBotDOD_navigate.cpp : CBotCS::GoToSpEnt (void) / CBotCS::GoToSpEnt (void)) | ||||
Bored : Wenn die Bots lange Zeit nichts ‘zu tun’ hatten, fangen sie für kurze Zeit an, bspw. verschiedene Dinge aus Langeweile zu zerschießen. (CBotCS_navigate.cpp / CBotDOD_navigate.cpp : CBotCS::Bored(void)) | ||||
Navigate : Das normale Verhalten eines Bots, also das Navigieren und das ‘Erforschen’ einer Karte, wird durch diesen Komplex gesteuert. (CBotCS_navigate.cpp / CBotDOD_navigate.cpp : CBotCS::HeadTowardWaypoint (void) und waypoint.cpp) | ||||
Wander : Der Bot läuft einfach solange geradeaus, bis er auf ein Hindernis stößt. Dort ändert er seine Richtung längs der Richtung des betreffenden Gegenstands. (CBotCS.cpp / CBotDOD.cpp : CBotCS::Think(void)) | ||||
AvoidCollision : Dieser Teil ist immer aktiv, sofern er nicht explizit durch CBotBase. f_dont_avoid abgeschaltet wurde, was nur in seltenen Situationen wie bspw. bei der Annäherung an einen Scharfschützenposten passiert. (CBotBase.cpp : CBotBase ::AvoidCollision(void)) | ||||
AvoidFall : Dieser Teil verhindert, dass der Bot zu tief fällt und sich verletzt. Dafür wird die Bewegungsrichtung des Bots festgestellt, die Tiefe in einer gewissen Distanz vor dem Bot gemessen und gegebenenfalls die Bewegungsrichtung umgekehrt. Dieser Teil kann durch CBotBase.f_ignore_fall unterdrückt werden. (CBotCS.cpp / CBotDOD.cpp : CBotCS::Think(void)) |
- Das Kurzzeitgedächtnis, das Positionen,Bewegungen usw. der zuletzt gesehenen Gegner speichert, um auf dieser BasisVorraussagen zu treffen, wo sich der Gegner befinden könnte. Diese Daten werdenmaximal 20 Sekunden gespeichert und werden somit nur in der direktenKampfsituation und direkt danach benutzt.
- Das Langzeitgedächtnis speichert bspw.die Orte, an denen Gegner besiegt, Die Zeiten, zu denen die Bombenplätzeüberprüft wurden oder wo und wann man zuletzt getötet wurde. Dieses Gedächtnisist nicht zeitlich, sondern in der Anzahl der Ereignisse, die es speichertbegrenzt. Diese Anzahl liegt z. Z. bei 10. Diese Daten können maximal so langebestehen, wie der betreffende Bot am Spiel teilnimmt.
- Das letzte System, das einigeEntscheidungsprozesse beeinflusst, sammelt Daten über Kämpfe und deren Ausgangbezogen auf das Waypointsystem. Wenn ein Spieler an einer bestimmten Stellegetötet wird, wird diese Information auf den nächstgelegenen Waypoint bezogenund in einer geeigneten Struktur gespeichert. Diese Daten werden in einer Dateigespeichert und werden somit mit jedem Spiel erweitert.
Dasneuronale Netz ist im Spiel für die Bewegungen des Bots in Kampfsituationen undzur Vermeidung von Kollisionen zuständig.
|
|
|
… bis zum nächsten Objekt |
|
|
Abbildung17 : GUI zurErstellung der Trainingsdaten. Es wurde erstellt um die Trainingsdatenübersichtlicher verändern können. Sonst musste dies in NNTrain.cpp in reinemASCII-Text erreicht werden.
Ich binso vorgegangen, dass ich zuerst versucht habe mir möglichst viele, aber dennochverschiedene Situationen auszudenken. Diese Muster wurden dann dem neuronalenNetz des Bots beigebracht und der Bot wurde dann getestet um evtl.Schwachstellen zu entdecken. Da dieses Verfahren jedoch sehr zeitaufwändig ist,da nach kurzer Zeit die Liste der Trainingsmuster immer länger wird, suchte ichmir eine andere Methode: Ich sammelte zuerst alle Eingaben des Kampf-NNswährend eines Spiels. Diese Muster gab ich einer selbstorganisierenden Kartezum Kategorisieren. Nach der fertigen Kategorisierung projizierte ich dieMuster, die ich zum Trainieren des neuronalen Netzes benutzt habe auf dieKarte. Nun kann man die Verteilung der Gewichte und die Trainingsdatenvergleichen und evtl. Muster finden, die das Netz wenig kennt, also der Abstandzwischen Trainingsdaten und Eingabe aus dem Spiel möglichst groß ist.
Die nachfolgenden 5 Bilder stellen einzelnenKomponenten der Gewichtsvektoren der Neuronen der SOM dar. (Diese Daten wurdenzu einem Zeitpunkt gewonnen, zu der das Netzt des Bots noch 5 Eingabeneuronenhatte) Jeder Bildpunkt ist an der Stelle angeordnet, an der auch dasdazugehörige Neuron in der SOM angesiedelt ist. Das Diffenzbild ist dadurchentstanden, dass ich für jeden Gewichtsvektor der Karte das am nächstengelegene Trainingsmuster gesucht habe und den Abstand berechnet habe. (Betragdes Diffenzvektors)
Die weißen Werte in dieser Tabelle sindjeweils die höchsten. Weiß entspricht somit einem Wert nahe 1, schwarz einemWert nahe –1. Beim Differenzbild gilt: Weiß entspricht einem Abstand derGewichtsvektoren von 1,97; schwarz 0; Die schwarzen Punkte repräsentieren diemanuell gefundenen Trainingsmuster für das Kampf-Netz. Diese Muster wurden demSOM als Eingabe präsentiert, woraufhin es das Gewinnerneuron ermitteln musste.An der Stelle des Gewinnerneurons wurde nun der schwarze Kreis gesetzt.
n(t) = 0.1 d(0) = 0.9 * X-Größe * 0.99t fNK=fgauss1 |
Dienachfolgenden Bilder stammen von einer SOM, die 90*100 Neuronen groß war, mit 12.000Trainingsmustern aus einem Counterstrike-Spiel trainiert wurde. Weiterhinbenutzte ich :
DasTraining wurde bei d < 1 abgebrochen (~ 438 Epochen) und benötigte auf einemPIII 500Mhz ungefähr 31h. (Erst später habe ich mit einer linear fallendenDistanzfunktion bessere Erfahrungen gemacht und habe diese auch erst dannverwendet.)
Abbildung 18 : (IHealth) Gesundheits- Komponente der Gewichtsvektoren der Neuronen |
Abbildung 19 : (IDistance) 'Distanz zum Gegner'-Komponente |
Abbildung 20 : (IEWeapon) 'Waffe des Gegners'-Komponente |
Abbildung 21 : (IWeapon) 'Waffe des Bots'-Komponente |
Abbildung 22 : (IAmmo) 'aktuelle Munition des Bots'-Komponente |
Abbildung 23 : Bild der Differenzen der Gewichtsvektoren zu dem jeweils nächsten Trainingsmuster |
InAbbildung 11-15 kann man erkennen, dass der Lernalgorithmus der SOMs ähnlicheTrainingsmuster an ähnlichen Stellen abbildet : Die schwarzen bzw. weißeGebiete hängen zusammen, es gibt keine Bildung von mehreren stark weißen‚Inseln’ in einem dunklen Bereich.
Bei demDifferenzbild kann man einige weiße Bereiche erkennen. Diese Bereiche hoherDiskrepanz zwischen Trainingsdaten und aufgenommenen Daten aus einem Spielmüssen näher untersucht werden. Im Visualisierungsprogramm kann man sich dieGewichtsvektoren der einzelnen Neuronen anzeigen lassen und so die genauenWerte erhalten. Es ist aber nicht zwingend nötig diese Muster neu hinzuzufügen,da es einige Muster gibt, für die das Netz gut generalisiert, also selber einegut passende Ausgabe findet.
Derkompilierte Code des Bots wird in einer DLL
|
Der Umfang dergesamten Botquelltexte beträgt ungefähr 1,1 MB, weshalb hier nur einigeAusschnitte aus den Simulatoren und dem eigentlichen Botquelltext abgedrucktsind.
Hier sindjetzt nur die wichtigsten Teile des Simulators abgedruckt. Der Teil desSimulators für BP + Momentum und TDNNs wurden nicht abgedruckt, da sie nurgeringe Abweichungen der BProp Klasse darstellen.
Ichbitte die beiliegenden Quelltexte nicht zu veröffentlichen.
DieDokumentation und auch der darin enthaltende Quelltext darf veröffentlichtwerden.
____________________
JohannesLampel