Neuronale Netze

“I always wondered how it would be if a superior species landed on earth and showed us how they played chess”, liess der dänische Schachmeister Peter Heine Nielsen kürzlich in einem Interview mit der BBC verlauten. “Now I know.”

Was er damit ansprach war Googles künstliche Intelligenz Alpha Zero, die sich in nur vier Stunden und mit der blossen Kenntnis der grundlegenden Schachregeln selbständig zu einem der besten Schachspieler der Welt coachte und anschliessend der etablierten Schachsoftware Stockfish 8 in 100 Partien den Meister zeigte. Alpha Zeros Spiel ist faszinierend. Die künstliche Intelligenz scheint sehr viel Wert auf aussichtsreiche Stellungen zu legen und nimmt dafür auch grosse Material-Verluste in Kauf, sprich opfert wichtige Figuren. Auf dem Youtube-Channel Agmador’s Chess Channel sind Analysen der Spiele zwischen Alpha Zero und Stockfish 8 zu finden, die ich sehr interessant finde (ich habe ein Video aus dieser Serie unten angehängt).

Das obige Beispiel ist nur eines von vielen, das die heutigen Möglichkeiten im Bereich der künstlichen Intelligenz eindrücklich aufzeigt. Doch wie genau funktioniert künstliche Intelligenz? Was sind die grundlegenden Ideen? Um der Beantwortung dieser Fragen näher zu kommen, werde ich in diesem Beitrag ein Klassifikations-Problem aus dem Gebiet Supervised Machine Learning und mehrere Lösungsansätze dazu vorstellen. Der Inhalt des Beitrags basiert sowohl auf der Vorlesung Introduction to Machine Learning, die ich im letzten Semester an der ETH Zürich besucht habe, als auch auf der Website A Neural Network Playground von Googles Machine Learning Framework Tensorflow.

Ein häufig vorkommendes Problem in (Supervised) Machine Learning ist die Klassifikation von Daten. Ausgehend von einem Trainings-Datenset \left \{(\vec{x}_1, y_1), \dots, (\vec{x}_n, y_n) \right \} mit Input-Vektoren \vec{x}_i (z.B. medizinische Angaben wie das Alter, das Gewicht, der Blutdruck, etc. eines Patienten) und Labels y_i (z.B. ob der Patient eine gewisse Krankheit hat oder nicht) soll ein Modell trainiert werden, das anschliessend neuen Input-Vektoren \vec{x} ein geschätztes Label \hat{y}(\vec{x}) zuordnen kann, das möglichst genau mit dem echten (eventuell unbekannten) Label y übereinstimmt.

Um quantifizieren zu können, wie gut die Vorhersagen eines Modells sind, muss eine sogenannte Loss-Funktion l(y, \hat{y}) definiert werden. Die Argumente dieser Funktion sind das wahre Label y und das geschätzte Label \hat{y}(\vec{x}). Der Funktionswert der Loss-Funktion wird grösser, je weiter entfernt das wahre Label vom geschätzten liegt. Um ein Modell dem Trainings-Datenset anzupassen, müssen die Parameter des Modells also so gewählt werden, dass \sum_{i = 1}^{n}l(y_i, \hat{y}(\vec{x}_i)) minimal wird (dann sind nämlich die Vorhersagen des Modells optimal).

Lineare Modelle

Die einfachsten Modelle liefern geschätzte Labels \hat{y}(\vec{x}), die linear von den Input-Vektoren \vec{x} \equiv (x^1, \dots, x^d) abhängen:

\hat{y}(x^1, \dots, x^d) = \sum_{j = 1}^d w^j x^j,

wobei \vec{w} = (w^1, \dots, w^d) die Parameter des Modells sind. Dieses Modell kann dem Trainings-Datenset angepasst werden, indem

\vec{w} = \arg \! \min \sum_{i = 1}^n l(y_i, \sum_{j = 1}^d w^j x^j_i)

als Parameter gewählt werden. Obige Optimierung wird numerisch mit dem Algorithmus Gradient Descent durchgeführt. Die sogenannten Decision Boundaries linearer Modelle, sprich die Grenzen im Raum der Input-Vektoren \vec{x} zwischen verschiedenen “Label-Gebieten”, sind natürlich linear in \vec{x} (siehe Abbildung).

Darstellung eines linearen Modells, das einer Trainings-Datenmenge angepasst wurde. Die (zweidimensionalen) Input-Vektoren entsprechen den Positionen der Punkte, die dazugehörigen Labels den Farben (orange/blau). Die Decision Boundary des linearen Modells ist in weiss gezeigt. Input-Vektoren unterhalb der Decision Boundary wird vom Modell das orange Label zugewiesen, Input-Vektoren oberhalb das blaue Label.

Dies wird zu einem Problem, sobald das Problem nicht mehr mit einer linearen Decision Boundary gelöst werden kann.

Dieses Problem kann nicht sinnvoll mit einem linearen Modell gelöst werden. Auf beiden Seiten der linearen Decision Boundary (weiss) gibt es viele orange wie auch blaue Punkte.

Auch bei diesem Problem scheitert das Modell.

 

Nicht-lineare Modelle (Feature-Transformation)

Mit dem Trick der Feature-Transformation kann man im Grunde lineare Modelle zu nicht-linearen erweitern. Die Idee dabei ist, dass eine nicht-lineare Feature-Transformation \phi: \mathbb{R}^{d} \mapsto \mathbb{R}^{d^\prime} auf die Input-Vektoren angewendet wird.

Beispiel: Für d = 2, d^\prime = 5:

\phi: (x^1, x^2) \mapsto (x^1, x^2, x^1x^1, x^1x^2, x^2x^2).

Auf den transformierten Input-Vektoren kann dann ein lineares Modell trainiert werden:

\hat{y}(x^1, \dots, x^d) = \sum_{j = 1}^{d^\prime} w^j \phi^j(x^1, \dots, x^d),

wobei \vec{w} = (w^1, \dots, w^{d^\prime}) wiederum die Parameter des Modells sind. Dieses Modell kann analog zu oben dem Trainings-Datenset angepasst werden, indem

\vec{w} = \arg \! \min \sum_{i = 1}^n l(y_i, \sum_{j = 1}^{d^\prime} w^j \phi^j(x_i^1, \dots, x_i^d))

als Parameter gewählt werden. Dadurch kann die Vielfalt der Datenmengen, die durch das Modell klassifiziert werden können, stark vergrössert werden.

Dieses Datenset kann nun vom nicht-linearen Modell mit der Feature-Transformation aus dem Beispiel oben sinnvoll klassifiziert werden.

Das Modell scheitert aber weiterhin an diesem Datenset, da es auch mit den (wie im Beispiel oben gewählten) transformierten Input-Vektoren nicht beschrieben werden kann.

 

Neuronale Netze

Obwohl man durch den oben beschriebenen Trick der Feature-Transformation eine Vielzahl von Datensets sinnvoll klassifizieren kann, hat diese Herangehensweise einen entscheidenen Nachteil: die Feature-Transformationen müssen quasi “von Hand” ausgewählt werden, d.h. es muss im Vornherein klar sein, welche transformierten Input-Vektoren sinnvoll zur Klassifizierung eines Datensets sind. Wie oben gezeigt ist die Feature-Transformation aus dem Beispiel nicht sinnvoll, um das Datenset mit der Spirale zu klassifizieren. Es wäre also raffiniert, wenn die Auswahl der “sinnvollen” Feature-Transformationen auch Teil des Trainings-Prozesses wären, also anhand des Trainings-Datensets optimiert werden würde. Genau dies ist die Idee von Neuronalen Netzen.

Neuronale Netze sind meist aus mehreren Layers aufgebaut. Das heisst, dass aus dem Input-Vektor \vec{x} zuerst Werte für die Knoten (Neuronen) der nachfolgenden Schichten berechnet werden, aus denen dann schlussendlich das geschätzte Label \hat{y}(\vec{x}) folgt. In der Folge werden die Schichten mit Subskripts (0), \dots, (f) notiert, wobei die Schicht (0) dem Input-Vektor \vec{x} entspricht und die Schicht (f) dem geschätzten Label \hat{y}. Die Anzahl Knoten in den jeweiligen Schichten wird mit d_{(l)} für l = 0, \dots, f notiert, sprich für das Beispiel im Bild unten gilt:

f = 3,
d_{(0)} = 2, d_{(1)} = 5, d_{(2)} = 5, d_{(3)} = 1.

Die d_{(l)} Werte der l-ten Schicht werden mit V_{(l)}^j für j = 1, \dots, d_{(l)} notiert.

Aus den Input-Komponenten x¹ und x² werden die Werte für die je 5 Knoten (Neuronen) in den zwei nachfolgenden Schichten berechnet, aus denen dann das geschätzte Label errechnet wird (im Output-Bild dargestellt).

Aus den Werten V_{(l)}^j der d_{(l)} Knoten der l-ten Schicht folgen die Werte V_{(l+1)}^k der d_{(l+1)} Knoten der nächsten Schicht folgendermassen:

V_{(l+1)}^k = \varphi (\sum_{j = 1}^{d_{(l)}} w_{(l+1)}^{kj} V_{(l)}^j) , \quad k = 1, \dots, d_{(l+1)}.

Die Bedeutung der Funktion \varphi und der Gewichts-Matrix w_{(l+1)} werden weiter unten diskutiert. Die nullte Schicht des Neuronalen Netzes besteht ganz einfach aus dem Input-Vektor, sprich

V_{(0)}^j = x^j , \quad j = 1, \dots, d_{(0)} = d.

Aus den d_{(f-1)} Werten der Knoten der zweitletzten Schicht V_{(f-1)}^j kann dann das geschätzte Label \hat{y}(\vec{x}, w_{(1)}, \dots, w_{(f)}) folgendermassen berechnet werden:

\hat{y}(\vec{x}, w_{(1)}, \dots, w_{(f)}) = \sum_{j = 1}^{d_{(f-1)}} w_{(f)}^{1j} V_{(f-1)}^j.

Beachte, dass die Input-Parameter \vec{x}, w_{(1)}, \dots, w_{(f-1)} wie oben beschrieben in den Werten der Knoten der zweitletzten Schicht V_{(f-1)}^j “verarbeitet” sind.

Das beschriebene Prinzip, dass ausgehend von den Werten der Knoten der einen Schicht die Werte der Knoten der folgenden Schicht berechnet werden, bis man schlussendlich das geschätzte Label \hat{y} erhält, wird Forward Propagation genannt. Es ist im Grunde ganz einfach, sieht aber in voller Notation zugegebenermassen etwas komplex aus.

Es bleiben zwei Konzepte zu diskutieren, die in obigen Formeln zur Forward Propagation auftauchen, ohne genauer erläutert worden zu sein. Ersteres ist die sogenannte Activation Function \varphi. Es handelt sich dabei um eine fest gewählte nicht-lineare Funktion. Die gängigsten Activation Functions sind:

Sigmoid: \varphi(z) = \frac{1}{1 + \exp{(-z)}}
Tanh: \varphi(z) = \text{tanh}(z)
ReLU: \varphi(z) = \text{max}(z, 0),

deren Plots folgendermassen aussehen:

Plots der drei gängigsten Activation Functions: Sigmoid, Tanh und ReLU.

Die Funktion der Activation Function lässt sich am besten anhand einer Analogie aus der Biologie verdeutlichen: Neuronen im menschlichen Gehirn besitzen eine Activation Function in Form einer Stufenfunktion. Liegt das Potential aller einlaufenden Stimuli unter dem sogenannten Schwellpotential des Neurons, so wird kein Puls weitergegeben (Wert 0), wird  das Schwellpotential erreicht, so feuert das Neuron einen Puls ab (Wert 1). Die Knoten in den künstlichen Neuronalen Netzen funktionieren auf eine ähnliche Weise: die (gewichtete) Summe aller Stimuli (Werte der Knoten in der vorangehenden Schicht) werden der Activation Function \varphi als Input übergeben, welche dann den Wert des Knotens in der neuen Schicht bestimmt. Die Sigmoid- und die Tanh-Funktion stellen kontinuierliche (und insbesondere stetig differenzierbare) Versionen der Stufenfunktion dar. Die ReLU-Funktion ist nicht mehr wirklich eine Stufenfunktion und auch nicht in allen Punkten differenzierbar, hat aber gegenüber den anderen Activation Functions gewisse Vorteile, weshalb sie in der Praxis häufig eingesetzt wird. Wie im menschlichen Gehirn sind auch die Activation Functions in künstlichen Neuronalen Netzen fest programmiert, das heisst sie werden zu Beginn festgelegt und können im Lernprozess des Netzwerks nicht verändert werden.

Den durch das Lernen veränderlichen Teil des Netzwerkes stellen die Gewichts-Matrizen w_{(1)}, \dots, w_{(f)} dar, womit wir beim zweiten der beiden noch zu diskutierenden Konzepte angelangt wären. Die Matrix w_{(l)} ist ein Element von \mathbb{R}^{d_{(l)} \times d_{(l-1)}}. Der Koeffizient w_{(l)}^{kj} gibt den Einfluss (bzw. das Gewicht) des Wertes des j-ten Knoten V_{(l-1)}^j der Schicht (l-1) auf den Wert des k-ten Knoten V_{(l)}^k der Schicht (l) an. Falls der Koeffizient positiv ist, so bewirkt ein hoher Wert des Knotens V_{(l-1)}^j einen höheren Wert des Knotens V_{(l)}^k. Ist der Koeffizient dagegen negativ, so verkleinert ein hoher Wert des Knotens V_{(l-1)}^j den Wert des Knotens V_{(l)}^k. Im Bild oben sind positive Koeffizienten als blaue Verbindungslinien dargestellt, negative dagegen als orange Verbindungslinien. Die optimalen Gewichts-Matrizen werden wiederum über das Trainings-Datenset \left \{(\vec{x}_1, y_1), \dots, (\vec{x}_n, y_n) \right \} bestimmt. Es muss das Optimierungs-Problem

(w_{(1)}, \dots, w_{(f)}) = \arg \! \min \sum_{i = 1}^n l(y_i, \hat{y}(\vec{x_i}, w_{(1)}, \dots, w_{(f)}))

gelöst werden, was mithilfe der sogenannten Backpropagation und Gradient Descent umgesetzt werden kann.

Der Vorteil von Neuronalen Netzen ist nun, dass die Auswahl der “sinnvollen” Feature-Transformationen Teil der Optimisierung ist, die basierend auf dem Trainings-Datenset durchgeführt wird. Durch die Wahl der Gewichts-Matrizen w_{(1)}, \dots, w_{(f-1)} werden für die Klassifikation relevante Features bestimmt. Diese sind in obigem Bild auf den Knoten des Neuronalen Netzes dargestellt.

Wie schlagen sich Neuronale Netze nun in der Praxis? Nach einminütigem Training ist das Neuronale Netz mit zwei Zwischenschichten à 5 Knoten imstande, das Klassifikationsproblem mit der Spirale zu lösen. Als Activation Function habe ich die ReLU-Funktion gewählt. Da die ReLU-Funktion keine negativen Werte annehmen kann, nehmen die unten dargestellten Features auf den Knoten nur die Farben weiss (0) und blau (positiv), nicht jedoch orange (negativ) an.

Nach kurzem Training ist das Neuronale Netzwerk imstande, das Klassifikationsproblem mit der Spirale zu lösen. Als Activation Function wurde die ReLU-Funktion gewählt.

Die beiden anderen vorgestellten Klassifikationsprobleme werden von diesem Neuronalen Netzwerk nach kurzem Training ebenfalls mit Leichtigkeit gelöst.

A Neural Network Playground

Die obigen Illustrationen und Beispiele basieren auf dem Neural Network Playground, der von Googles Machine Learning Framework Tensorflow zur Verfügung gestellt wurde. Meiner Meinung nach ist die Seite extrem übersichtlich gemacht und illustriert die Aspekte von Neural Networks auf eine intuitive Art und Weise. Ein Besuch lohnt sich auf alle Fälle!

Quellen

Quellen Bilder

Leave a comment