Künstliche neuronale Netze sind eine tragende Säule moderner künstlicher Intelligenz und finden in vielen Bereichen Anwendung. Um ihre Funktionsweise zu verstehen, kann man selbst ein neuronales Netzwerk aufbauen und trainieren. Dieser Artikel bietet eine Grundlage dafür und demonstriert, wie man ein solches Modell, insbesondere ein Neuron Modell, basteln kann.
Einführung in das Neuron Modell
Der Hype um Deep Learning begann bereits in der Mitte des letzten Jahrhunderts. Zentraler Gedanke ist ein Neuron, das von anderen Neuronen "gefüttert" wird und je nach Menge der Eingaben selbst aktiv wird und andere Neuronen aktiviert. Die Eingaben werden im Neuron aufsummiert, und wenn ein bestimmter Schwellwert erreicht wird, schaltet das Neuron selbst auf "1", sonst auf "0". Dieser Zustand - das Neuron leuchtet auf (=1) oder bleibt dunkel (=0) - ist ein binärer Kippschalter. Im maschinellen Lernen spricht man von einem binären Klassifikator.
Das Perzeptron als Vorläufer
Die Geschichte des Neuronen-Modells reicht zurück bis zum Perzeptron. Das Perzeptron gehört zu den Methoden des Supervised Learning (Lernen mit Lehrer) und benötigt zum Zweck des Lernens gute Beispiele, die dem Perzeptron sagen, ob es richtig oder falsch gearbeitet hat. Diese Trainingsbeispiele müssen sorgfältig ausgewählt werden. Das ganze Geheimnis des Lernens steckt in den Verbindungen, die zwischen Eingabe- und Ausgabeschicht stecken. Jedes Eingabeneuron geht eine Verbindung mit dem Ausgabeneuron ein. Diese Verbindungen erhalten Gewichte (engl. weights), mit der die Stärke der Verbindung in Zahlenwerte übertragen wird.
Einfaches Beispiel: "Schöner Tag"-Klassifikator
Ein einfaches Beispiel ist ein Klassifikator, der uns sagt, ob heute ein "Schöner Tag" ist. Die Merkmale "Sonne scheint" und "Freunde haben Zeit" werden als Eingabe verwendet, und "Schöner Tag" ist der gesuchte Wert oder die gewünschte Ausgabe. Im Grunde ist das die logische ODER-Funktion: Ein schöner Tag ist immer dann gegeben, wenn mindestens eines der beiden Eingangsmerkmale erfüllt ist. Anstatt die ODER-Funktion fest einzubauen, soll diese von einem Algorithmus gelernt werden. Zum Schluss sagt der Supervisor, ob das Perzeptron alles richtig gelernt hat. Falls nicht, werden die Gewichte des Systems geändert.
Die Rolle der Gewichte
Jedes Eingabeneuron hat eine Verbindung mit dem Ausgabeneuron. Diese werden einfach durchgezählt und als Gewichte des Netzes bezeichnet (engl. weights). Im Ausgabeneuron wird alles, was da rein kommt, aufsummiert, wobei die Eingaben über eine Gewichtung stärker oder schwächer auf die Summe einzahlen. Die Gewichte können Fließkommazahlen sein. Das Ausgabeneuron des Perzeptrons feuert "1", wenn die Eingaben einen Schwellwert überschritten haben, ansonsten bleibt es dunkel und auf "0".
Lesen Sie auch: Ursachen, Symptome und Behandlungen von Motoneuron-Erkrankungen
Mathematische Umsetzung
Um diese Konzepte am Computer umzusetzen, werden zwei Operatoren der Algebra verwendet: Die Summe lässt sich mit einem Plus (+) realisieren, die Stärke der Verbindung mit einer Multiplikation (*). Für "Sonne scheint" wird kurz S geschrieben, und für "Freunde haben Zeit" kurz F. Aus den Eingaben S und F, die jeweils mit ihren eigenen Verbindungsgewichten multipliziert werden, entsteht eine neue Zahl, die mit dem Schwellwert verglichen werden kann.
Da fast immer davon ausgegangen wird, dass die Neuronen der einen Schicht (bspw. Eingabe-Schicht) mit allen Neuronen der anderen Schicht verbunden sind, müssen wir uns nur die Gewichte in der richtigen Anordnung merken und wissen immer ganz genau, was zwischen Neuron 2 der einen Seite und Neuron 1 der anderen Seite los ist.
Das Bias-Neuron
Um den Schwellwert nicht als Extrawurst behandeln zu müssen, kann man sich ein Neuron dazu basteln. Eine zusätzliche Eingabe in das System ist das Bias-Neuron, das immer aktiviert ist und immer auch mit "1" aktiv ist. In Schaubildern sieht man daher einen Kreis mit einer 1 drin. Auf diese Art und Weise braucht man nur noch ein Trainingsverfahren für die Verbindungsgewichte zwischen Eingabe und Ausgabe und muss sich um den Schwellwert nicht mehr extra kümmern.
Mathematische Formulierung
Statt S und F für unsere Merkmale gewöhnen wir uns jedoch gleich an, die Variablen so wie die Gewichte auch durchzunummerieren. Jedes Element der einen Liste wird mit jedem Element der anderen Liste multipliziert und zum Schluss werden die Werte aufsummiert. Das nennt man auch Skalarprodukt (engl. dot product).
Aktivierungsfunktion
Normalsterbliche Programmierer würden jetzt sagen: ja, da haben wir jetzt eine wunderbare Größer-Gleich-Null-Klausel im Code, aber da Mathematiker nicht wie herkömmliche Programmierer denken, nennen Sie das was wir da machen wollen Heaviside-Funktion. Das meint aber im Grunde das gleiche: alles, was kleiner 0 ist, ist 0. Alles, was größer oder gleich 0 ist, ist 1. In Schaubildern neuronaler Netze sieht man dann eben ein Neuron, wo der Anfang einer Treppe eingezeichnet ist (deswegen nennt man die Funktion auch Treppenfunktion).
Lesen Sie auch: Fliegen und Drohnen im Fokus
Bis hierin wurde im Grunde genommen ein einlagiges neuronales Netz mit einem Ausgabeneuron gebaut, das über die komplizierte Heaviside-Funktion (nagut, kompliziert ist hier nur der Name) aktiviert wird.
Wie lernt ein Perzeptron?
Bislang gab es auch gar keine wirklich schwere Mathematik. Viel eher drückt bis hier hin die Last der unterschiedlichen Konzepte, die wir uns erarbeitet haben. Zum Glück haben wir das schwerste schon hinter uns und stürzen uns jetzt darauf, wie das Perzeptron lernen kann. Oben haben wir ja schon gelesen, dass wir die Gewichte verändern dürfen. Man könnte einfach zufällige Gewichte durchprobieren. Ja, kann man so machen. Das dauert aber eine Ewigkeit. Zudem hat dieses Verfahren gar kein Gedächtnis, von einer Intuition ganz zu schweigen: Wenn wir schon einmal nah dran waren an einem guten Ergebnis, dann probieren wir ja in der nächsten Runde wieder ein komplett zufälliges Ergebnis.
Die Formel genauer betrachtet
Wenn eine 1 das Ergebnis war, aber 0 richtig gewesen wäre, dann kann das nur bedeuten: die gewichtete Summe vor dem Größer-Gleich-Zeichen war zu groß. Das wiederum kann nur bedeuten, dass die Gewichte falsch in dem Sinne gewählt sind, dass auch die relevanten Gewichte zu groß sind. Damit sind wir schon einen großen Schritt weiter, denn wir kennen nun schon die Richtung, in die wir Gewichte verändern müssen.
Die Richtung der Gewichtsänderung hängt offenbar ab von dem erwarteten Ergebnis und dem gelieferten Ergebnis. Kann man die beiden Fälle nicht einfach mit IF-Statements abfrühstücken? Das geht vielleicht, solange wir nur Einsen und Nullen und nur ein Ausgabeneuron haben. Wenn wir mehrere Ausgaben wollen (bspw. "Schöner Tag", "Mittelguter Tag", "Montag"), oder wenn wir statt Einsen und Nullen auch noch "die Werte dazwischen" zulassen wollen, und erst recht wenn wir damit anfangen wollen, tiefere Modelle zu bauen, die auch noch Zwischenschichten zwischen Ein- und Ausgabe haben, dann sind wir mit unserem Programmiererlatein dann doch schnell am Ende.
Den Fehler des Perzeptrons messen
Und was machen wir nun mit diesen beiden Fällen, wenn wir als Mathematiker denken? Wir rechnen einfach mit den Werten weiter. (für engl. o=output). Kurz und knackig, nicht wahr? Wenn wir unsere Tabelle oben anschauen, bekommen wir also für den Fehler -1, wenn eine 0 erwartet wurde, aber 1 geliefert wurde. Und wir bekommen eine +1, wenn eine 1 erwartet, aber eine 0 geliefert wurde. Und wenn beide Werte übereinstimmen, also bspw. eine 1 erwartet und eine 1 geliefert wurde, dann ist der Fehler 0! Denn das Vorzeichen liefert uns ja auch gleich die Richtung der Korrektur! Wir merken uns, dass uns die Differenz die Richtung gibt. Später, wenn wir mit tieferen und komplexeren neuronalen Netzen arbeiten, werden wir über das Differenzieren eine Richtung erhalten.
Lesen Sie auch: Die Rolle des Zellkörpers in Neuronen
Aus dem Fehler lernen
Wir wissen, in welche Richtung unser Fehler korrigiert werden muss, aber wie sollten wir nun vorgehen, um die Gewichte zu aktualisieren? den Wert +1 hat, dann wird das Gewicht vergrößert, ist es -1, dann wird das Gewicht verringert. gleich Null und es ändert sich gar nix am Gewicht. ) bezeichnen wollen und für die wir für den Anfang einen Wert von 0.1 wählen. Wenn wir uns langsamer unserem Ziel nähern, vermeiden wir, über das Ziel hinaus zu schießen.
Die relevanten Gewichte finden
Zunächst mal übertragen wir unsere Lerntabelle in eine Liste von Listen. Dabei führen wir das daueraktivierte Bias-Neuron am Anfang und die beiden Merkmale S und F an Position 2 und 3 der Liste. Das gewünschte Ergebnis halten wir uns in einer einfachen Liste parat, die wir targets nennen. Nun können wir uns ein Trainingsbeispiel, sagen wir mal das 4. Wenn wir uns dieses Trainingsbeispiel nochmal anschauen, sehen wir, dass außer dem Bias-Neuron kein anderes Neuron gefeuert hat. waren also gar nicht am aktuellen Fehler beteiligt, weil die entsprechenden Eingabeneuronen gar nicht aktiv waren! Da die Gewichte nicht am Fehler beteiligt waren, sollten wir auch aus Sicht unseres Programmes für das Trainieren der Gewichte gar keine Aussage darüber wagen, ob die nicht beteiligten Gewichte nun gut oder schlecht waren.
Die Perzeptron-Lernregel
Generell wissen wir ja nun, dass ein Gewicht nur etwas zum Fehler beigetragen haben kann, wenn das entsprechende Input-Neuron vor diesem Gewicht auch aktiv war. Wir können also die Veränderung eines Gewichtes verhindern, in dem wir mit dem zugehörigen Input-Neuron multiplizieren. Denn war das Input-Neuron 0.0, dann wird auch die Änderung 0.0 sein! Alter Schwede - delta, alpha und i in einer Multiplikation. Wir ändern ein Gewicht also proprotional zur Stärke der Aktivierung im Input-Neuron, proportional zur Lernrate alpha und - ganz besonders wichtig - auch in die Richtung der Differenz zwischen Soll und Ist, die wir delta genannt haben. Das ist wirklich eine komprimierte Darstellung, über die man eine Weile meditieren darf.
Die Trainingsepochen können starten
Wir haben Trainingsdaten. Wir wissen, wie wir unsere n Gewichte aktualisieren können. Jetzt brauchen wir nur noch eine Strategie, damit das Training auch gelingt. Bislang haben wir uns immer nur ein Trainingsbeispiel rausgepickt und untersucht, aber das Training soll ja für alle Beispiele laufen, damit auch alle Ausgaben später so sind, wie gewünscht. Mindestens müssen wir also einmal für alle Trainingsbeispiele die Gewichtsaktualisierung durchführen. Die Präsentation aller Beispiele und das Ausrechnen von Fehler und Gewichtsaktualisierung wird auch Epoche genannt. Es wäre schön, wenn eine Epoche reichen würde: in der Regel müssen jedoch mehrere Epochen durchlaufen werden, damit die Gewichte sich nach und nach…
Neuronales Netzwerk in Java aufbauen
Ein neuronales Netz ist ein Graph, bestehend aus Knoten (Nodes), die Neuronen genannt werden. Dieses Modell ist sehr variabel.
Die Neuron-Class
Eine Neuron-Class soll die Werte enthalten. Jedes Mitglied (bias, weight1 und weight2) wird mit einem zufälligen Double zwischen -1 und 1 initialisiert. Um den Output des Neurons zu berechnen, wird jede Eingabe mit ihrer Gewichtung plus dem Bias multipliziert: input1 * weight1 + input2 * weight2 + bias. So erhalten wir die unverarbeitete Berechnung (preActivation), die wir durch die Aktivierungsfunktion laufen lassen. In diesem Fall verwenden wir die Sigmoid-Aktivierungsfunktion, die Werte in einem Bereich von -1 bis 1 komprimiert.
Die Network-Class
Einige Neuronen werden in ein Netzwerk eingefügt. Dazu nutzen wir eine Network-Class mit einer Liste von Neuronen. Obwohl die Liste der Neuronen eindimensional ist, werden wir sie während der Nutzung zu einem Netzwerk verbinden. Die ersten drei Neuronen sind Inputs, die folgenden beiden versteckt und das letzte der Output-Knoten.
Eine Prediction anstoßen
Um ein Netzwerk zu Prediction-Zwecken einzusetzen, verwenden wir einen einfachen Datensatz mit zwei ganzzahligen Inputs und einem Antwortformat von 0 bis 1. In unserem Beispiel wird eine Kombination aus Gewicht und Größe verwendet, um das Geschlecht einer Person zu erraten. Dabei wird davon ausgegangen, dass mehr Gewicht und Größe auf eine männliche Person hindeuten. Dieselbe Formel ließe sich für jede beliebige Wahrscheinlichkeitsrechnung mit zwei Faktoren und einem Output nutzen. Den Input könnte man auch als Vektor betrachten - und somit die Gesamtfunktion der Neuronen als Umwandlung eines Vektors in einem Skalarwert.
Die beiden Inputs fließen an die ersten drei Neuronen. Deren Outputs werden an die Neuronen 4 und 5 weitergeleitet wird, die wiederum in das Output-Neuron einspeisen. Dieser Prozess wird als Feedforward bezeichnet.
Das würde sicher zu Ergebnissen führen - die allerdings nur auf Zufallswerten und Bias basieren. Für eine echte Prediction ist es nötig, das Netzwerk zuvor zu trainieren.
Das Netzwerk trainieren
Das Training eines neuronalen Netzwerks folgt einem Prozess, der als Backpropagation bekannt ist. Der beinhaltet im Grunde, Änderungen rückwärts durch das Netzwerk zu “schieben”, damit sich der Output in Richtung eines gewünschten Zielwerts bewegt. Backpropagation lässt sich mit Hilfe von Funktionsdifferenzierung durchführen - für unser Beispiel werden wir allerdings einen anderen Weg gehen und jedem Neuron die Fähigkeit verleihen, zu “mutieren”.
In jeder Trainingsrunde (auch Epoch genannt) wählen wir ein anderes Neuron aus, um eine kleine, zufällige Anpassung an einer seiner Eigenschaften (weight1, weight2 oder bias) vorzunehmen und dann zu prüfen, ob sich die Ergebnisse verbessern. Ist das der Fall, behalten wir diese Änderung mit einer remember()-Methode bei. Wenn sich die Ergebnisse verschlechtert haben, machen wir sie mit einer forget()-Methode rückgängig.
Um die Änderungen zu tracken, fügen wir Class-Mitglieder hinzu (old*-Versionen von weights und bias).
Zusammengefasst:
- Die mutate()-Methode wählt eine zufällige Eigenschaft und einen zufälligen Wert zwischen -1 und 1 aus und ändert dann die Eigenschaft.
- Die forget()-Methode setzt diese Änderung auf den alten Wert zurück.
- Die remember()-Methode kopiert den neuen Wert in den Puffer.
Um nun die neuen Fähigkeiten unseres Neurons zu nutzen, fügen wir Network eine train()-Methode hinzu.
Die train()-Methode iteriert eintausendmal über die aufgeführten data, answers und lists. Es handelt sich um gleich große Trainingsmengen: data beinhaltet Input-Werte, answers die bekannten, richtigen Antworten. Die Methode ermittelt dann einen Wert darüber, wie nahe das Ergebnis des Netzwerks den bekannten, richtigen Antworten kommt. Dann wird ein zufälliges Neuron verändert (mutiert), wobei die Änderung beibehalten wird, wenn ein neuer Test ergibt, dass sie eine bessere Vorhersage zur Folge hatte.
Die Ergebnisse lassen sich mithilfe der Mean-Squared-Error (MSE) -Formel überprüfen - einer dafür gängigen Methode.
System feinabstimmen
Nun müssen wir nur noch einige Trainingsdaten in das Netz fließen lassen und es mit weiteren Predictions austesten.
Trainingsdaten bereitstellen
Die Trainingsdaten bestehen aus einer Liste von zweidimensionalen Integer-Sets (wir könnten sie uns als Gewicht und Größe vorstellen) und einer Liste von Antworten (wobei 1.0 weiblich und 0.0 männlich ist).
Trainingsdaten-Logging
Wenn wir den Trainingsalgorithmus eine Logging-Funktionalität hinzufügen, sehen wir, dass der "Loss" (also die Fehlerabweichung von "100 Prozent korrekt") langsam abnimmt. Das Modell nähert sich also immer mehr einer genauen Vorhersage an.
Vorhersagen
Wir füttern unser trainiertes neuronales Netz mit Daten und geben die Vorhersagen aus. Das Netzwerk leistet bei den meisten Wertepaaren (Vektoren) ziemlich gute Arbeit. Es gibt den weiblichen Datensätzen eine Schätzung um 0.907 - was ziemlich nahe an 1 ist. Zwei männliche Datensätze weisen 0.027 und 0.030 auf - und nähern sich damit der 0. Der männliche Ausreißer-Datensatz (130, 67) wird als “wahrscheinlich weiblich” angesehen, bei einem Wert von 0.900 allerdings mit geringerer Zuversicht.
Möglichkeiten zur Verbesserung
Es gibt eine Reihe von Möglichkeiten, die Einstellungen an diesem System zu verändern: Die Anzahl der Epochs in einem Trainingslauf ist dabei ein wichtiger Faktor. Je mehr Epochs, desto besser wird das Modell auf die Daten abgestimmt. Das kann auch die Genauigkeit von Live-Daten verbessern, die mit den Trainingssätzen übereinstimmen. Allerdings kann es auch in einem “Overtraining” resultieren - also einem Modell, das zuversichtlich die falschen Ergebnisse für Randfälle vorhersagt.
Neuron Modell Basteln im Biologieunterricht
Ein Netz aus Nervenzellen sorgt beim Menschen für Aufnahme, Weiterleitung und Verarbeitung von Informationen aus der Umwelt und der Innenwelt des Körpers. Eine Phantasiereise zu den Nervenzellen macht die SchülerInnen mit deren Aufbau und den Funktionen der einzelnen Teile vertraut. Anschließend basteln sie - zunächst nach eigenen Vorstellungen, anschließend nach einer Bauanleitung - Nervenzell-Modelle und verbinden diese zu einem Netz.
Kreative Modelle aus Alltagsgegenständen
Schüler können aus Alltagsgegenständen zu Hause ein Modell einer Nervenzelle (Neuron) bauen. Dabei können kreative Anschauungsmodelle entstehen.
- Zellkörper: Ein Korallenschwamm kann als Zellkörper dienen.
- Zellkern: Ein Knopf kann den Zellkern darstellen.
- Dendriten: Kleine Geschenkpapierschnüre können als Dendriten dienen.
- Axonhügel: Der Axonhügel kann aus glitzerndem Papier ausgeschnitten werden.
- Schnürring und Endknöpfchen: Plüschdraht und Glitzerpapier können für Schnürring und Endknöpfchen verwendet werden.
- Alternative Materialien: Plüschdraht (Pfeifenreiniger) kann für eine farbliche Gestaltung verwendet werden. Aluminiumfolie kann als Zellkern dienen. Ein Duschschwamm kann die Verzweigungen der Dendriten darstellen. Eine Kordel mit grüner Wolle kann die Gliazellen mit den Schnürringen darstellen. Ein altes Stück Stoff mit einem Gummi kann den Axonhügel darstellen.
Bauanleitung für ein dreidimensionales Laubblattmodell
Baue ein dreidimensionales Modell des Ausschnittes aus einem Laubblatt. Schneide die Vorlage aus, falte an den gestrichelten Linien und klebe an den Laschen zusammen. Wenn Du die Rückseite (in der Vorlage links) in das Heft klebst, kannst Du die übrigen Seiten auch falten ohne sie zu kleben. Benenne die im Modell erkennbaren Strukturen und beschreibe ihre Funktion. Überprüfe den Bau hinsichtlich der Vermutungen 1 und 2.