ML Atlas

Kurs uczenia maszynowego od zera · Lekcja 3.6 · 19 z 33 gotowych lekcji · 12 min

Wczesne zatrzymanie

W skrócie

Sieć uczona za długo zapamiętuje błędne etykiety. Przy 20% losowych etykiet 100 epok zamiast zatrzymania obniża trafność testową z 86,1% do 76,3%.

Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
Z lekcji 3.5: Strojenie hiperparametrów bez oszukiwania Jak uczciwie ocenić model, którego hiperparametry dobrałeś walidacją krzyżową?

Pokaż odpowiedź

Poprawna odpowiedź: Sprawdzić go na odłożonym teście albo w zagnieżdżonej walidacji krzyżowej

Odłożony test i zagnieżdżona walidacja nie brały udziału w wyborze. W kodzie zwykła walidacja daje 94,0%, a zagnieżdżona 91,9%.

Z lekcji 3.4: Regularyzacja: ridge i lasso Czym różni się kara ridge od kary lasso?

Pokaż odpowiedź

Poprawna odpowiedź: Ridge ściąga wszystkie wagi, a lasso część z nich ustawia dokładnie na zero

Ridge karze kwadraty wag i żadnej nie zeruje; lasso karze wartości bezwzględne i zeruje wagi po kolei. W labie przy α = 398 ridge ma 10 niezerowych wag, a lasso przy α = 15,8 tylko 3.

Sieć neuronowa uczy się w epokach: jedna epoka to jedno przejście przez wszystkie przykłady treningowe. Po każdej epoce strata treningowa zwykle spada. Pytanie z lekcji 3.1 wraca w nowej postaci: ile epok to za dużo? Wczesne zatrzymanie odpowiada na nie zbiorem walidacyjnym: trening staje, gdy strata walidacyjna przestaje spadać, a model wraca do najlepszej epoki.

Przewidź, potem sprawdź Mała sieć neuronowa uczy się rozpoznawać odręczne cyfry na 299 obrazkach. W 20% z nich etykieta jest losową cyfrą zamiast prawdziwej. Najniższa strata walidacyjna przypada na epokę 28. Trenujesz jednak 100 epok, zamiast zatrzymać się w najlepszej. Co się dzieje z trafnością na teście?
Jak bardzo jesteś pewny(-a)?

Eksperyment

Ten interaktywny eksperyment działa w przeglądarce z włączonym JavaScriptem. Tekst wokół opisuje, co w nim widać.

Pokaż odpowiedź

Poprawna odpowiedź: Spada z 86,1% do 76,3%, bo sieć zapamiętuje też błędne etykiety

Wagi z epoki 28 mają na 997 obrazkach testowych 86,1%, a po 100 epokach 76,3%: o 9,7 pkt proc. mniej. Strata walidacyjna rośnie w tym czasie z 0,48 do 0,84, a z 51 błędnych etykiet sieć powtarza na koniec wszystkie.

Spróbuj

  • Lab startuje od etykiet czystych. Przełącz na losowe etykiety i zostaw cierpliwość 5. W której epoce trening staje, które wagi zostają i czy to najlepsza epoka całego przebiegu?
  • Zwiększ cierpliwość do 10. Co zmienia się w zachowanej epoce i w trafności na teście?
  • Wróć do etykiet czystych. Ile teraz kosztuje trening do końca?

Gdy już sprawdzisz to w labie, nazwijmy, co widzisz.

Pomysł w prostych słowach

Na początku treningu sieć uczy się tego, co wspólne dla wielu obrazków: kształtu zera, ósemki, siódemki. Strata treningowa i walidacyjna spadają razem. Potem sieć zaczyna dopasowywać pojedyncze przykłady, także te z błędną etykietą. Strata treningowa dalej spada, a walidacyjna zaczyna rosnąć. To przeuczenie z lekcji 3.1, tylko w osi epok zamiast liczby parametrów.

Wczesne zatrzymanie pilnuje straty walidacyjnej. Zapamiętuje epokę z najniższą stratą i liczy epoki bez poprawy. Gdy jest ich tyle, ile wynosi cierpliwość, trening staje, a sieć wraca do wag z najlepszej epoki. W labie przy cierpliwości 10 trening staje w epoce 38, a zostają wagi z epoki 28: 86,1% na teście zamiast 76,3% po 100 epokach.

Za mała cierpliwość też szkodzi. Krzywa walidacyjna drga od epoki do epoki. Przy cierpliwości 5 trening staje już w epoce 23 i zostają wagi z epoki 18 (85,0% na teście), choć najlepsza była epoka 28.

Jak to policzono
  • Cyfry: Optical Recognition of Handwritten Digits, UCI, licencja CC BY 4.0. 1797 obrazków 8×8 pikseli.
  • Podział warstwowy: 299 obrazków do nauki, 501 do walidacji, 997 do testu. W wersji z szumem każda etykieta treningowa z prawdopodobieństwem 20% zamieniona na losową cyfrę: zmieniło się 51 etykiet (losowa cyfra czasem trafia w prawdziwą).
  • Sieć 64 → 32 → 10, ReLU, entropia krzyżowa, SGD z momentum 0,9, krok 0,05, paczki po 32 obrazki, 100 epok. Strata walidacyjna liczona po każdej epoce.
  • Walidacja i test mają prawdziwe etykiety. Szum jest tylko w danych treningowych.

Dlaczego to działa

Przykład z błędną etykietą jest dla sieci trudny: obrazek wygląda jak trójka, a etykieta mówi „siedem”. Żeby zmniejszyć stratę na takim przykładzie, sieć musi nauczyć się reguły, która pasuje tylko do niego. Zwykle robi to późno, gdy łatwe, wspólne wzorce są już opanowane. W labie w epoce 28 sieć powtarza 10 z 51 błędnych etykiet, a po 100 epokach wszystkie 51. Na własnych danych treningowych ma wtedy 99,7% trafności, czyli zgadza się nawet z etykietami, które są nieprawdziwe.

Reguły dopasowane do błędnych etykiet psują odpowiedzi na nowych obrazkach. Zbiór walidacyjny ma prawdziwe etykiety, więc jego strata rośnie dokładnie wtedy, gdy sieć zaczyna uczyć się szumu. Dlatego to ona, a nie strata treningowa, mówi, kiedy przestać.

To nie jest przypadek jednego przebiegu. W kodzie niżej ten sam eksperyment idzie na 10 innych podziałach i losowaniach szumu w scikit-learn: najlepsza epoka wypada między 13 a 23, a trening do 100 epok obniża trafność testową w każdym z 10 przebiegów, średnio z 87,2% do 76,4%. Najlepsza epoka labu (28) leży poza tym zakresem, bo zależy też od wag startowych i kolejności paczek: ta sama sieć z labu z 9 innymi ziarnami losowymi wypada najlepiej między epoką 12 a 25, a trening do 100 epok za każdym razem obniża trafność testową.

Częsty błąd

Prawda czy fałsz: „dłuższy trening zawsze daje lepszy model”. Fałsz. Dłuższy trening zawsze lepiej dopasowuje dane treningowe, ale nie nowe dane. Przy losowych etykietach 100 epok daje 99,7% trafności na treningu i 76,3% na teście, podczas gdy zatrzymanie w epoce 28 daje 86,1% na teście.

Uwaga w drugą stronę: przy czystych etykietach trening do końca prawie nic nie psuje. Najlepsza strata walidacyjna przypada na epokę 30 (93,9% na teście), a po 100 epokach trafność wynosi 94,5%. Wczesne zatrzymanie nie zawsze ratuje trafność, ale zawsze oszczędza czas i chroni przed sytuacją, w której dane są gorsze, niż myślisz.

Quiz

Trzy pytania na sprawdzenie się. Wybierz odpowiedź albo rozwiń odpowiedź pod pytaniem. Z klawiatury: strzałki wybierają, Enter albo spacja zatwierdza.

1. Na podstawie czego wczesne zatrzymanie decyduje, kiedy przerwać trening?
Pokaż odpowiedź

Poprawna odpowiedź: Straty walidacyjnej: trening staje, gdy przestaje ona spadać

Strata treningowa spada prawie do końca, nawet gdy sieć uczy się szumu. Strata walidacyjna liczona na danych spoza nauki rośnie, gdy model zaczyna się przeuczać.

2. Przy 20% losowych etykiet sieć po 100 epokach ma 99,7% na treningu i 76,3% na teście. Co to znaczy?
Pokaż odpowiedź

Poprawna odpowiedź: Sieć zapamiętała także błędne etykiety, a to psuje jej odpowiedzi na nowych danych

Wysoka trafność na treningu przy szumie w etykietach znaczy, że sieć dopasowała też szum. Wagi z epoki 28 mają na teście 86,1%.

3. Cierpliwość 5 zatrzymuje trening w epoce 23 i zostawia epokę 18, choć najniższa strata jest w epoce 28. Dlaczego?
Pokaż odpowiedź

Poprawna odpowiedź: Bo krzywa walidacyjna drga i za mała cierpliwość myli drganie ze szczytem

Strata walidacyjna nie spada równo: kilka gorszych epok z rzędu może być przypadkiem. Przy cierpliwości 10 trening dochodzi do epoki 28.

Najważniejsze wnioski

  • Epoka to jedno przejście przez dane treningowe; strata treningowa spada prawie zawsze, walidacyjna nie.
  • Wczesne zatrzymanie przerywa trening, gdy strata walidacyjna przez kilka epok (cierpliwość) się nie poprawia, i wraca do najlepszych wag.
  • Za długi trening przy błędnych etykietach uczy sieć szumu: test spada z 86,1% do 76,3%.
  • Za mała cierpliwość zatrzymuje trening na przypadkowym drganiu krzywej.

Głębiej: wzór, kod, praktyka

Matematyka

Strata walidacyjna po epoce e: L_val(e) = −(1/m) · Σᵢ log p_e(yᵢ | xᵢ) na m obrazkach walidacyjnych (entropia krzyżowa).

Reguła z cierpliwością P: e = argmin_{e ≤ t} L_val(e); trening staje w pierwszej epoce t, dla której t − e ≥ P, i zwraca wagi w(e). Gdy taka epoka nie nadejdzie, zwraca w(e) z całego przebiegu.

Wczesne zatrzymanie działa podobnie jak kara z lekcji 3.4. Przy spadku gradientu z małym krokiem wagi startują blisko zera i oddalają się od niego z każdą epoką. Mniej epok to mniejsze wagi: dla modelu liniowego z kwadratową stratą zatrzymanie po t krokach daje w przybliżeniu ten sam efekt co ridge z α rzędu 1 / (krok · t).

W kodzie (Python)

Ten sam eksperyment w scikit-learn: 10 różnych podziałów i losowań szumu, sieć 64 → 32 → 10 uczona epoka po epoce, z zapamiętaniem wag z epoki o najniższej stracie walidacyjnej.

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 cyfr do nauki, 500 do walidacji, pozostałe 997 do testu
    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% etykiet treningowych zamienionych na losową cyfrę
    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  # wczesne zatrzymanie zachowuje wagi z najlepszej epoki
    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")

Wynik

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

Podziały, wagi startowe i szum są inne niż w labie, więc liczby też są inne. Obraz jest ten sam: najlepsza epoka wypada wcześnie (między 13 a 23), a trening do 100 epok obniża trafność testową we wszystkich 10 przebiegach, średnio z 87,2% do 76,4%.

Dla praktyka
  • W Kerasie: EarlyStopping(monitor="val_loss", patience=10, restore_best_weights=True). Bez restore_best_weights=True zostają wagi z ostatniej epoki, nie z najlepszej.
  • W PyTorchu pętlę piszesz sam: po każdej epoce licz stratę walidacyjną i zapisuj kopię wag, gdy jest najniższa.
  • W scikit-learn: MLPClassifier(early_stopping=True, n_iter_no_change=...) odkłada część danych treningowych na walidację; patrzy na trafność walidacyjną, nie na stratę. W gradient boostingu ten sam pomysł nazywa się n_iter_no_change albo early_stopping_rounds.
  • Liczba epok wybrana na walidacji to też hiperparametr: wynik walidacji w najlepszej epoce jest trochę zawyżony (lekcja 3.5), więc ostateczną ocenę rób na odłożonym teście.

Więcej w Atlasie

Hasła encyklopedii o pojęciach z tej lekcji: