ML Atlas

Machine Learning von Grund auf · Lektion 3.6 · 19 von 33 fertigen Lektionen · 12 Min.

Frühes Stoppen

Kurz gesagt

Ein zu lange trainiertes Netz lernt falsche Labels auswendig. Bei 20 % zufälligen Labels senken 100 Epochen die Testgenauigkeit von 86,1 % auf 76,3 %.

Aufwärmen Zwei Fragen aus früheren Lektionen. Eine Minute, und sie blockiert die Lektion nicht.
Aus Lektion 3.5: Hyperparameter abstimmen, ohne zu schummeln Wie bewertest du fair ein Modell, dessen Hyperparameter du per Kreuzvalidierung gewählt hast?

Antwort anzeigen

Richtige Antwort: Es auf einem zurückgehaltenen Test oder mit verschachtelter Kreuzvalidierung prüfen

Zurückgehaltener Test und verschachtelte Kreuzvalidierung waren an der Wahl nicht beteiligt. Im Code ergibt die gewöhnliche Kreuzvalidierung 94,0 %, die verschachtelte 91,9 %.

Aus Lektion 3.4: Regularisierung: Ridge und Lasso Wie unterscheidet sich die Ridge-Strafe von der Lasso-Strafe?

Antwort anzeigen

Richtige Antwort: Ridge zieht alle Gewichte zur Null, Lasso setzt einige davon genau auf null

Ridge bestraft quadrierte Gewichte und setzt keines auf null; Lasso bestraft Beträge und setzt die Gewichte nacheinander auf null. Im Lab hat Ridge bei α = 398 10 Gewichte ungleich null, Lasso bei α = 15,8 nur 3.

Ein neuronales Netz lernt in Epochen: Eine Epoche ist ein Durchgang durch alle Trainingsbeispiele. Nach jeder Epoche sinkt der Trainingsverlust meist. Die Frage aus Lektion 3.1 kehrt in neuer Form zurück: Wie viele Epochen sind zu viele? Frühes Stoppen beantwortet sie mit der Validierungsmenge: Das Training stoppt, wenn der Validierungsverlust nicht mehr sinkt, und das Modell kehrt zu seiner besten Epoche zurück.

Erst vorhersagen, dann prüfen Ein kleines neuronales Netz lernt an 299 Bildern, handgeschriebene Ziffern zu erkennen. Bei 20 % davon ist das Label eine zufällige Ziffer statt der richtigen. Der niedrigste Validierungsverlust kommt in Epoche 28. Du trainierst trotzdem 100 Epochen, statt bei der besten zu stoppen. Was passiert mit der Genauigkeit im Test?
Wie sicher bist du?

Interaktives Labor

Dieses interaktive Labor läuft im Browser mit aktiviertem JavaScript. Der Text drumherum beschreibt, was es zeigt.

Antwort anzeigen

Richtige Antwort: Sie fällt von 86,1 % auf 76,3 %, weil das Netz auch die falschen Labels auswendig lernt

Die Gewichte aus Epoche 28 erreichen auf den 997 Testbildern 86,1 %, nach 100 Epochen 76,3 %: 9,7 Prozentpunkte weniger. Der Validierungsverlust steigt in dieser Zeit von 0,48 auf 0,84, und von den 51 falschen Labels gibt das Netz am Ende alle wieder.

Probier es aus

  • Das Labor startet mit sauberen Labels. Wechsle zu den zufälligen Labels und lass die Geduld bei 5. In welcher Epoche stoppt das Training, welche Gewichte bleiben, und ist das die beste Epoche des ganzen Laufs?
  • Erhöhe die Geduld auf 10. Was ändert sich an der behaltenen Epoche und an der Testgenauigkeit?
  • Geh zurück zu den sauberen Labels. Was kostet jetzt das Training bis zum Ende?

Wenn du es im Lab geprüft hast, geben wir dem, was du siehst, einen Namen.

Die Idee in einfachen Worten

Am Anfang des Trainings lernt das Netz, was viele Bilder gemeinsam haben: die Form einer Null, einer Acht, einer Sieben. Trainings- und Validierungsverlust sinken zusammen. Dann beginnt das Netz, einzelne Beispiele anzupassen, auch die mit falschem Label. Der Trainingsverlust sinkt weiter, der Validierungsverlust beginnt zu steigen. Das ist die Überanpassung aus Lektion 3.1, nur entlang der Epochen statt der Zahl der Parameter.

Frühes Stoppen beobachtet den Validierungsverlust. Es merkt sich die Epoche mit dem niedrigsten Verlust und zählt die Epochen ohne Verbesserung. Sind es so viele wie die Geduld, stoppt das Training, und das Netz kehrt zu den Gewichten der besten Epoche zurück. Im Lab stoppt das Training bei einer Geduld von 10 in Epoche 38, und die Gewichte aus Epoche 28 bleiben: 86,1 % im Test statt 76,3 % nach 100 Epochen.

Zu wenig Geduld schadet auch. Die Validierungskurve zittert von Epoche zu Epoche. Bei einer Geduld von 5 stoppt das Training schon in Epoche 23 und behält die Gewichte aus Epoche 18 (85,0 % im Test), obwohl Epoche 28 die beste war.

Jak to policzono
  • Ziffern: Optical Recognition of Handwritten Digits, UCI, Lizenz CC BY 4.0. 1797 Bilder mit 8×8 Pixeln.
  • Geschichtete Aufteilung: 299 Bilder zum Lernen, 501 zur Validierung, 997 für den Test. In der verrauschten Version wird jedes Trainingslabel mit Wahrscheinlichkeit 20 % durch eine zufällige Ziffer ersetzt: 51 Labels haben sich geändert (eine zufällige Ziffer trifft manchmal die richtige).
  • Netz 64 → 32 → 10, ReLU, Kreuzentropie, SGD mit Momentum 0,9, Schritt 0,05, Batches von 32 Bildern, 100 Epochen. Validierungsverlust nach jeder Epoche berechnet.
  • Validierung und Test haben die richtigen Labels. Das Rauschen steckt nur in den Trainingsdaten.

Warum es funktioniert

Ein Beispiel mit falschem Label ist für das Netz schwer: Das Bild sieht aus wie eine Drei, das Label sagt „Sieben“. Um den Verlust bei so einem Beispiel zu senken, muss das Netz eine Regel lernen, die nur zu ihm passt. Das tut es meist spät, wenn die leichten, gemeinsamen Muster schon sitzen. Im Lab gibt das Netz in Epoche 28 10 der 51 falschen Labels wieder, nach 100 Epochen alle 51. Auf seinen eigenen Trainingsdaten hat es dann 99,7 % Genauigkeit: Es stimmt sogar mit den Labels überein, die falsch sind.

Regeln, die an falsche Labels angepasst sind, verderben die Antworten auf neuen Bildern. Die Validierungsmenge hat die richtigen Labels, also steigt ihr Verlust genau dann, wenn das Netz anfängt, das Rauschen zu lernen. Deshalb sagt sie, und nicht der Trainingsverlust, wann Schluss ist.

Das ist kein Zufall eines einzigen Laufs. Im Code unten läuft dasselbe Experiment in scikit-learn auf 10 anderen Aufteilungen und Rauschziehungen: Die beste Epoche liegt zwischen 13 und 23, und Training bis 100 Epochen senkt die Testgenauigkeit in jedem der 10 Läufe, im Mittel von 87,2 % auf 76,4 %. Die beste Epoche des Labs (28) liegt außerhalb dieses Bereichs, weil sie auch von den Startgewichten und der Reihenfolge der Batches abhängt: Dasselbe Netz aus dem Lab mit 9 anderen Zufalls-Seeds ist zwischen Epoche 12 und 25 am besten, und Training bis 100 Epochen senkt die Testgenauigkeit jedes Mal.

Häufiger Fehler

Richtig oder falsch: „Längeres Training ergibt immer ein besseres Modell.“ Falsch. Längeres Training passt sich immer besser an die Trainingsdaten an, aber nicht an neue Daten. Mit zufälligen Labels ergeben 100 Epochen 99,7 % Genauigkeit im Training und 76,3 % im Test, während ein Stopp bei Epoche 28 im Test 86,1 % ergibt.

Ein Hinweis in die andere Richtung: Mit sauberen Labels verdirbt Training bis zum Ende fast nichts. Der niedrigste Validierungsverlust kommt in Epoche 30 (93,9 % im Test), und nach 100 Epochen liegt die Genauigkeit bei 94,5 %. Frühes Stoppen rettet nicht immer Genauigkeit, spart aber immer Zeit und schützt vor Daten, die schlechter sind, als du denkst.

Quiz

Drei Fragen zur Selbstkontrolle. Wähle eine Antwort oder klappe die Lösung unter der Frage auf. Mit der Tastatur: Pfeiltasten wählen, Enter oder Leertaste bestätigt.

1. Woran entscheidet frühes Stoppen, wann das Training abbricht?
Antwort anzeigen

Richtige Antwort: Am Validierungsverlust: Es stoppt, wenn er nicht mehr sinkt

Der Trainingsverlust sinkt fast bis zum Ende, selbst wenn das Netz Rauschen lernt. Der Validierungsverlust, berechnet auf Daten außerhalb des Trainings, steigt, wenn das Modell anfängt, sich zu überanpassen.

2. Bei 20 % zufälligen Labels hat das Netz nach 100 Epochen 99,7 % im Training und 76,3 % im Test. Was bedeutet das?
Antwort anzeigen

Richtige Antwort: Das Netz hat auch die falschen Labels auswendig gelernt, und das verdirbt seine Antworten auf neuen Daten

Hohe Trainingsgenauigkeit bei verrauschten Labels heißt, dass das Netz auch das Rauschen angepasst hat. Die Gewichte aus Epoche 28 erreichen im Test 86,1 %.

3. Eine Geduld von 5 stoppt das Training in Epoche 23 und behält Epoche 18, obwohl der niedrigste Verlust in Epoche 28 liegt. Warum?
Antwort anzeigen

Richtige Antwort: Weil die Validierungskurve zittert und zu wenig Geduld ein Zittern für das Minimum hält

Der Validierungsverlust sinkt nicht gleichmäßig: Einige schlechtere Epochen hintereinander können Zufall sein. Bei einer Geduld von 10 erreicht das Training Epoche 28.

Das Wichtigste

  • Eine Epoche ist ein Durchgang durch die Trainingsdaten; der Trainingsverlust sinkt fast immer, der Validierungsverlust nicht.
  • Frühes Stoppen bricht das Training ab, wenn sich der Validierungsverlust einige Epochen lang (die Geduld) nicht verbessert, und kehrt zu den besten Gewichten zurück.
  • Zu langes Training mit falschen Labels bringt dem Netz das Rauschen bei: Der Test fällt von 86,1 % auf 76,3 %.
  • Zu wenig Geduld stoppt das Training an einem zufälligen Zittern der Kurve.

Tiefer: Formel, Code, Praxis

Die Mathematik

Validierungsverlust nach Epoche e: L_val(e) = −(1/m) · Σᵢ log p_e(yᵢ | xᵢ) auf m Validierungsbildern (Kreuzentropie).

Die Regel mit Geduld P: e = argmin_{e ≤ t} L_val(e); das Training stoppt in der ersten Epoche t mit t − e ≥ P und gibt die Gewichte w(e) zurück. Kommt keine solche Epoche, gibt es w(e) über den ganzen Lauf zurück.

Frühes Stoppen wirkt ähnlich wie die Strafe aus Lektion 3.4. Beim Gradientenabstieg mit kleinem Schritt starten die Gewichte nahe null und entfernen sich mit jeder Epoche davon. Weniger Epochen heißen kleinere Gewichte: Für ein lineares Modell mit quadratischem Verlust wirkt ein Stopp nach t Schritten ungefähr wie Ridge mit α in der Größenordnung 1 / (Schritt · t).

Im Code (Python)

Dasselbe Experiment in scikit-learn: 10 verschiedene Aufteilungen und Rauschziehungen, ein Netz 64 → 32 → 10, Epoche für Epoche trainiert, wobei die Gewichte der Epoche mit dem niedrigsten Validierungsverlust behalten werden.

import copy
import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import log_loss

X, y = load_digits(return_X_y=True)
X = X / 16
def run(seed):  # 300 Ziffern zum Lernen, 500 zur Validierung, die übrigen 997 für den Test
    used, te = train_test_split(np.arange(len(y)), train_size=800, stratify=y, random_state=seed)
    tr, va = train_test_split(used, test_size=500, stratify=y[used], random_state=seed)
    rng = np.random.default_rng(seed)
    noisy = y[tr].copy()
    flip = rng.random(len(tr)) < 0.2  # 20 % der Trainingslabels durch eine zufällige Ziffer ersetzt
    noisy[flip] = rng.integers(0, 10, flip.sum())
    net = MLPClassifier(hidden_layer_sizes=(32,), solver="sgd", learning_rate_init=0.05, momentum=0.9, batch_size=32, alpha=0, random_state=seed)
    best, best_loss = None, np.inf
    for epoch in range(1, 101):
        net.partial_fit(X[tr], noisy, classes=np.arange(10))
        loss = log_loss(y[va], net.predict_proba(X[va]), labels=np.arange(10))
        if loss < best_loss:
            best, best_loss, best_epoch = copy.deepcopy(net), loss, epoch  # frühes Stoppen behält die Gewichte der besten Epoche
    return best_epoch, best.score(X[te], y[te]), net.score(X[te], y[te])
r = np.array([run(s) for s in range(10)])
print(f"10 splits and noise draws: lowest validation loss at epoch {r[:, 0].min():.0f} to {r[:, 0].max():.0f}; test at that epoch {r[:, 1].mean():.1%}, after 100 epochs {r[:, 2].mean():.1%}; lower after 100 in {(r[:, 2] < r[:, 1]).sum()} of 10")

Ausgabe

10 splits and noise draws: lowest validation loss at epoch 13 to 23; test at that epoch 87.2%, after 100 epochs 76.4%; lower after 100 in 10 of 10

Aufteilungen, Startgewichte und Rauschen sind andere als im Lab, also auch die Zahlen. Das Bild ist dasselbe: Die beste Epoche kommt früh (zwischen 13 und 23), und Training bis 100 Epochen senkt die Testgenauigkeit in allen 10 Läufen, im Mittel von 87,2 % auf 76,4 %.

Für die Praxis
  • In Keras: EarlyStopping(monitor="val_loss", patience=10, restore_best_weights=True). Ohne restore_best_weights=True bleiben die Gewichte der letzten Epoche, nicht die der besten.
  • In PyTorch schreibst du die Schleife selbst: Berechne nach jeder Epoche den Validierungsverlust und speichere eine Kopie der Gewichte, wenn er am niedrigsten ist.
  • In scikit-learn: MLPClassifier(early_stopping=True, n_iter_no_change=...) legt einen Teil der Trainingsdaten für die Validierung beiseite; es beobachtet die Validierungsgenauigkeit, nicht den Verlust. Beim Gradient Boosting heißt dieselbe Idee n_iter_no_change oder early_stopping_rounds.
  • Die auf der Validierung gewählte Zahl der Epochen ist auch ein Hyperparameter: Das Validierungsergebnis in der besten Epoche ist leicht aufgebläht (Lektion 3.5), also mach die abschließende Bewertung auf einem zurückgehaltenen Test.

Mehr im Atlas

Einträge der Enzyklopädie zu den Ideen dieser Lektion: