Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ss15:neuronale_netze

Neuronale Netze

Was ist ein Neuronales Netz?

Ein Neuronales Netz besteht aus Schichten von Neuronen. Jedes Neuron hat eine gewisse Zahl an Inputs und Gewichten. Die Inputs werden mit den Gewichten verrechnet und in die Sigmoid-Funktion1) eingesetzt. Dies ist der Output des Neurons.

Ein Neuronales Netz besteht nun aus mehreren Schichten solcher Neuronen, wobei die Outputs der einen Schicht die Inputs der nächsten Schicht sind. Wenn man nun ein Neuronales Netz anlegt, so werden die Gewichte zunächst zufällig besetzt. Allerdings werden diese im Trainingsprozess angepasst. Das funktioniert folgendermaßen:

  • Zunächst braucht man einen Datensatz mit Inputs und erwarteten Outputs.
  • Dann berechnet man den quadratischen Fehler zwischen dem Output, den das Netz bei einem Input liefert und dem dabei erwarteten Output.
  • Nun kann man mittels Backtracking die einzelnen Gewichte nacheinander updaten. Dazu bildet man die partielle Ableitung der Fehlerfunktion nach jedem Gewicht und updatet jedes einzelne Gewicht mithilfe des Gradientenabstiegs.

Nachdem man diesen Prozess einige Male wiederholt hat, sollte das Netz in der Lage sein, ähnliche Probleme zu lösen. Es gibt hier jedoch einige Dinge zu beachten: Das Netzwerk kann overfitten.

Das bedeutet, dass das Netzwerk nicht mehr die Struktur des Problems lernt, sondern die Trainingsmenge. Das Netz ist dann zwar in der Lage, in der Trainingsmenge unglaublich gute Vorhersagen zu treffen, allerdings fallen die Lösungen für neue Daten sehr schlecht aus. Es gibt allerdings ein paar Möglichkeiten, dieses Problem zu lösen:

  • Einführung einer Lernrate: Indem man die einzelnen Updateschritte nur ziemlich klein hält, kann man verhindern, dass das Netz zu schnell overfittet
  • Weightdecay: Hierbei laufen ungenutzte Gewichte langsam gegen 0; Das verhindert ebenfalls Overfitting des Netzes
  • Cross-Validation: Dabei wird nach jedem Update die Erfolgsrate des Netzes an einer kleineren, seperaten Testmenge berechnet. Sobald diese kleiner wird, kann man aufhören zu trainieren.

Wie programmiert man ein Neuronales Netz?

In meinem selbstgeschriebenen Beispiel habe ich versucht, die Struktur des Netzes so einfach wie möglich in Programmcode zu übertragen. Dafür habe ich eine Klasse neuron.py geschrieben. Jedes Neuron erwartet zunächst eine Liste mit Gewichten. Dann kann die $\texttt{processInput()}$-Methode den Output zu den jeweiligen Inputs berechnen.

$\texttt{self.value}$ hält dabei den Wert, bevor die Sigmoid-Funktion anhewendet wurde, $\texttt{self.output}$ trägt den tatsächlichen Output. $\texttt{actFunc()}$ und $\texttt{derivedActFunc()}$ sind noch die Sigmoid-Funktion bzw. die abgeleitete Sigmoid-Funktion.

Der Kern des Programms liegt jedoch im Modul network.py: Die Klasse $\texttt{Network}$ erwartet zunächst eine Liste mit der Anzahl der Neuronen pro Schicht. Dann wird ein ebesolches Netzwerk angelegt, bei dem die Outputs der einen Schicht gleichzeitig die Inputs der nächsten Schicht sind und alle Gewichte zufällig gesetzt sind.

Der wichtigste Teil ist die $\texttt{update()}$-Funktion. Diese erwartet einen Input und dazugehörigen Output aus einer Trainingsmenge. Zunächst wird dann der tatsächliche Output mithilfe der $\texttt{getOutput()}$-Methode berechnet. Im zweiten Teil werden dann die partiellen Ableitungen nach jedem Neuron berechnet (es ist tatsächlich nicht ganz so kompliziert wie es aussieht, dennoch ist das Ganze recht fehleranfällig und hat mich einige Nerven gekostet). Die neuen Gewichte werden dann zunächst in der $\texttt{newWeightsList[]}$ gespeichert un sie später dann alle in einem Schritt zu updaten.

Die Funktion $\texttt{updateDataset()}$ iteriert dann die $\texttt{update()}$-Methode auf eine ganze Menge von Beispieldaten. Die $\texttt{testDataset}$-Methode hingegen testet die Erfolgsrate des Netzed auf einer Menge, indem sie die Vorhersage des Netzes mit der tatsächlichen Antwort vergleicht.

Nun noch etwas zum Problem, auf das ich mein Netz angesetzt habe: Jeden Tag werden Millionen von Briefen und Paketen verschickt. Dabei ist es nicht sehr effizient, wenn jede Postleitzahl von Postbeamten eingelesen werden müssten. Stattdessen wäre ein Computerprogramm, dass diese Aufgabe löst, sehr praktisch. Zwar wurde dieses Problem schon unzählige Male gelöst, ist aber ein sehr dankbares Anfängerproblem, weil es genügend Testdatensätze und Dokumentationen gibt. In meinem Datensatz liegt dabei jede Zahl als $16\cdot{}16$ Pixel Graustufenbild vor.

Im Datensatz ist jedes Bild folgendermaßen gespeicher: Zunächst hat man 256 Werte zwischen -1 und 1, die die Graustufe reprästentieren und zum Schluss eine Zahl, die angibt, welches Zahl das Bild tatsächlich darstellt. Um das Netz zu trainieren, übergebe ich also einen Vektor mit 256 Einträgen und einen Vektor mit 10 Einträgen, wobei alle 0 sind, außer demjenigen, der der Zahl entspricht, die das Bild darstellt. Dieser ist auf 1 gesetzt. Dies alles ist im Modul readfile.py gespeichert.

Das verwendete Netz ist recht einfach; es hat 3 Schichten mit 256, 12, und 10 Neuronen. Mein Netz hat es dabei geschafft, etwas mehr als 90% richtig zuzuordnen. Komplexer aufgebaute Netze mit mehr Schichten, in dem Neuronen von zwei aufeinanderfolgenden Schichten auch nicht immer miteinander verbunden sind, haben es geschafft, mehr als 99,5% korrekt zuzuordnen.

Andere Anwendungsbereiche von Neuronalen Netzen sind beispielsweise Vorhersage von Ereignissen oder Mustererkennung.

1) Diese sorgt lediglich dafür, dass der Output zwischen 0 und 1 liegt und sieht so aus: $\frac{1}{1+e^{-x}}$
ss15/neuronale_netze.txt · Zuletzt geändert: 2016/05/10 14:46 (Externe Bearbeitung)