Künstliche neuronale Netze (KNN) sind ein faszinierendes Gebiet, das sich von der Funktionsweise des menschlichen Gehirns inspirieren lässt. Sie haben sich zu einem unverzichtbaren Werkzeug in den Bereichen maschinelles Lernen und künstliche Intelligenz entwickelt. In diesem Artikel werden wir uns mit den Grundlagen neuronaler Netze befassen, ihre Funktionsweise erläutern und zeigen, wie man sie mit Python programmieren kann.
Was sind künstliche neuronale Netze?
Wenn wir von "Neuronalen Netzen" sprechen, meinen wir artifizielle neuronale Netze (ANN). Die Idee eines ANN basiert auf biologischen neuronalen Netzen, wie sie z.B. im menschlichen Gehirn vorkommen. Künstliche Neuronale Netze sind Algorithmen, die dem menschlichen Gehirn nachempfunden sind. Dieses abstrahierte Modell miteinander verbundener künstlicher Neuronen ermöglicht es, komplexe Aufgaben aus den Bereichen Statistik, Informatik und Wirtschaft durch Computer zu lösen.
Die biologische Inspiration
Die wichtigsten Bestandteile eines biologischen Gehirns sind die Gehirnzellen, auch Neuronen genannt, und die Verbindungen zwischen den Neuronen. Das menschliche Gehirn besteht aus etwa 86 Milliarden Neuronen und ca. (10^{14}) (100 Trillionen) Verbindungen, also Synapsen.
Neuronen empfangen elektrische Signale über Dendriten und laden sich gewissermaßen auf. Erst wenn ein bestimmter Schwellwert erreicht ist, feuert das Neuron über das Axon ein Signal nach außen. Die Erregung eines Neurons wird über sein Axon weitergegeben und über Synapsen auf die Dendriten anderer Neuronen weitergegeben. Neurotransmitter können das Signal verstärken (exzitatorisch) oder hemmen (inhibitorisch).
Das künstliche Neuron
Die Basiseinheit eines neuronalen Netzes - sowohl eines artifiziellen als auch eines lebendigen - ist das Neuron. Die Dendriten zweigen aus dem Soma ab wie die Verzweigung eines Baumes und verjüngen sich mit jeder neuen Aufteilung. Sie erhalten Signale (Impulse) von anderen Neuronen an den Synapsen, wo sie sich mit anderen Zellen verbinden. Das Axon - wovon immer nur eines existiert - kommt ebenfalls aus dem Soma und erstreckt sich normalerweise über weitere Distanzen als die Dendriten.
Lesen Sie auch: Ursachen, Symptome und Behandlungen von Motoneuron-Erkrankungen
Bereits 1943 schlugen Warren McCulloch und Walter Pitts ein informationstechnisches Modell des biologischen Neurons vor: das McCulloch-Pitts-Neuron. Das Modell verarbeitete eingehende Signale durch Aufsummieren und kontrollierte die Weiterleitung durch einen Schwellwert. Es wurde gezeigt, dass die grundlegenden booleschen Operatoren (AND, OR, NOT) realisiert werden können.
Das Perzeptron (engl. perceptron) hatte bereits ein verfeinertes Modell und vor allem einen Lernalgorithmus (allerdings nur für ein Perzeptron mit einer Schicht). Es wurde 1958 von Frank Rosenblatt in einer Publikation der Öffentlichkeit vorgestellt. 1969 gewann das Perzeptron größere Bekanntheit durch eine Buchpublikation der KI-Pioniere Marvin Minsky und Seymour Papert. Durch das Buch wurden auch die Grenzen des Perzeptrons (sogenanntes XOR-Problem) bekannt. Das Adaline (ADAptive Linear NEuron) wurde 1960 von Bernard Widrow eingeführt.
Auch wenn künstliche NN von biologischen Neuronen inspiriert sind, ist es doch wichtig festzuhalten, dass die Funktionsweise eines künstlichen NN wenig Rückschlüsse auf das menschliche Denken oder auf die Funktionsweise des menschlichen Hirns zulässt. In einem natürlichen Neuron spielen viele Faktoren (biologische, chemische, physikalische) eine Rolle, die in einem künstlichen Neuronalen Netz nicht modelliert sind. Das Lernverfahren “Backpropagation”, mit dem künstliche NN trainiert werden, hat wenig mit biologischen Vorgängen zu tun. Mit der Frage, inwiefern menschliches Denken mit Hilfe von informationstechnischen Modellen erforscht werden kann, beschäftigt sich die Kognitionswissenschaft.
Die Struktur eines KNN
Künstliche neuronale Netze können unterschiedlich komplex aufgebaut sein, haben aber im Wesentlichen die Struktur gerichteter Graphen. Vereinfacht kann man sich den Aufbau eines KNN wie folgt vorstellen:
Das Modell des Neuronalen Netzes besteht aus Knoten, auch Neuronen genannt, die Informationen von anderen Neuronen oder von außen aufnehmen, modifizieren und als Ergebnis wieder ausgeben. Die Information wird durch die Input-Neuronen aufgenommen und durch die Output-Neuronen ausgegeben. Die Hidden-Neuronen liegen dazwischen und bilden innere Informationsmuster ab. Die Neuronen sind miteinander über sogenannte Kanten verbunden.
Lesen Sie auch: Fliegen und Drohnen im Fokus
Ein typisches KNN besteht aus folgenden Schichten:
Eingabeschicht: Die Eingangsschicht versorgt das neuronale Netz mit den notwendigen Informationen. Die Input-Neuronen verarbeiten die eingegebenen Daten und führen diese gewichtet an die nächste Schicht weiter.
Verborgene Schicht: Die verborgene Schicht befindet sich zwischen der Eingabeschicht und der Ausgabeschicht. Während die Ein- und Ausgabeschicht lediglich aus einer Ebene bestehen, können beliebig viele Ebenen an Neuronen in der verborgenen Schicht vorhanden sein. Hier werden die empfangenen Informationen erneut gewichtet und von Neuron zu Neuron bis zur Ausgabeschicht weitergereicht. Die Gewichtung findet in jeder Ebene der verborgenen Schicht statt. Die genaue Prozessierung der Informationen ist jedoch nicht sichtbar. Daher stammt auch der Name, verborgene Schicht.
Ausgabeschicht: Die Ausgabeschicht ist die letzte Schicht und schließt unmittelbar an die letzte Ebene der verborgenen Schicht an.
Die Verarbeitung im Neuron
Was im Inneren eines solchen Perceptrons oder Neurons vorgeht, ist erstaunlich einfach. Die Eingangssignale werden mit den Gewichten (engl. "weights") multipliziert, jeder Eingang hat sein zugeordnetes Gewicht. Wenn also ein Signal ankommt, wird es mit dem Wert des Gewichts des individuellen Eingangs multipliziert, das diesem Eingang zugeordnet ist. So hat ein Neuron mit drei Eingängen auch drei Gewichte, die individuell angepasst werden können. Danach werden die Eingangssignale summiert. Es ist auch möglich, einen sogenannten Bias "b" dazu zu addieren, der ein von anderen Neuronen unabhängiges Eingangssignal darstellt. Schliesslich wird er Ausgangswert festgelegt. Die einfachste Form einer Aktivierungsfunktion ist eine Binärfunktion.
Lesen Sie auch: Die Rolle des Zellkörpers in Neuronen
Aktivierungsfunktionen
Die Aktivierungsfunktion ist meist eine monoton steigende und differenzierbare Funktion, die (stückweise) linear oder nichtlinear sein kann. Häufig verwendete Aktivierungsfunktionen sind die Sigmoid-, die Tanh- und die ReLU-Funktion.
Lernen im neuronalen Netz
Tiefes Lernen ist eine Hauptfunktion eines KNN und funktioniert wie folgt: Bei einer vorhandenen Netzstruktur bekommt jedes Neuron ein zufälliges Anfangsgewicht zugeteilt. Das Ergebnis dieser Berechnung wird an die nächsten Neuronen der nächsten Schicht oder des nächsten Layers weitergegeben, man spricht auch von einer „Aktivierung der Neuronen“. Natürlich sind, wie bei jedem maschinellen Lernverfahren, nicht alle Ergebnisse (Outputs) korrekt und es treten Fehler auf. Diese Fehler sind berechenbar, ebenso wie der Anteil eines einzelnen Neurons am Fehler. Im nächsten Durchlauf wird der Fehler erneut gemessen und angepasst. Dieser Prozess ist dem menschlichen Entscheidungsprozess sehr ähnlich.
Lernen bedeutet, dass die Gewichte mit Hilfe von Trainingsdaten schrittweise angepasst werden, so dass unser Netzwerk sich der gewünschten idealen Funktion annähert. Trainingsdaten sind z.B. eine Reihe von Bildern mit Labeln (z.B. Katze und Nicht-Katze). Wir gehen von Traningsdaten aus und verwenden als Index für ein Trainingsbeispiel. Bei handelt es sich um den korrekten Output des Trainingsbeispiels. Lernen bedeutet, dass wir für jedes Trainingsbeispiel den Output berechnen und die Gewichte so anpassen, dass der Fehler, also die Differenz zwischen berechnetem und korrekten Output, kleiner wird. Dazu addieren wir auf jedes Gewicht ein “Delta”.
Gradientenabstieg
Unsere Herleitung folgt der Idee des Gradientenabstieg und dieses Verfahren bedeutet etwas ganz Einfaches: Wenn wir einen Parameter haben und diesen leicht vergrößern, wird dann der Fehler kleiner oder größer?
Wir wollen die Gewichte so anpassen, dass der Fehler sich verringert. Dazu gehen wir in Richtung des negativen Gradienten, denn der Gradient gibt uns den größten Anstieg. Aufgrund der obigen Ausführungen können wir das Delta definieren als den negativen Gradienten des Fehlers definieren. Denken Sie immer daran, dass sich die Gewichte im Verlauf des Trainings ändern. Das in dem Ausdruck soll deutlich machen, dass wir in die Ableitungen immer konkrete Werte im Form des Gewichtsvektors einsetzen. Die Gewichte sind sozusagen die “aktuelle Konfiguration” des Netzwerks.
Die Lernrate wird zwischen 0 und 1 gewählt und bestimmt, wie schnell das Lernen stattfindet. Eine zu hohe Lernrate kann dazu führen, dass das Optimum immer wieder “übersprungen” wird, so dass das Lernen doch wieder langsamer wird oder sogar nie das Optimum erreicht. Eine zu niedrige Lernrate kann zu sehr langsamen Lernprozessen führen. Als Daumenregel sollte man mit niedrigen Lernraten beginnen und diese dann schrittweise erhöhen.
Lernalgorithmus
Angesichts unserer Herleitung formulieren wir einen Lernalgorithmus. Man beachte, dass wir das innerhalb einer Epoche als Speicher benutzen, um alle Deltas für alle Trainingsdaten “einzusammeln” (zu aggregieren).
- Setze alle Gewichte, z.B. auf Null oder zufällige Werte.
- Für jede Epoche:
- Setze alle auf Null.
- Für jedes Trainingsbeispiel k:
- Berechne Ausgabe.
- Berechne Delta für alle Gewichte.
- Addiere Delta zum entsprechenden .
- Update alle Gewichte: .
- Berechne den Fehler über alle Trainingsbeispiele.
Wie viele Epochen zum Training genutzt werden, ist dem Anwender überlassen. In der Regel wählt man eine Epochenzahl, z.B. 100.
Neuronale Netze in der Praxis
Anwendungsbereiche
Wo finden denn nun solche Netzwerke Anwendungen? Nun, da gibt es zahlreiche Möglichkeiten. Typischerweise sind sie prädestiniert für solche Bereiche, bei denen wenig systematisches Wissen vorliegt, aber eine große Menge unpräziser Eingabeinformationen (unstrukturierte Daten) verarbeitet werden müssen, um ein konkretes Ergebnis zu erhalten. Das kann zum Beispiel in der Spracherkennung, Mustererkennung, Gesichtserkennung oder Bilderkennung der Fall sein.
Zahlreiche Produkte und Dienstleistungen, die auf künstlichen neuronalen Netzen basieren, haben bereits Einzug in unseren Alltag gehalten. Künstliche Neuronale Netze spielen in vielen Bereichen eine wichtige Rolle. Neuronale Netze ermöglichen es, unterschiedliche Datenquellen wie Bilder, Töne, Texte, Tabellen oder Zeitreihen zu interpretieren und Informationen oder Muster zu extrahieren, um diese auf unbekannte Daten anzuwenden.
Typen von neuronalen Netzwerk-Architekturen
Es gibt unzählig viele Typen von neuronalen Netzwerk-Architekturen. Hier eine kleine Auswahl:
Perzeptron: Das einfachste und älteste neuronale Netz. Es nimmt die Eingabeparameter, addiert diese, wendet die Aktivierungsfunktion an und schickt das Ergebnis an die Ausgabeschicht. Das Ergebnis ist binär, also entweder 0 oder 1 und damit vergleichbar mit einer Ja- oder Nein-Entscheidung. Die Entscheidung erfolgt, indem man den Wert der Aktivierungsfunktion mit einem Schwellwert vergleicht. Bei Überschreitung des Schwellwertes, wird dem Ergebnis eine 1 zugeordnet, hingegen 0 wenn der Schwellwert unterschritten wird. Darauf aufbauend wurden weitere Neuronale Netzwerke und Aktivierungsfunktionen entwickelt, die es auch ermöglichen mehrere Ausgaben mit Werten zwischen 0 und 1 zu erhalten. Am bekanntesten ist die Sigmoid-Funktion, in dem Fall spricht man auch von Sigmoid-Neuronen.
Feedforward-Netzwerke: Der Ursprung dieser neuronalen Netze liegt in den 1950 Jahren. Sie zeichnen sich dadurch aus, dass die Schichten lediglich mit der nächst höheren Schicht verbunden sind. Es gibt keine zurückgerichteten Kanten.
Faltende Neuronale Netze (CNN): Faltende Neuronale Netze oder auch Convolutional Neural Networks (CNN), sind Künstliche Neuronale Netzwerke, die besonders effizient mit 2D- oder 3D-Eingabedaten arbeiten können. Der große Unterschied zu den klassischen neuronalen Netzen liegt in der Architektur der CNNs, die auch den Namen „Convolution“ oder „Faltung“ erklärt. Bei CNNs basiert die verborgene Schicht auf einer Abfolge von Faltungs- und Poolingoperationen. Bei der Faltung wird ein sogenannter Kernel über die Daten geschoben und währenddessen eine Faltung berechnet, was mit einer Multiplikation vergleichbar ist. Die Neuronen werden aktualisiert. Die anschließende Einführung einer Pooling-Schicht sorgt für eine Vereinfachung der Ergebnisse. Dies sorgt auch dafür, dass die 2D- oder 3D-Eingangsdaten kleiner werden. Setzt man diesen Prozess fort, so erhält man am Ende in der Ausgabeschicht einen Vektor, den „fully connected layer“.
Rekurrente Neuronale Netze (RNN): Recurrent Neural Networks (RNN) fügen den KNN wiederkehrende Zellen hinzu, wodurch neuronale Netze ein Gedächtnis erhalten. Das erste künstliche, neuronale Netzwerk dieser Art war das Jordan-Netzwerk, bei dem jede versteckte Zelle ihre eigene Ausgabe mit fester Verzögerung - eine oder mehrere Iterationen - erhielt. Natürlich gibt es viele Variationen, wie z.B. die Übergabe des Status an die Eingangsknoten, variable Verzögerungen usw., aber die Grundidee bleibt die gleiche. Diese Art von NN wird insbesondere dann verwendet, wenn der Kontext wichtig ist. In diesem Fall haben Entscheidungen aus früheren Iterationen oder Stichproben einen signifikanten Einfluss auf die aktuellen Iterationen. Da rekurrente Netze jedoch den entscheidenden Nachteil haben, dass sie mit der Zeit instabil werden, ist es mittlerweile üblich, sogenannte Long Short-Term Memory Units (kurz: LSTMs) zu verwenden. Das häufigste Beispiel für solche Abhängigkeiten ist die Textverarbeitung - ein Wort kann nur im Zusammenhang mit vorhergehenden Wörtern oder Sätzen analysiert werden. Ein weiteres Beispiel ist die Verarbeitung von Videos, z.B. beim autonomen Fahren.
Programmierung eines Perzeptrons in Python
Wir implementieren das Perzeptron in Python, um die Funktionsweise besser zu verstehen.
Datensatz: Der Iris-Datensatz
Im Iris-Datensatz geht es darum, eine Blume aufgrund der Abmessungen ihrer Blüte zu klassifizieren. Es gibt drei Blumen-Klassen, die es vorherzusagen gilt: iris setosa, iris virginica und iris versicolor. Es gibt vier Blüten-Abmessungen als Eingabe-Features für den Input: sepal length, sepal width, petal length und petal width (“sepal” ist das Kelchblatt und “petal” das Kronblatt, siehe Wikipedia). Der für den Einstieg sehr beliebte, sehr kleine Iris-Datensatz stammt aus dem Jahr 1936. Bei diesem Datensatz geht es um Blumen, genauer gesagt um die Gattung der “Schwertlilien”, deren lateinischer Name Iris lautet. Der Datensatz besteht nur aus 150 Trainingsbeispielen. In der Sammlung sind 150 Dateneinträge, jeweils 50 pro Klasse.
Python-Code
import numpy as np# Trainingsdaten (Beispiel)training_inputs = np.array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]])training_outputs = np.array([0, 1, 1, 0]).T# Initialisiere Gewichte zufällignp.random.seed(1)synaptic_weights = 2 * np.random.random((3, 1)) - 1# Sigmoid Funktiondef sigmoid(x): return 1 / (1 + np.exp(-x))# Ableitung der Sigmoid Funktiondef sigmoid_derivative(x): return x * (1 - x)# Trainingfor iteration in range(10000): input_layer = training_inputs outputs = sigmoid(np.dot(input_layer, synaptic_weights)) # Berechne den Fehler error = training_outputs - outputs # Gewichte anpassen adjustments = error * sigmoid_derivative(outputs) synaptic_weights += np.dot(input_layer.T, adjustments)print("Gewichte nach dem Training:")print(synaptic_weights)print("Ausgabe nach dem Training:")print(outputs)Dieser Code demonstriert ein einfaches neuronales Netzwerk, das auf dem Konzept des Perzeptrons basiert. Er verwendet die Sigmoid-Funktion als Aktivierungsfunktion und trainiert das Netzwerk durch Anpassung der Gewichte, um die Fehler zwischen den vorhergesagten Ausgaben und den tatsächlichen Ausgaben zu minimieren.
Erweiterung des Codes
Der obige Code kann erweitert werden, um komplexere neuronale Netze zu implementieren, die in der Lage sind, anspruchsvollere Aufgaben zu lösen. Hier sind einige Möglichkeiten, den Code zu erweitern:
- Hinzufügen von versteckten Schichten: Durch Hinzufügen von versteckten Schichten kann das Netzwerk komplexere Muster in den Daten erkennen.
- Verwendung anderer Aktivierungsfunktionen: Es gibt viele verschiedene Aktivierungsfunktionen, die für verschiedene Arten von Problemen geeignet sind.
- Implementierung von Backpropagation: Backpropagation ist ein Algorithmus, der verwendet wird, um die Gewichte in einem neuronalen Netzwerk mit mehreren Schichten zu trainieren.
- Verwendung von Frameworks wie TensorFlow oder Keras: Diese Frameworks bieten eine einfache Möglichkeit, komplexe neuronale Netze zu erstellen und zu trainieren.
tags: #neuron #programmieren #python