ML Atlas

Kurs uczenia maszynowego od zera · Lekcja 3.3 · 16 z 33 gotowych lekcji · 12 min

Krzywe uczenia: więcej danych czy lepszy model?

W skrócie

Krzywe uczenia pokazują wynik na treningu i walidacji, gdy danych przybywa. Z ich kształtu wiesz, czy zbierać dane, czy zmienić model na bogatszy.

Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
Z lekcji 3.2: Walidacja i walidacja krzyżowa Dlaczego skalowanie cech na wszystkich wierszach przed walidacją krzyżową to błąd?

Pokaż odpowiedź

Poprawna odpowiedź: Bo statystyki z foldów walidacyjnych przeciekają do treningu i zawyżają wyniki

Każdy krok, który uczy się z danych, trzeba dopasować wyłącznie na foldach treningowych, inaczej foldy walidacyjne przestają być nieznane.

Z lekcji 3.1: Przeuczenie: gdy model uczy się na pamięć Co dzieje się z błędem treningowym, gdy rośnie stopień wielomianu?

Pokaż odpowiedź

Poprawna odpowiedź: Spada albo stoi w miejscu, bo giętsza krzywa może skopiować prostszą

Wielomian wyższego stopnia zawiera każdy niższy jako szczególny przypadek, więc nigdy nie dopasuje się do punktów treningowych gorzej.

W lekcji 3.1 model był za prosty albo za złożony, a danych było tyle samo. Dziś zmieniasz liczbę danych. To codzienne pytanie praktyka: model działa średnio, więc zbierać więcej przykładów czy zmienić model? Odpowiedź daje krzywa uczenia: wynik na treningu i na walidacji, rysowany dla coraz większego zbioru do nauki.

Przewidź, potem sprawdź Regresja logistyczna uczy się rozpoznawać odręczne cyfry z 50 obrazów. Na tych 50 obrazach ma 100% trafności. Ile mniej więcej trafi na nowych cyfrach z walidacji?
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ź: Około 82%, czyli o kilkanaście punktów mniej niż na treningu

Walidacja ma 82,3% (średnia z 5 losowań 50 obrazów), więc luka wynosi 17,7 pkt proc. Na pełnym treningu, 1438 obrazach, walidacja rośnie do 95,8%, a luka maleje do 2,2 pkt proc. Przy małych danych 100% na treningu to w dużej części pamięć.

Spróbuj

  • Przy modelu szczegółowym przesuwaj suwak od 50 do 1438 obrazów. Która krzywa się zmienia bardziej: treningu czy walidacji?
  • Przełącz na model rozmytych cyfr. Gdzie spotykają się jego krzywe i jak wysoko?
  • Porównaj model szczegółowy przy 100 obrazach z modelem rozmytym przy 1438. Który wygrywa?

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

Pomysł w prostych słowach

Krzywa uczenia to dwie linie: trafność na danych do nauki i na walidacji, w zależności od liczby przykładów do nauki. Przy kilkudziesięciu obrazach model zapamiętuje każdy z nich: trening ma 100%, a walidacja 82,3%. Im więcej danych, tym trudniej wszystko zapamiętać, więc trening spada (do 98,0%), a walidacja rośnie (do 95,8%). Luka między nimi maleje z 17,7 do 2,2 pkt proc.

Z kształtu tych linii czytasz decyzję:

  • Duża luka, walidacja wciąż rośnie (wysoka wariancja): model zna trening dużo lepiej niż nowe dane. Więcej danych pomoże, podobnie jak regularyzacja.
  • Mała luka, obie linie nisko (wysokie obciążenie): model jest za prosty. Krzywe się zeszły i więcej danych prawie nic nie da. Pomoże bogatszy model albo lepsze cechy.

Model rozmytych cyfr widzi każdą cyfrę jako obrazek 4 × 4, czyli 16 pikseli zamiast 64. Przy 1438 obrazach ma na treningu 86,9%, na walidacji 85,0%, luka to tylko 1,9 pkt proc. Walidacja zwykle nie wychodzi ponad trening, a ten ma tylko 86,9%. Model szczegółowy przy zaledwie 100 obrazach ma już 87,6%.

Jak to policzono
  • Cyfry: Optical Recognition of Handwritten Digits, UCI, licencja CC BY 4.0. 1797 obrazów 8 × 8 pikseli, 10 cyfr.
  • Podział 80/20 ze stratyfikacją, taki sam jak w widżecie Atlasu: 1438 obrazów do nauki, 359 do walidacji. Dla każdego rozmiaru średnia z 5 losowań, które obrazy idą do nauki.
  • Model: regresja logistyczna (softmax) z karą 0,001 za duże wagi. Model rozmyty widzi średnie bloków 2 × 2 pikseli.

Dlaczego to działa

Na treningu model widzi odpowiedzi, więc przy małych danych może je zapamiętać. Każdy nowy przykład utrudnia zapamiętywanie, a ułatwia znalezienie reguły, która działa też poza treningiem. Dlatego linie idą ku sobie: trening w dół, walidacja w górę. Spotkają się na poziomie, który ten model w ogóle potrafi osiągnąć.

Ten poziom zależy od modelu, nie od danych. Rozmyty obrazek gubi szczegóły, które odróżniają na przykład 3 od 8, i żadna liczba przykładów ich nie odda. W kodzie niżej ten sam eksperyment idzie na 50 różnych podziałach: model rozmyty ma przy pełnych danych 86,4% na treningu i 85,1% na walidacji, a szczegółowy 96,6% na walidacji. Szczegółowy model ze 100 obrazów bije rozmyty z 1437 obrazów w 49 podziałach na 50.

Częsty błąd

Prawda czy fałsz: „więcej danych zawsze pomaga”. Fałsz. Więcej danych pomaga, gdy model jest za mocny jak na ilość danych: wtedy luka jest duża, a walidacja rośnie. Gdy model jest za prosty, krzywe szybko się schodzą i stoją. W labie model rozmyty ma przy 400 obrazach 83,6% na walidacji, a przy prawie czterokrotnie większym zbiorze 85,0%. Model szczegółowy przy tych samych danych ma 95,8%. Zanim zapłacisz za zebranie danych, narysuj krzywą uczenia: jeśli trening sam stoi nisko, dane nie pomogą.

Uwaga: krzywe rysuj na walidacji albo w walidacji krzyżowej, nie na zbiorze testowym. Test zostaje na samą ocenę końcową.

Quiz

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

1. Trening ma 100%, walidacja 82,3%, a krzywa walidacji wciąż rośnie. Co najpewniej pomoże?
Pokaż odpowiedź

Poprawna odpowiedź: Więcej danych do nauki, bo duża luka oznacza, że model zapamiętuje

Duża luka i rosnąca walidacja to wysoka wariancja. Na pełnym treningu ten sam model ma 95,8% na walidacji, a luka spada do 2,2 pkt proc.

2. Model rozmytych cyfr ma przy 1438 obrazach 86,9% na treningu i 85,0% na walidacji. Co zrobić?
Pokaż odpowiedź

Poprawna odpowiedź: Zmienić model na bogatszy, bo obie krzywe zeszły się nisko

To wysokie obciążenie: walidacja nie przeskoczy treningu, a ten ma tylko 86,9%. Model na wszystkich 64 pikselach ma przy tych samych danych 95,8%.

3. Dlaczego trafność na treningu spada, gdy danych do nauki przybywa?
Pokaż odpowiedź

Poprawna odpowiedź: Bo coraz trudniej zapamiętać wszystkie przykłady, więc model uogólnia

Przy 50 obrazach model trafia wszystkie, przy 1438 już 98,0%. Za to walidacja rośnie z 82,3% do 95,8%.

Najważniejsze wnioski

  • Krzywa uczenia to wynik na treningu i walidacji dla coraz większego zbioru do nauki.
  • Duża luka i rosnąca walidacja: model zapamiętuje, więcej danych pomoże.
  • Mała luka przy niskim wyniku: model jest za prosty, pomoże bogatszy model albo lepsze cechy, nie więcej danych.
  • Narysuj krzywą, zanim zapłacisz za dane; rysuj ją na walidacji, a test zostaw na koniec.

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

Matematyka

Niech A_tr(n) i A_wal(n) to trafność na n przykładach do nauki i na walidacji. Krzywa uczenia to obie funkcje n. Zwykle A_tr(n) maleje, A_wal(n) rośnie, a obie zbliżają się do tego samego poziomu A*, najlepszej trafności, jaką osiąga ta rodzina modeli.

Luka A_tr(n) − A_wal(n) mierzy wariancję: jak bardzo wynik zależy od tego, które przykłady trafiły do nauki. Odległość 1 − A to obciążenie tej rodziny modeli razem z szumem, którego nie usunie żaden model (cyfry nieczytelne nawet dla człowieka): tego żadne dane nie usuną. Więcej danych zmniejsza lukę, a tylko zmiana modelu podnosi A.

Regresja logistyczna w labie minimalizuje L = średnia strata + (λ / 2) · ‖W‖² z λ = 0,001. W scikit-learn ta sama kara to C = 1 / (λ · n) = 1000 / n.

W kodzie (Python)

Ten sam eksperyment w scikit-learn na 50 różnych podziałach: model na 64 pikselach i na cyfrze rozmytej do 16 pikseli, przy rosnącej liczbie obrazów do nauki.

import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

X, y = load_digits(return_X_y=True)
X = X / 16  # 8 × 8 = 64 piksele od 0 do 1, jak w labie
X16 = X.reshape(-1, 4, 2, 4, 2).mean(axis=(2, 4)).reshape(len(X), -1)  # ta sama cyfra rozmyta do 4 × 4 = 16 pikseli
def run(Z, n, seed):
    Xtr, Xva, ytr, yva = train_test_split(Z, y, test_size=0.2, stratify=y, random_state=seed)
    i = np.random.default_rng(seed).permutation(len(ytr))[:n]  # pierwsze n obrazów treningowych po przetasowaniu
    m = LogisticRegression(C=1000 / n, max_iter=5000).fit(Xtr[i], ytr[i])  # C = 1000 / n to kara 0,001 z labu
    return m.score(Xtr[i], ytr[i]), m.score(Xva, yva)
for name, Z in (("64 pixels", X), ("16 pixels", X16)):
    for n in (50, 100, 400, 800, 1437):
        tr, va = np.mean([run(Z, n, s) for s in range(50)], axis=0)  # średnia z 50 różnych podziałów
        print(f"{name}, {n} images: training {tr:.1%}, validation {va:.1%}, gap {(tr - va) * 100:.1f} points")
wins = sum(run(X, 100, s)[1] > run(X16, 1437, s)[1] for s in range(50))
print(f"64 pixels from 100 images beat 16 pixels from 1437 images in {wins} of 50 splits")

Wynik

64 pixels, 50 images: training 100.0%, validation 81.2%, gap 18.8 points
64 pixels, 100 images: training 100.0%, validation 89.5%, gap 10.5 points
64 pixels, 400 images: training 99.7%, validation 94.9%, gap 4.8 points
64 pixels, 800 images: training 99.0%, validation 96.0%, gap 2.9 points
64 pixels, 1437 images: training 98.2%, validation 96.6%, gap 1.6 points
16 pixels, 50 images: training 98.5%, validation 72.6%, gap 25.9 points
16 pixels, 100 images: training 94.1%, validation 79.8%, gap 14.4 points
16 pixels, 400 images: training 87.7%, validation 83.8%, gap 3.8 points
16 pixels, 800 images: training 86.9%, validation 84.6%, gap 2.3 points
16 pixels, 1437 images: training 86.4%, validation 85.1%, gap 1.3 points
64 pixels from 100 images beat 16 pixels from 1437 images in 49 of 50 splits

Lab pokazuje jeden podział i 5 losowań, kod 50 podziałów, więc liczby są trochę inne: przy 50 obrazach walidacja ma w labie 82,3%, a średnio 81,2%. Kształt krzywych i wniosek są te same.

Dla praktyka
  • W scikit-learn krzywe daje learning_curve (z walidacją krzyżową) i LearningCurveDisplay. Dla klasyfikacji używaj StratifiedKFold, żeby każdy rozmiar miał wszystkie klasy.
  • Oś liczby przykładów rysuj w skali logarytmicznej: postęp przy podwajaniu danych jest wtedy lepiej widoczny.
  • Krzywa walidacji (validation_curve) to coś innego: wynik w zależności od ustawienia modelu, np. siły regularyzacji, przy stałych danych.
  • Zanim zbierzesz dane, oszacuj, ile da podwojenie: jeśli ostatnie podwojenie dało ułamek punktu, następne da jeszcze mniej.

Więcej w Atlasie

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