Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Im letzten Kapitel blieb die Frage offen, in welche Richtung man von der bisher besten Schätzung ww aus gehen soll, damit die Loss-Funktion kleiner wird. Die Antwort ist der Gradient, und um ihn für verkettete Funktionen auszurechnen, brauchen wir zuerst die Kettenregel.

Kurze Erinnerung an die Kettenregel

Für das Training werden wir Ableitungen von verketteten Funktionen brauchen, deshalb die Kettenregel in der Form, die wir benötigen: für Funktionen zwischen Vektorräumen.

Für eine Funktion g ⁣:Rn→Rmg \colon \mathbb{R}^n \to \mathbb{R}^m an einem Punkt x0x_0 ist die Ableitung (Dg)(x0)(Dg)(x_0) – eine m×nm \times n-Matrix, die Jacobi-Matrix – die beste lineare Approximation, also für x1x_1 nah bei x0x_0:

g(x1)≈g(x0)+(Dg)(x0) (x1−x0).g(x_1) \approx g(x_0) + (Dg)(x_0)\,(x_1 - x_0).

Gegeben eine weitere Funktion f ⁣:Rm→Rkf \colon \mathbb{R}^m \to \mathbb{R}^k, ebenso

f(y1)≈f(y0)+(Df)(y0) (y1−y0).f(y_1) \approx f(y_0) + (Df)(y_0)\,(y_1 - y_0).

Im Spezialfall y0=g(x0)y_0 = g(x_0), y1=g(x1)y_1 = g(x_1) setzen wir ein:

f(g(x1))≈f(g(x0))+(Df)(g(x0)) (g(x1)−g(x0))≈f(g(x0))+(Df)(g(x0)) (g(x0)+(Dg)(x0)(x1−x0)−g(x0))=f(g(x0))+(Df)(g(x0)) (Dg)(x0) (x1−x0).\begin{aligned} f(g(x_1)) &\approx f(g(x_0)) + (Df)(g(x_0))\,\bigl(g(x_1) - g(x_0)\bigr) \\ &\approx f(g(x_0)) + (Df)(g(x_0))\,\bigl(g(x_0) + (Dg)(x_0)(x_1 - x_0) - g(x_0)\bigr) \\ &= f(g(x_0)) + (Df)(g(x_0))\,(Dg)(x_0)\,(x_1 - x_0). \end{aligned}

Damit ist (Df)(g(x0))⋅(Dg)(x0)(Df)(g(x_0)) \cdot (Dg)(x_0) die beste lineare Approximation von f∘gf \circ g bei x0x_0. In anderer Notation der gleiche Sachverhalt:

D(f∘g)=((Df)∘g)⋅Dg.D(f \circ g) = \bigl((Df) \circ g\bigr) \cdot Dg .

Die Ableitung einer Verkettung ist das Matrixprodukt der Ableitungen, ausgewertet an den richtigen Stellen. Das ist bereits die halbe Backpropagation.

Summe über alle Pfade. Die Matrixform versteckt einen Fall, der beim Rechnen von Hand oft schiefgeht: Wenn eine Variable auf mehreren Wegen in das Ergebnis eingeht, addieren sich die Beiträge. Für L=u⋅vL = u \cdot v mit u=g(w)u = g(w) und v=h(w)v = h(w) ist

dLdw=∂L∂u g′(w)+∂L∂v h′(w)=v g′(w)+u h′(w).\frac{dL}{dw} = \frac{\partial L}{\partial u}\,g'(w) + \frac{\partial L}{\partial v}\,h'(w) = v\,g'(w) + u\,h'(w).

Kleinstes Beispiel: u=wu = w und v=wv = w, also L=w2L = w^2. Wer nur einem Pfad folgt, erhält ww; richtig ist w+w=2ww + w = 2w. In einem Netz geht jedes Gewicht der ersten Schicht über alle Neuronen der zweiten Schicht in den Loss ein. Backpropagation ist im Kern die Buchhaltung dieser Summe, und die Matrixmultiplikation (Df) (Dg)(Df)\,(Dg) erledigt sie automatisch: Ein Matrixprodukt ist eine Summe über Zwischenindizes.

Numerische Probe. Ableitungen kann man nachprüfen, ohne sie zu kennen: Für kleines hh ist

L(w+h)−L(w)h≈L′(w).\frac{L(w + h) - L(w)}{h} \approx L'(w).

Beispiel: L(w)=(1−2w)2L(w) = (1 - 2w)^2, also L′(w)=−4 (1−2w)L'(w) = -4\,(1 - 2w) und L′(1)=4L'(1) = 4. Nachrechnen: L(1)=1L(1) = 1, L(1,01)=(1−2,02)2=1,0404L(1{,}01) = (1 - 2{,}02)^2 = 1{,}0404, Differenzenquotient 0,0404/0,01=4,040{,}0404 / 0{,}01 = 4{,}04. Diese Probe (gradient check) ist der wichtigste Handgriff, wenn eine von Hand hergeleitete Ableitung oder ein selbst geschriebenes backward nicht stimmen will. PyTorch hat sie eingebaut: torch.autograd.gradcheck.

Gradienten

Wir stellen uns für den Moment vor, dass w∈R2w \in \mathbb{R}^2 ist (also die Daten zwei Features haben). Wir stellen uns die ww-Ebene vor und darauf ein L(w)L(w)-Gebirge. An jedem Punkt die Frage: Wohin sollen wir gehen, wenn wir runter wollen? Antwort: In die Richtung, wo L(w)L(w) am schnellsten kleiner wird, also „nach unten“ – das heißt entlang des negativen Gradienten grad⁡(L)(w)=L′(w)∈R2\operatorname{grad}(L)(w) = L'(w) \in \mathbb{R}^2.

Ein (erfundenes) Loss-Gebirge über der w-Ebene mit zwei Gradientenabstiegspfaden von verschiedenen Startpunkten. Beide landen im selben Tal – das ist nicht immer so.

Ein (erfundenes) Loss-Gebirge über der ww-Ebene mit zwei Gradientenabstiegspfaden von verschiedenen Startpunkten. Beide landen im selben Tal – das ist nicht immer so.

Gradienten konkret

Betrachten wir den MSE für eine lineare Regression, mit der Notation xj(i)x^{(i)}_j für Feature jj von Datenpunkt ii aus dem Kapitel „Was ist Deep Learning?“:

L(w)=1N∑i=1N(yi−⟨w,x(i)⟩)2.L(w) = \frac1N \sum_{i=1}^N \bigl( y_i - \langle w, x^{(i)} \rangle \bigr)^2 .

Halte zunächst die Komponente w2w_2 fest und variiere w1w_1. Das gibt eine Funktion in einer Variablen, w1↦L(w1,w2)w_1 \mapsto L(w_1, w_2), und ihre Ableitung gibt die Änderung von LL abhängig von w1w_1 an, also die Änderung in Richtung der ersten Koordinate der ww-Ebene: „Wenn ich einen (infinitesimalen) Schritt nach Osten gehe, wie stark ändert sich LL dann?“ Danach w1w_1 festhalten und w2w_2 variieren: ein Schritt nach Norden.

Diese beiden Ableitungen heißen besser partielle Ableitungen ∂∂w1L(w)\frac{\partial}{\partial w_1} L(w) und ∂∂w2L(w)\frac{\partial}{\partial w_2} L(w), und der Gradient ist der Vektor aus beiden:

L′(w)=(∂L∂w1(w), ∂L∂w2(w))=∂L∂w1(w) e1+∂L∂w2(w) e2.L'(w) = \left( \frac{\partial L}{\partial w_1}(w),\ \frac{\partial L}{\partial w_2}(w) \right) = \frac{\partial L}{\partial w_1}(w)\, e_1 + \frac{\partial L}{\partial w_2}(w)\, e_2 .

Nicht verwechseln: die Ableitung L′L' (eine Funktion, die jedem ww einen Vektor zuordnet) und L′(w)L'(w), der Gradientenvektor an einem Punkt ww.

Richtungsableitung. Die Änderung in Richtung e1e_1 ist ⟨L′(w),e1⟩=∂L∂w1(w)\langle L'(w), e_1 \rangle = \frac{\partial L}{\partial w_1}(w). Die Änderung in Richtung eines beliebigen Einheitsvektors vv ist

⟨L′(w),v⟩=∂L∂w1(w) v1+∂L∂w2(w) v2.\langle L'(w), v \rangle = \frac{\partial L}{\partial w_1}(w)\, v_1 + \frac{\partial L}{\partial w_2}(w)\, v_2 .

In welche Richtung vv ist die Änderung maximal? Das Skalarprodukt ⟨L′(w),v⟩\langle L'(w), v \rangle ist ∥L′(w)∥cos⁡α\|L'(w)\| \cos \alpha mit dem Winkel α\alpha zwischen vv und dem Gradienten, und der Kosinus ist maximal 1, wenn vv in Richtung L′(w)L'(w) zeigt, und minimal -1 in der Gegenrichtung. Der Gradient zeigt bergauf, der negative Gradient bergab.

Endlich ausrechnen. Mit der Kettenregel:

∂L∂w1(w)=1N∑i=1N2 (yi−w1x1(i)−w2x2(i)) (−x1(i)),∂L∂w2(w)=1N∑i=1N2 (yi−w1x1(i)−w2x2(i)) (−x2(i)).\frac{\partial L}{\partial w_1}(w) = \frac1N \sum_{i=1}^N 2\,\bigl(y_i - w_1 x^{(i)}_1 - w_2 x^{(i)}_2\bigr)\,\bigl(-x^{(i)}_1\bigr), \qquad \frac{\partial L}{\partial w_2}(w) = \frac1N \sum_{i=1}^N 2\,\bigl(y_i - w_1 x^{(i)}_1 - w_2 x^{(i)}_2\bigr)\,\bigl(-x^{(i)}_2\bigr).
Tafelbild zum Gradientenschritt von Hand (WiSe 2025/26).

Tafelbild zum Gradientenschritt von Hand (WiSe 2025/26).

Der Algorithmus

Damit haben wir die sehr clevere Variante der approximativen Minimierung:

  1. Sehr clever ein ww auswählen, in der Nähe der bisher besten Schätzung:

    wneu:=walt−ρ L′(walt).w_{\text{neu}} := w_{\text{alt}} - \rho\, L'(w_{\text{alt}}).
  2. L(w)L(w) ausrechnen, vergleichen mit dem bisher niedrigsten Wert,

  3. Größer? Pech gehabt, weitermachen (ggf. mit kleinerem ρ\rho). Kleiner? Besseres ww gefunden!

  4. Jetzt ggf. aufhören, wenn ww gut genug ist.

Das ist der Gradientenabstieg, und ρ\rho ist die Lernrate – dieselbe, die wir beim Perzeptron schon hatten. Zu klein, und man braucht ewig; zu groß, und man springt über das Tal hinweg.

Wie groß „zu groß“ ist, hängt von den Daten ab, und zwar von jedem Feature einzeln. Für den MSE ist ∂L∂wj=1N∑i2 (yi−⟨w,x(i)⟩) (−xj(i))\frac{\partial L}{\partial w_j} = \frac1N \sum_i 2\,(y_i - \langle w, x^{(i)} \rangle)\,(-x^{(i)}_j), also proportional zu den Werten von Feature jj. Hat Feature 1 Werte um 1 und Feature 2 Werte um 1000 (Körpergröße in Metern, Einkommen in Euro), so ist die zweite Gradientenkomponente etwa tausendmal größer als die erste, und die Krümmung des Loss-Gebirges in w2w_2-Richtung ist eine Million mal größer: Das Tal ist eine lange, schmale Schlucht. Eine Lernrate, die in w1w_1-Richtung vernünftig vorankommt, springt in w2w_2-Richtung über die Schlucht hinaus; eine, die dort stabil ist, kriecht in w1w_1-Richtung.

Der einfachste Ausweg ist, alle Features vorher auf Mittelwert 0 und Standardabweichung 1 zu bringen (Standardisierung, sklearn.preprocessing.StandardScaler, und beim Testset mit den Werten aus dem Trainingsset skalieren). Dass dieselbe Idee auch innerhalb eines Netzes hilft (Batch Normalization, Layer Normalization) und dass Optimierer wie Adam die Lernrate pro Parameter anpassen, sehen wir in späteren Kapiteln; der Grund ist immer dieser.

Wie so ein Loss-Gebirge für ein echtes neuronales Netz aussieht, zeigen z.B. Li, Xu, Taylor, Studer und Goldstein, Visualizing the loss landscape of neural nets (arXiv:1712.09913, 2017). Die Landschaften sind nicht konvex, es gibt viele lokale Minima, Sattelpunkte und Plateaus – und trotzdem funktioniert Gradientenabstieg erstaunlich gut.

Zurück zum Perzeptron

Die neue Perspektive erklärt auch die Perzeptronregel. Der „harte“ Perceptron Loss ∑imax⁡(0,−yisign⁡⟨w,xi⟩)\sum_i \max(0, -y_i \operatorname{sign}\langle w, x_i \rangle) hat ein Problem: Ableitung?!? Die Funktion ist stückweise konstant, der Gradient ist fast überall 0. Besser ist der „weiche“ Perceptron Loss ohne das sign⁡\operatorname{sign}:

LPerc(w)=∑i=1Nmax⁡(0, −yi⟨w,xi⟩).L_{\text{Perc}}(w) = \sum_{i=1}^N \max\bigl(0,\, -y_i \langle w, x_i \rangle\bigr).

Ein Summand ist 0, wenn xix_i korrekt klassifiziert ist (yi⟨w,xi⟩>0y_i \langle w, x_i \rangle > 0), und sonst −yi⟨w,xi⟩>0-y_i \langle w, x_i \rangle > 0, also proportional dazu, wie weit auf der falschen Seite xix_i liegt. Die (schwache) Ableitung ist

LPerc′(w)=∑i falsch klassifiziert−yixi,L_{\text{Perc}}'(w) = \sum_{i \text{ falsch klassifiziert}} -y_i x_i ,

die Summe über die falsch klassifizierten Samples. Die allgemeine Update-Regel wneu=walt−ρ L′(w)w_{\text{neu}} = w_{\text{alt}} - \rho\, L'(w) liefert für ein einzelnes (x,ytrue)(x, y_{\text{true}}), also N=1N = 1:

wneu=walt±ρ xwenn x falsch klassifiziert ist, sonst wneu=walt.w_{\text{neu}} = w_{\text{alt}} \pm \rho\, x \quad \text{wenn } x \text{ falsch klassifiziert ist, sonst } w_{\text{neu}} = w_{\text{alt}}.

Das ist exakt die Perzeptronregel. Rosenblatt hat also, ohne es so zu nennen, stochastischen Gradientenabstieg auf dem Perceptron Loss gemacht.

Und zurück zur logistischen Regression

Für die BCE lohnt sich dieselbe Rechnung, denn sie hat eine Pointe. Für ein einzelnes Sample (x,y)(x, y) mit Logit z=⟨w,x⟩z = \langle w, x \rangle und p=σ(z)p = \sigma(z) ist

L(z)=−yln⁡σ(z)−(1−y)ln⁡(1−σ(z)).L(z) = -y \ln \sigma(z) - (1 - y) \ln\bigl(1 - \sigma(z)\bigr).

Mit σ′=σ(1−σ)\sigma' = \sigma(1 - \sigma) und der Kettenregel:

dLdz=−y σ(z)(1−σ(z))σ(z)+(1−y) σ(z)(1−σ(z))1−σ(z)=−y(1−p)+(1−y) p=p−y.\frac{dL}{dz} = -y\,\frac{\sigma(z)(1 - \sigma(z))}{\sigma(z)} + (1 - y)\,\frac{\sigma(z)(1 - \sigma(z))}{1 - \sigma(z)} = -y(1 - p) + (1 - y)\,p = p - y .

Alle Logarithmen und Sigmoide heben sich gegenseitig weg; übrig bleibt der Vorhersagefehler. Mit ∂z∂w=x\frac{\partial z}{\partial w} = x ist der Gradient (p−y) x(p - y)\,x, und die Update-Regel lautet

wneu=walt−ρ (σ(⟨walt,x⟩)−y) x=walt+ρ (y−f(x)) x.w_{\text{neu}} = w_{\text{alt}} - \rho\,\bigl(\sigma(\langle w_{\text{alt}}, x \rangle) - y\bigr)\,x = w_{\text{alt}} + \rho\,\bigl(y - f(x)\bigr)\,x .

Das ist buchstäblich die Perzeptronregel aus dem Kapitel „Das Perzeptron trainieren“, nur mit f(x)=σ(⟨w,x⟩)f(x) = \sigma(\langle w, x \rangle) statt [⟨w,x⟩>0][\langle w, x \rangle > 0]: Statt „falsch oder richtig“ zählt jetzt „um wie viel daneben“. Die Formel p−yp - y werden wir bei Backpropagation als Startwert der Rückwärtsrechnung wiedersehen; sie gilt genauso für Softmax mit Kreuzentropie.

Loss-Funktionen, die wir bisher gesehen haben

Für ein einzelnes Sample mit y=1y = 1, aufgetragen gegen den Wert der Entscheidungsfunktion f(x)=⟨w,x⟩f(x) = \langle w, x \rangle:

Drei Loss-Funktionen für ein Sample der Klasse y = 1 in Abhängigkeit vom Wert der Entscheidungsfunktion f(x).

Drei Loss-Funktionen für ein Sample der Klasse y=1y = 1 in Abhängigkeit vom Wert der Entscheidungsfunktion f(x)f(x).

Take-Home Message

Ein einzelnes Neuron besteht aus einer Aktivierungsfunktion τ\tau und einem Gewichtsvektor ww (den Parametern). Inferenz:

ypred=τ(⟨w,x⟩).y_{\text{pred}} = \tau(\langle w, x \rangle).

Training, mit Hyperparameter ρ\rho, hängt von der Loss-Funktion L(w)L(w) ab:

wneu=walt−ρ L′(walt).w_{\text{neu}} = w_{\text{alt}} - \rho\, L'(w_{\text{alt}}).

Für binäre Klassifikation nimmt man τ=σ\tau = \sigma und L=LBCEL = L_{\text{BCE}}. Das ist logistische Regression. In echt kennt man die Landschaft nicht und muss die Lernrate ausprobieren.

Nicht-stochastischer Gradientenabstieg??

Gradientenabstieg ist der Oberbegriff und gleichzeitig die spezifische Bezeichnung für: den ganzen Datensatz einlesen, dabei die Loss-Funktion auswerten und den Gradienten bestimmen, damit die Gewichte anpassen, und erneut den ganzen Datensatz einlesen usw. (auch Batch Gradient Descent).

Stochastischer Gradientenabstieg (SGD) ist das Anpassen der Gewichte mit einer Schätzung des Gradienten aus einem Teildatensatz – meist ist ein einzelnes Sample gemeint. Das ist zufällig gewählt (die Anordnung der Daten wird als zufällig angenommen), daher stochastisch. Der geschätzte Gradient ist verrauscht, aber im Mittel korrekt, und man kommt viel häufiger zu einem Update.

Was „im Mittel korrekt“ genau heißt: Der Loss L(w)=1N∑i=1Nℓ(xi,yi;w)L(w) = \frac1N \sum_{i=1}^N \ell(x_i, y_i; w) ist ein Stichprobenmittel, also eine Schätzung des Erwartungswerts E[ℓ(X,Y;w)]\mathbb{E}\bigl[\ell(X, Y; w)\bigr] über die erzeugende Verteilung aus dem Kapitel „Was ist Deep Learning?“. Das ist die Größe, die wir eigentlich klein haben wollen, denn sie misst den Fehler auf neuen Daten. Der Gradient eines Mini-Batches ist ebenfalls ein Stichprobenmittel; weil der Erwartungswert linear ist, ist sein Erwartungswert der Gradient des vollen Loss. Nach dem Gesetz der großen Zahlen (DS-Skript) liegt das Mittel über viele Batches nahe daran, auch wenn jeder einzelne Batch danebenliegt.

Wo steckt in diesem Verfahren überall Zufall? Im Startvektor, in den Daten, die wir als Stichprobe einer Verteilung modellieren, und in der Reihenfolge, in der die Samples verarbeitet werden. Deshalb liefern zwei Trainingsläufe mit denselben Daten verschiedene Gewichte, und ein Schritt lässt sich nicht sinnvoll rückgängig machen; man kann nur neu starten.

Der Kompromiss ist Mini-Batch SGD: Eine kleine, handhabbare Menge von Samples (die Batch Size, z.B. 32 oder 64) wird gemeinsam verarbeitet und damit der Gradient approximiert. Das ist, was in der Praxis fast immer gemeint ist, wenn jemand „SGD“ sagt – auch torch.optim.SGD aus dem Kapitel „Logistische Regression“ weiß nichts davon, wie viele Samples im Batch waren. Ein Durchlauf durch den gesamten Datensatz heißt Epoche.

Übung

Sei x=(2,−1)x = (2, -1) fest und L(w):=(1−w⋅x)2L(w) := (1 - w \cdot x)^2.

  1. Bestimmen Sie ∂L∂w1\frac{\partial L}{\partial w_1} und ∂L∂w2\frac{\partial L}{\partial w_2} mit der Kettenregel. Tipp: Äußere Funktion u↦u2u \mapsto u^2, innere w↦1−w⋅xw \mapsto 1 - w\cdot x. Die Ableitung von w⋅xw \cdot x nach wjw_j ist xjx_j – mehr steckt nicht dahinter.

  2. Werten Sie den Gradienten bei w=(0,0)w = (0,0) aus und führen Sie einen Schritt mit Lernrate ρ=0,1\rho = 0{,}1 aus.

  3. Berechnen Sie LL vor und nach dem Schritt.

Antwortprobe: LL ist nach dem Schritt exakt 0 – bei ρ=0,1\rho = 0{,}1 und ∥x∥2=5\|x\|^2 = 5 landet man genau im Minimum. Kommt etwas anderes heraus, fehlt meist der Faktor 2 aus der Kettenregel.