In diesem Artikel gehe ich einmal genauer auf die Bedeutung von Aktivierungsfunktionen in einem neuronalen Netzwerk ein. Wie bereits in meinem ersten Video (Artikel folgt) zu neuronalen Netzen erläutert, dient die Aktivierungsfunktion unter anderem dazu, ein nicht lineares Modell auf Basis des neuronalen Netzwerks zu erzeugen. Alle anderen Operationen in einem neuronalen Netzwerk sind nämlich rein lineare Operationen.
Diesen und andere Beiträge von mir kannst du als sauber formatierte PDF-Datei zum Ausdrucken oder offline Lesen erwerben. Mehr Informationen dazu findest du hier.
Zu diesem Artikel findest du auch ein Video von mir auf YouTube.
Nötige Vorkenntnisse
- Grundkenntnisse über neuronale Netze, etwa aus meinen ersten beiden Videos/Artikeln:
Überblick über Aktivierungsfunktionen
Zunächst ein kleiner Überblick über einige der am häufigsten genutzten Aktivierungsfunktionen.
Die Auswirkungen der ReLU-Aktivierungsfunktion
Schauen wir uns einmal am Beispiel der $ReLU$-Funktion die Auswirkungen der enthaltenen Nichtlinearität genauer an und wie sich dies über mehrere Neuronen auswirkt. Beginnen wir mit einem extrem simplen neuronalen Netz, indem wir ein Eingangsneuron $x$ mit zugehörigem Bias-Neuron mit einem weiteren Neuron im nächsten Layer verknüpfen. Als Aktivierungsfunktion $g(z)$ verwenden wir hier die $ReLU$-Funktion.
Somit ergibt sich für die Ausgabe $h(x)$ dieses Neurons die folgende Formel mit der Gewichtung $w_1$ des Input-Neurons und des Bias-Gewichts $b_1$.
$h(x) = ReLU(w_1 x + b_1)$
Grafisch sieht die Funktion $h(x)$ dann für $w_1=1.0$ und $b_1=0.0$ wie folgt aus:
Im folgenden Video wird einmal der Wert für das Gewicht $w_1$ angepasst.
Wird $w_1$ negativ, so erhält man für positive $x$-Werte als Output den Wert null und für negative $x$-Werte eine lineare Funktion.
Durch Ändern von $b_1$ kann der Knick in der Funktion nach rechts respektive links auf der x-Achse verschoben werden, wie im folgenden Video zu sehen.
Erweitern wir jetzt das neuronale Netz um einen weiteren Knoten und addieren die Werte der beiden orangen Neuronen zusammen.
Hierdurch kommen die beiden Gewichte $w_2$ und $b_2$ hinzu und damit auch ein zweiter Knick in der Funktion $h(x)$, hervorgehoben durch die roten Kreise.
Die Position der beiden Knicke kann auch über die beiden neuen Gewichte gesteuert werden.
Wandeln wir das neuronale Netz nun einmal in ein klassisches neuronales Netz mit einem zusätzlichen Bias-Neuron und den Gewichten $a_1$, $a_2$ und $b_3$ um und verwenden als Output-Aktivierungsfunktion eine lineare Funktion.
Dadurch, dass keine weitere $ReLU$-Funktion addiert wird, kommt auch kein weiterer Knick hinzu, allerdings lässt sich durch die zusätzlichen Parameter die Funktion $h(x)$ weiter anpassen.
Tatsächlich ist es so, dass eine solche Verkettung von $ReLU$-Funktionen mit den entsprechenden Parametern $a$, $w$ und $b$ es ermöglicht, jede beliebige, stetige Funktion zu approximieren. Die Genauigkeit hängt dabei natürlich von der Anzahl der Neuronen, respektive der $ReLU$-Funktionen ab.
Approximation der logistischen Funktion
Versuchen wir jetzt also einmal die logistische Funktion $f(x)$, im unteren Bild auf der linken Seite in Orange dargestellt, zu approximieren. Der Plot der Output-Funktion in Blau zeigt den Stand nach der Initialisierung des neuronalen Netzes, wobei die beiden Knicke der $ReLU$-Funktionen übereinander liegen.
Zur Approximation der Funktion oder anders ausgedrückt zur Optimierung des hier dargestellten neuronalen Netzes habe ich die Python-Bibliothek keras verwendet und im Speziellen eine Variante des Stochastic Gradient Descent Algorithmus. Stochastic Gradient Descent ist eine probabilistische Variante des Gradient Descent Verfahrens, welches ich bereits in einem früheren Video mit zugehörigem Artikel vorgestellt habe.
Der Lernprozess
Schauen wir uns nun einmal den Lernprozess des neuronalen Netzes an.
Mit lediglich zwei Knicken oder anders ausgedrückt der Kombination dreier Linien ist es natürlich nicht exakt möglich, die orange Funktion zu approximieren. Jedoch kann die ungefähre Form der Funktion dargestellt werden.
Erweitern wir daher das neuronale Netz jetzt einmal auf fünf Neuronen im mittleren Layer.
Der Verlauf der Optimierung mutet zunächst etwas merkwürdig an, aber die Funktion wird letztendlich recht genau approximiert und das mit lediglich fünf Neuronen.
Anschließend wird das neuronale Netz auf zehn Neuronen erweitert.
Damit wird vor allem die linke Hälfte der Funktion sehr genau approximiert.
Das Verhalten einer mathematischen Optimierung, insbesondere mit probabilistischem Anteil wie in diesem Fall, ist nicht immer leicht nachzuvollziehen und soll auch nicht der Fokus dieses Artikels sein. Entscheidend ist, dass die orange Funktion immer exakter approximiert werden kann. Dies wäre mit einer rein linearen Aktivierungsfunktion nicht möglich gewesen.
Daher sind in der Realität nicht lineare Aktivierungsfunktionen von entscheidender Bedeutung, um nicht lineare Zusammenhänge in den Daten widerspiegeln zu können. Dass dabei jedoch nicht einfach blind irgendwelche Aktivierungsfunktionen gewählt werden sollten, schauen wir uns nun in einem etwas komplexeren Beispiel einmal an.
Approximation einer komplexen Funktion
Betrachten wir jetzt einmal diese komplexe Funktion mit vielen lokalen Minima und Maxima.
Single Hidden Layer
In einem ersten Versuch nutzen wir das gleiche neuronale Netz wie im vorigen Beispiel mit 10 Neuronen mit der $ReLU$-Aktivierungsfunktion im mittleren Layer. Anschließend starten wir den Lernprozess des neuronalen Netzes, wobei in Blau die approximierte Funktion des neuronalen Netzes dargestellt ist.
Ist zu Beginn des Lernprozesses noch ein gewisser Fortschritt zu erkennen, so sind etwa ab der zwanzigsten Iteration nur noch minimale Änderungen zu verzeichnen. Dieses Hin- und Herspringen der Funktion zeigt, dass die numerische Optimierung an dieser Stelle nicht wirklich weiterkommt. Wir befinden uns mutmaßlich in einem lokalen Optimum, aus dem wir nicht mehr herauskommen.
Es hat sich gezeigt, dass für die Approximation einer Funktion mit vielen lokalen Minima und Maxima, die $tanh$-Funktion deutlich besser geeignet ist als die $ReLU$-Funktion. Verwenden wir daher nun einmal zehn Neuronen der $tanh$-Aktivierungsfunktion.
Im Gegensatz zum vorigen neuronalen Netz ist dieses jetzt besser in der Lage, die Funktion zu approximieren.
Nach etwa 150 Iterationen sind die Änderungen nur noch minimal. Speziell in dem blau markierten Bereich im unteren Bild weicht unsere Approximation noch relativ stark von der ursprünglichen Funktion ab, aber ansonsten sieht es schon ziemlich gut aus.
Erhöhen wir jetzt einmal auf 20 Neuronen und schauen, was passiert.
Ich verzichte an dieser Stelle auf den Ablauf der Optimierung und stelle nur das Endergebnis in Grün dargestellt vor.
Bis auf den Bereich am Anfang wird die Funktion jetzt nahezu exakt approximiert.
Multiple Hidden Layer
Statt immer mehr Neuronen in einen einzelnen Layer zu packen, können auch mehrere Hidden Layer verwendet werden. Dadurch ergibt sich automatisch eine höhere Anzahl von Parametern. Betrachten wir etwa das folgende neuronale Netz mit zehn Neuronen mit der $ReLU$-Aktivierungsfunktion im ersten Hidden Layer und zehn Neuronen mit der $tanh$-Aktivierungsfunktion im zweiten Layer.
Während das vorige neuronale Netz mit 20 Neuronen in einem Hidden Layer 61 trainierbare Parameter enthält, so hat dieses neuronale Netz nun 141 trainierbare Parameter. Durch die Verwendung eines zusätzlichen Layers hat sich also die Anzahl der Parameter im neuronalen Netz mehr als verdoppelt. Theoretisch sollte auch ein einziger Layer für alle möglichen Aufgaben ausreichend sein, in der Praxis machen sich mehrere Layer jedoch häufig bezahlt.
Betrachten wir jetzt einmal das Ergebnis dieses neuronalen Netzes bei der Funktionsapproximation.
Die Funktion wird ebenfalls hervorragend approximiert, allerdings nicht ganz so exakt wie zuvor. Insbesondere am Anfang der Funktion und im mittleren Bereich (dargestellt durch die blauen Kreise) weicht dieser Versuch doch ein klein wenig mehr ab. Zum Abschluss hier noch einmal eine Darstellung aller gezeigten Approximationen.
Bedeutung zusätzlicher Hidden Layer
Die Bedeutung zusätzlicher Layer innerhalb eines neuronalen Netzes lässt sich oft nur schwer bestimmen. In der Bilderkennung, in der aus den einzelnen Layern Bilder extrahiert werden können, ist dies jedoch etwas einfacher möglich. In diesem Video von 3blue1brown wird gezeigt, wie einzelne Layer unterschiedliche Konturen, etwa Kreise oder Linien, beim Erkennen von Zahlen detektieren. Im Folgenden ein kleiner Ausschnitt daraus:
Zusammenfassung Aktivierungsfunktionen
In diesem Artikel habe ich die Bedeutung der Aktivierungsfunktion in einem neuronalen Netz erläutert. Durch Verwendung nicht linearer Aktivierungsfunktionen können jegliche stetigen Funktionen approximiert werden, wobei die Güte von der Anzahl der Neuronen abhängt. Zudem ist die Wahl der Aktivierungsfunktion entscheidend, wie im komplexen Funktionsbeispiel gesehen. Durch Verwendung mehrerer Layer lässt sich die Anzahl der Parameter leicht erhöhen und auch unterschiedliche Aktivierungsfunktionen verwenden.
Weitere Informationen
In meinen Videos auf YouTube stelle ich dieses und weitere Machine Learning Themen noch einmal detaillierter vor. Bei Fragen oder Anmerkungen schreibt mir gerne einen Kommentar :).
Meine Webseite ist komplett werbefrei. Falls dir dieser Beitrag gefallen hat und du meine Arbeit gerne unterstützen möchtest, schau daher doch einmal auf meiner Support-Seite vorbei. Das würde mich sehr freuen :).
Quellen
- YT Video: But what is a neural network REALLY?
- YT Video: Why Neural Networks can learn (almost) anything
- YT Video: But what is a neural network? | Chapter 1, Deep learning
- Stackoverflow: Komplexe Funktionsapproximation
- Machine Learning Bibliothek: keras