JGU Logo JGU Logo JGU Logo JGU Logo

Institut für Informatik

Modellierung 2

Michael Wand
Ann-Christin Wörl & David Hartmann
Sommersemester 2023

Lehreinheit 10

Forward- & Backwardpass
Letzte Änderung: 17. April 2023, 13:41 Uhr
Abgabe: Montag, der 26.06.2023, 12 Uhr

  /  






Aufgabe: Forward Pass

Wir starten mit dem Problem. Gegeben ein einfacher 2D-Datensatz, bestehend aus jeweils wenigen Klassen von Punkten. Wir wollen ein Neuronales Netz entwerfen, das solche Datenssätze selbstständig zu klassifizieren lernt.



Als Datensatz dient uns entweder ein selbstgebauter Datensatz, beispielsweise ein Gitter mit einer festen und ungefähr gleichverteilte Anzahl an Klassen (siehe Bild) oder aber einer der vorgefertigten Spielzeug-Datensätze von SciKit-Learn.


Wichtig: Damit Sie gute Ergebnisse erziehlen müssen Sie vorher dafür sorgen, dass der Datensatz normiert in das Netz kommt, d.h. den Mittelwert 0 hat bei einer Standardabweichung von 1.


Wir schauen uns Netze der Form \[ f(x) := \left(f_n \circ a \circ f_{n-1} \circ a \circ \dots a \circ f_2 \circ a \circ f_1\right)(x) \] an, wobei \(a\) die oben beschriebene ReLU-Aktivierungsfunktion ist und \(f_i\) Lineare Layer mit den jeweiligen Parametern \(W_i \in \mathbb{R}^{c_{i-1}\times c_{i}}\) und \(b_i\in \mathbb{R}^{c_i}\).
Wir starten mit zufällig gewählten Parametern. Konkret wählen wir \(W_i \sim \mathcal{N}(0,1)\) und \(b=0.1\).


Aufgabe: Implementieren Sie den Forward-Pass, d.h. eine Auswertung des Netzes auf einem Datenpunkt \(x\).


Hinweise:

Aufgabe: Backward Pass / BackProp


Nun zur Optimierung. Wir schauen uns die Cross-Entropie der Ausgabe des Netzwerks an, \(y(x) := \operatorname{SingleClassSoftmaxCE}(f(x), y)\). Die Frage, wie wir die Gewichte ändern müssen, damit sich die Energiefunktion (a.k.a. Loss) lokal verbessert, lässt sich leicht beantworten: Die Ableitung zeigt in die Richtung des steilsten Anstiegs. Wir haben in Lehreinheit 9 bereits verschiedene Algorithmen kennengelernt, die diese Idee zur Optimierung nutzen.


Der Einfachheit halber implementieren wir Stochastic Gradient Descent:
Um den Loss zu minimieren gehen wir einfach eine strikte Distanz \(W_i \rightarrow \lambda \cdot \nabla \frac{\partial y}{\partial W_i}\).


Doch wie erhalten wir diese Gradienten effizient? Die Antwort darauf zeigt uns die Kettenregel. Wir leiten den Loss nach einem beliebigen Gewicht mitten im Netzwerk ab. \[ \frac{\partial y}{\partial W_i} = \frac{\partial \operatorname{SCSCE}}{\partial f_n} \cdot \frac{\partial f_n}{\partial a} \cdot \frac{\partial a}{\partial f_{n-1}} \cdot \dots \cdot \frac{\partial f_{i+1}}{\partial a} \cdot \frac{\partial a}{\partial f_i} \cdot \frac{\partial f_i}{\partial W_i} \]


Die Faktorisierung der Ableitung durch die Kettenregel ermöglicht es uns den folgenden Algorithmus.


Für jeden Layer im Netzwerk berechnen wir die lokale Ableitung des Ergebnisses nach den Eingaben und nach den Gewichten. Für einen linearen Layer \(f_i(x) := x\cdot W_i + b_i\) ist dies einfach (siehe auch hier): \[ \begin{align} \frac{\partial f_i}{\partial W_i} &:= x\\ \frac{\partial f_i}{\partial x} &:= W_i^T\\ \frac{\partial f_i}{\partial b_i} &:= 1 \end{align} \]


Aufgaben:

  1. Wie sieht das im Fall der Aktivierungsfunktion \(a\) aus und im Falle des Softmax-CrossEntropy-Losses?
  2. Um also ein spezifisches Gewicht \(W_i\) anzupassen, müssen wir zuerst den Loss bestimmen und dann der Kettenregel folgend alle Faktoren bis zum Layer \(f_{i+1}\) aufmultiplizieren und zuletzt mit \(W_i^T\) multiplizieren. Das Ergebnis skaliert mit \(\lambda\) können wir direkt auf die Gewichte anwenden. Praktischerweise ändern sich die Multiplikationen für alle folgenden Layer nicht, d.h. wir können eine Menge Rechnungen sparen.
  3. Implementieren Sie die ganze Optimierungspipeline und plotten Sie die Verläufe von Loss und Accuracy.
    • Testen Sie verschiedene Netz-Größen (Anzahl Layer, Anzahl Dimensionen \(c_i\) auf den verschiedenen Layern) und verschiedene Batch-Größen (also die Anzahl an Punkten, die bei jedem Forward-/Backwardpass neu gewürfelt werden).