FloNET – evolutionäres Lernen

am 26. November 2017 in Aktuelles, Tech von

Vor ca. Einem Jahr beschloss ich, herauszufinden wie man Neurale Netzwerke benutzt um Intelligente Programme programmieren zu können. Das Thema künstliche Intelligenz ist ein Thema, das in Zukunft immer mehr Teil unseres täglichen Lebens wird, daher ist es sicher kein Fehler, etwas Wissen in diesem Gebiet zu haben. Umso erfreuter war ich, als ich ein Video mit dem Titel “Deep Learning without an PhD” fand, anscheinend eine einfache Anleitung als Videoform. Als ich jedoch bereits nach wenigen Minuten gar nichts mehr verstand, stellte ich das Thema Neurale Netzwerke ersteinmal hinten an. Etwas später fand ich diesen Artikel (Den Blog kann ich übrigens nur wärmstens empfehlen!). Dort wird auch unter anderem beschrieben, wie ein Gehirn grundsätzlich funktioniert. Auf Basis von diesem Wissen konnte ich dann eine eigene Version eines Neuralen Netzwerks programmieren.

Funktionsweise

Die Funktionsweise meiner Version ähnelt teilweise verbreiteten Methoden, jedoch gibt es auch einige Unterschiede. Ich werde im Folgenden meine Version beschreiben, doch der Grundgedanke eines Neuralen Netzwerks ist überall der selbe.

Das Neuron

Ein Neuron ist der kleinste Teil eines Neuralen Netzwerks, und damit auch von unserem Gehirn. Ob ein Neuron ein Signal weitergibt, das es erhalten hat, hängt davon ab wie stark es aktiviert wurde. Wurde das Neuron oft genug und mit genug Energie aktiviert, gibt es irgendwann einen Impuls an weitere Neuronen weiter.

In diesem Bild ist ein Neuron dargestellt, wie ich es in meiner Implementierung benutze. Von der vorherigen Schicht übergibt ein Neuron in diesem Beispiel einen Wert von 1.3 an das Neuron. Dieses würde nun null weitergeben, da der Threshold-Wert von 2.1 nicht überschritten wurde. Jedoch übergibt ein zweites vorheriges Neuron zusätzlich noch den Wert 1.8. Das Neuron addiert alle Werte, die es bekommt, und vergleicht es mit seinem Threshold Wert. In diesem Fall wurde er überschritten, weshalb das Neuron seinen festgelegten Outputwert weiterreicht. Dieser ist für jedes Neuron individuell, genau wie sein Threshold-Wert. Durch diese parametergesteuerte Interaktion können einfache Logikoperationen ausgeführt werden.

Das Netz

Das Netz besteht aus vielen verbundenen Neuronen, wie es oben beschrieben wurde. In diesem Beispiel besitzt das Netz 3 Inputfelder/Neuronen. Diese Werte werden von dort an die erste Reihe an Neuronen weitergeleitet. Dieses Netz besitzt 3 sogenannte “hidden layers”. Diese sind für die Berechnung der Outputwerte zuständig, in diesem Fall sind es 2. Alle Parameter können frei gewählt werden, und an das jeweilige Szenario angepasst werden.

Wie geeignet, oder “intelligent”, ein Netz ist, hängt davon ab, wie die Parameter der einzelnen Neuronen gewählt werden. Dann sind gängige Machine Learning Aufgaben wie Bild- oder Spracherkennung möglich. Auch wenn diese modellhaften Netze nicht exakt dem eines Gehirns nachempfunden sind, sind sie doch recht ähnlich. Das heißt, mit den richtigen Parametern müssen sehr intelligente Systeme möglich sein, da uns das biologische Vorbild beweist, was mit einfacher Signalübergabe möglich ist.
Doch diese Parameter des Netzes müssen erst einmal bestimmt werden. Mit zufälligen Parametern wird das Netz nur zufällige Ausgaben machen, die niemandem etwas Nützen. Die größten Unterschiede zwischen verschiedenen Machine Learning Methoden liegen genau hier, bei dem kritischen Teil. Komplexe Methoden, versuchen zum Beispiel, zu analysieren, welche Parameter besser zum Ziel verholfen haben, und welche nicht, und passt diese entsprechend an. Dies ist jedoch mathematisch sehr komplex, weshalb ich mich für eine andere Methode entschied:

Evolution

Ich verwende Auslese und Mutation, wie sie aus der Darwinistischen Evolutionstheorie stammt, um die Fitness meiner Netze zu steigern. Zu Beginn generiere ich eine festgelegte Anzahl an Netzen. Die Netze sind in ihren Netzeigenschaften gleich, jedoch werden alle Parameter der Neuronen zufällig bestimmt. Dazu gehören die Parameter maxX, outX und welche Neuronen miteinander verbunden sind. Zu diesem Zeitpunkt wird mit sehr hoher Wahrscheinlichkeit kein Netz ansatzweise einen Zweck erfüllen. Jedoch teste ich trotzdem jedes Netz, und bestimme einen Fitness-Wert. Dieser sagt aus, wie gut das Netz abgeschnitten hat. Habe ich zu jedem Netz eine Bewertung, kann ich beginnen, die nächste Generation vorzubereiten. Dafür sind 3 Schritte notwendig:

  1. Auslese
    Die Netze, die in der Rangliste in der unteren hälfte sind, werden gelöscht. (Das Gegenstück in der Realität wäre einen Darwin-Award zu gewinnen)
  2. Mutation
    Die Plätze, die durch die Auslese frei geworden sind, werden ersetzt durch neue Netze. Diese sind mutierte Versionen der Netze, die in der Rangliste die obere Hälfte besetzen. Bei einem Mutationsvorgang werden die Parameter der Neuronen leicht abgewandelt. So entsteht ein Netz, das teilweise neue Eigenschaften besitzt, zum Größten Teil jedoch noch dem Vorfahren-Netz entspricht. Die Mutation findet unter bestimmten Parametern statt, die angeben wie wahrscheinlich eine Mutation ist, und wie stark sich diese Auswirkt.
  3. Frisches Genmaterial
    Da die Netze mit jeder Generation ähnlicher werden, kann es sein dass sie sich in eine bestimmte Richtung entwickeln, von wo keine Möglichkeit zu einer Lösungsfindung vorhanden ist. Deshalb werden mit jeder Generation wenige Verlierer ersetzt durch komplett neu zufällig generierte Netze.

Löst ein Netz eine Aufgabe besonders gut, wird es auch in der nächsten Generation vorhanden sein. Es wird erst aussortiert werden, wenn es von vielen anderen Netzen in der Fitness überholt wurde, Zum Beispiel durch Mutationen von sich selbst, die kleine Verbesserungen aufweisen. Auf diese Weise werden die Parameter immer besser gewählt. Dieser Evolutionäre Lernvorgang wird dann beendet, wenn die Ergebnisse zufriedenstellend sind. Das Gewinner Netz der letzten Generation kann nun alleine verwendet werden, um Aufgaben zu lösen. Da die Rechnung, die in einem Netzwerk passiert auf einfachen Rechnungen basiert, ist die Endlösung auch relativ performant.

Diese Art des Lernens ist im Vergleich mit anderen Lernmethoden nicht sehr elegant, da es zum Großteil auf Zufall und “trial and error” basiert.

Implementierung: Autonomes Fahren

Um FloNET zu testen habe ich in Unity eine Umgebung gebaut, in der Fahrzeuge durch Hindernisparcours navigieren können. Jedes Fahrzeug besitzt fünf Sensoren, die in Unterschiedlichen Winkeln den Abstand zu einer Wand angeben. Diese fünf Abstände werden an das Neurale Netz weitergegeben, das dem Fahrzeug zugeordnet ist. Das Netz bestimmt basierend darauf den Wert, der das Fahrzeug steuert (Lenkung) Dafür wählte ich Netze mit drei hidden layers, sechs Neuronen in einem layer, fünf Inputs und einem Output. Jede Generation besteht aus 20 Fahrzeugen, die gleichzeitig Gegeneinander antreten. Kollidiert ein Fahrzeug mit einer Absperrung, bleibt es stehen. Ist die Zeit des Testlaufs um, wird die nächste Generation generiert. Als Fitnesswert wird die gefahrene Distanz der Fahrzeuge benutzt.

In dem Video ist ein Lernvorgang zu sehen, wie diese Fahrzeuge über mehrere Generationen immer weniger kollidieren, bis sie irgendwann die Teststrecke komplett durchqueren können.
Leider ist das Interface sehr unübersichtlich, doch manche Bezeichnungen solltest du aus dem vorherigen Text wiedererkennen können. Ab 1:20 sind die fühlerartigen Abstandssensoren als rote Linien zu erkennen.
In diesem Versuch ist es bereits nach zwölf Generationen gelungen, ein paar Netze zu erzeugen, die die Teststrecke durchqueren können. In diesem Fall war sehr früh ein Netz dabei, das bereits in den Grundzügen die Fähigkeit besaß, Hindernissen auszuweichen. Dies bringt die Evolution schneller voran. Doch auch mit weniger Glück sind die Netze spätestens nach 20 Generationen in der Lage, sicher zu navigieren.

Fazit

Der Ansatz über Evolution intelligente Systeme zu schaffen, halte ich für sehr vielversprechend, da wir Menschen auch ein Produkt der Evolution sind. FloNET ist in seiner Funktionalität sehr eingeschränkt, außerdem ist es mit PHP als Sprache nicht sehr performant. Ein großer Teil der außerdem noch zum biologischen Vorbild fehlt, ist die Fähigkeit, dass sich das Netz selbst anpassen kann. Die hier generierten Netze lernen nicht mehr, sobald sie eingesetzt werden.

Das Konzept von evolutionärem Lernen ist nicht neu, wie ich später feststellen musste. Es gibt bereits viele Beispiele im Internet. Dort habe ich mir dann auch die Idee abgeschaut, Fahrzeuge selbstständig fahren zu lassen.
Ich denke jedoch, dass es eine gute Demonstration ist, wie mächtig evolutionäre Algorithmen sein können. Ich denke dass es nicht die Lösung für Künstliche Intelligenz ist, jedoch glaube ich, dass es als Werkzeug sehr nützlich sein kann. So könnte man zum Beispiel spezielle Netze, die eigene Neuronenverbindungen herstellen können, nach ihrer Lernfähigkeit bewerten und evolutionär verbessern.

Falls du Interesse hast, FloNET zu benutzen, kannst du das gerne tun. Alle PHP Scripte findest du in dem Repository.

Keine Kommentare vorhanden, schreibe doch einen.

Schreibe ein Kommentar