Kurs uczenia maszynowego od zera · Lekcja 3.5 · 18 z 33 gotowych lekcji · 14 min
Strojenie hiperparametrów bez oszukiwania
W skrócie
Najlepsze z 9 ustawień drzewa ma w walidacji krzyżowej 93,7%, a na nowych biopsjach 88,3%. Wybór zwycięzcy zawyża wynik, tak samo jak wybór ziarna.
Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
W lekcji 3.2 walidacja krzyżowa oceniała jedno ustawienie modelu. W praktyce sprawdzasz ich wiele i bierzesz najlepsze. To się nazywa strojenie. Ustawienia, które wybierasz przed treningiem (głębokość drzewa, siła kary α z lekcji 3.4), to hiperparametry: model nie uczy się ich z danych, wybierasz je ty. Dziś zobaczysz, że wynik zwycięzcy strojenia jest zbyt optymistyczny i dlaczego.
Wybierz odpowiedź i pewność.
Odpowiedz, żeby odblokować lab.
Eksperyment
Ten interaktywny eksperyment działa w przeglądarce z włączonym JavaScriptem. Tekst wokół opisuje, co w nim widać.
Pokaż odpowiedź
Poprawna odpowiedź: Mniej, na przykład 88,3%, bo wybraliśmy też korzystny szum
Na 171 biopsjach testowych zwycięzca ma 88,3%, czyli o 5,4 pkt proc. mniej niż w walidacji krzyżowej. Część to selekcja, część to mały test: jedna biopsja to 0,6 pkt proc. Wybór najlepszego z 20 ziaren podziału zawyża wynik o 2,7 pkt proc. Ten podział wypadł po pesymistycznej stronie: na 50 innych podziałach (kod niżej) zwycięzca traci średnio 1,4 pkt proc.
Spróbuj
- Przy siatce przesuń budżet z 4 na 9. Jaki wynik ma zwycięzca w walidacji krzyżowej, a jaki na teście?
- Przełącz na przeszukiwanie losowe i kliknij kilka razy „nowe losowanie”. Czy zwycięzca na teście jest kiedyś lepszy niż w walidacji?
- W drugiej części przesuwaj suwak ziaren od 1 do 20. Jak rośnie najlepszy wynik i jak daleko odchodzi od średniej z 200 podziałów?
Gdy już sprawdzisz to w labie, nazwijmy, co widzisz.
Pomysł w prostych słowach
Strojenie to porównanie wielu ustawień na danych walidacyjnych i wybór najlepszego. Przeszukiwanie siatki sprawdza wszystkie kombinacje kilku wartości. Przeszukiwanie losowe losuje kombinacje z całego zakresu. Przy tym samym budżecie siatka 3×3 sprawdza tylko 3 głębokości: 1, 6 i 12. Losowanie 9 prób widzi zwykle więcej różnych wartości każdego hiperparametru.
Każdy wynik walidacji to prawdziwa jakość ustawienia plus trochę szczęścia: które biopsje akurat trafiły do których części. Gdy wybierasz najlepszy wynik, wybierasz też to ustawienie, któremu szczęście najbardziej dopisało. Na nowych danych tego szczęścia już nie ma. To klątwa zwycięzcy. Działa tym mocniej, im więcej ustawień porównujesz i im mniejsze są dane.
To samo dzieje się, gdy szukasz najlepszego podziału danych. Ta sama regresja logistyczna w 200 losowych podziałach ma średnio 93,8% na teście. Gdy wypróbujesz ziarna 1–20 i zgłosisz najlepsze, wyjdzie 96,5%, czyli o 2,7 pkt proc. więcej. Kod jest ten sam, wybrałeś tylko szczęście.
Jak to policzono
- Biopsje: Breast Cancer Wisconsin (Diagnostic), UCI, licencja CC BY 4.0. 569 biopsji, 10 pomiarów „mean” każdej.
- Strojenie: podział warstwowy, 398 biopsji do strojenia i 171 testowych. Drzewo CART (Gini), 10 głębokości razy 11 minimalnych liczb biopsji w liściu, czyli 110 ustawień, każde w 5-krotnej walidacji krzyżowej na 398 biopsjach.
- Zwycięzca: najlepsza średnia z 5 części; przy remisie prostsze drzewo. Na teście ocenia się drzewo uczone na wszystkich 398 biopsjach.
- Ziarna: regresja logistyczna (C = 1) na standaryzowanych pomiarach, 200 losowych podziałów 70/30, w każdym 171 biopsji testowych.
Dlaczego to działa
Weźmy 9 ustawień o prawie tej samej prawdziwej jakości. Ich wyniki w walidacji różnią się głównie szumem. Najwyższy z 9 wyników to prawie zawsze ten, w którym szum był dodatni. W labie najlepsze CV ma 373 trafień na 398 biopsji, a kilka ustawień jest tylko o jedną, dwie biopsje gorszych. Tak małe różnice to w dużej części przypadek.
Selekcję widać w drugim trybie labu: przy 200 losowaniach 9 ustawień zwycięzca ma w walidacji więcej niż na teście w każdym z nich, średnio o 3,6 pkt proc. Test nie brał udziału w wyborze, więc nie ma w nim selekcji. Jest tylko zwykły szum skończonego zbioru. Wszystkie 200 losowań to jednak różne ustawienia na tym samym podziale danych, a ten wypadł po pesymistycznej stronie: nawet bez żadnego wyboru 110 ustawień ma w walidacji średnio o 0,6 pkt proc. więcej niż na teście. W kodzie niżej, na 50 różnych podziałach, zwycięzca traci średnio 1,4 pkt proc., a w 17 z 50 podziałów walidacja nie wypada wyżej niż test.
Dlatego testu nie można używać do wyboru. Gdyby wybrać ustawienie po wyniku testu, najlepsza komórka miałaby na teście 92,4%. To też byłaby liczba zawyżona, tylko trudniej to zauważyć, bo nie zostałyby już żadne dane do sprawdzenia.
Częsty błąd
Prawda czy fałsz: „wynik zwycięzcy strojenia to prognoza na nowe dane”. Fałsz. Wynik zwycięzcy w walidacji jest zawyżony, bo to maksimum z wielu zaszumionych liczb. W labie zwycięzca 9 ustawień ma 93,7% w walidacji i 88,3% na teście. W kodzie niżej, na 50 podziałach i 110 ustawieniach, zwycięzca ma w walidacji średnio 93,3%, a na odłożonym teście 91,9%.
Uczciwą prognozę dają dwie drogi. Pierwsza: odłożony test, którego nie używasz do żadnego wyboru i oglądasz raz, na końcu. Druga: zagnieżdżona walidacja krzyżowa, czyli całe strojenie powtórzone wewnątrz każdej części zewnętrznej walidacji. Na wszystkich 569 biopsjach zwycięzca ma w zwykłej walidacji 94,0%, a zagnieżdżona daje 91,9%. Ta druga liczba jest bliżej tego, co model zrobi jutro.
Quiz
Trzy pytania na sprawdzenie się. Wybierz odpowiedź albo rozwiń odpowiedź pod pytaniem. Z klawiatury: strzałki wybierają, Enter albo spacja zatwierdza.
Najważniejsze wnioski
- Hiperparametry wybierasz ty, przed treningiem; stroisz je na walidacji, nigdy na teście.
- Wynik zwycięzcy strojenia jest zawyżony: wybierając najlepszy wynik, wybierasz też szczęście (klątwa zwycięzcy).
- Wybór najlepszego ziarna podziału to też strojenie na zbiorze testowym.
- Uczciwą prognozę daje odłożony test oglądany raz albo zagnieżdżona walidacja krzyżowa.
Głębiej: wzór, kod, praktyka
Matematyka
Niech prawdziwa jakość ustawienia k to μₖ, a wynik walidacji Ŝₖ = μₖ + εₖ, gdzie szum εₖ ma średnią 0. Dla jednego ustawienia E[Ŝₖ] = μₖ. Dla zwycięzcy k = argmaxₖ Ŝₖ średnio E[Ŝ_k] ≥ μ_k*: maksimum z kilku zaszumionych liczb jest średnio wyższe niż prawdziwa jakość wybranego. Przy m ustawieniach o tej samej jakości E[max εₖ] rośnie z m mniej więcej jak σ · √(2 · ln m).
Jedna biopsja testowa przy n = 171 to 1/171, czyli 0,6 pkt proc. Błąd standardowy trafności p na n przykładach: √(p(1 − p)/n).
Zagnieżdżona walidacja krzyżowa: zewnętrzna pętla dzieli dane na K części; dla każdej części całe strojenie (wewnętrzna walidacja krzyżowa) idzie tylko na pozostałych, a wybrany model ocenia się na odłożonej części.
W kodzie (Python)
Ten sam eksperyment w scikit-learn: klątwa zwycięzcy na 50 podziałach przy 110 ustawieniach drzewa, zwykła i zagnieżdżona walidacja krzyżowa na wszystkich biopsjach oraz najlepsze z 20 ziaren podziału.
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, GridSearchCV, StratifiedKFold, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
X, y = load_breast_cancer(return_X_y=True)
X = X[:, :10] # 10 pomiarów „mean”, jak w labie
grid = {"max_depth": [1, 2, 3, 4, 5, 6, 7, 8, 10, 12], "min_samples_leaf": [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48]} # 110 ustawień z labu
tree = DecisionTreeClassifier(random_state=0)
r = []
for s in range(50):
tr, te = train_test_split(np.arange(len(y)), test_size=0.3, stratify=y, random_state=s)
search = GridSearchCV(tree, grid, cv=StratifiedKFold(5, shuffle=True, random_state=s)).fit(X[tr], y[tr])
r.append((search.best_score_, search.score(X[te], y[te]))) # wynik zwycięzcy w CV, potem zwycięzca na odłożonym teście
r = np.array(r)
print(f"winner of 110 settings, 50 splits: CV {r[:, 0].mean():.1%}, held-out test {r[:, 1].mean():.1%}; CV higher in {(r[:, 0] > r[:, 1]).sum()} of 50")
outer = StratifiedKFold(5, shuffle=True, random_state=0)
flat = GridSearchCV(tree, grid, cv=outer).fit(X, y).best_score_ # wynik zwycięzcy na tych samych częściach, które go wybrały
nested = cross_val_score(GridSearchCV(tree, grid, cv=StratifiedKFold(5, shuffle=True, random_state=1)), X, y, cv=outer).mean() # strojenie idzie wewnątrz każdej części zewnętrznej
print(f"all 569 biopsies: winner's CV {flat:.1%}, nested CV {nested:.1%}")
model = make_pipeline(StandardScaler(), LogisticRegression())
acc = []
for s in range(200): # 200 losowych podziałów, 30% na test, jak w labie
tr, te = train_test_split(np.arange(len(y)), test_size=0.3, random_state=s)
acc.append(model.fit(X[tr], y[tr]).score(X[te], y[te]))
acc = np.array(acc)
best = acc.reshape(10, 20).max(axis=1) # dziesięć osób, każda próbuje 20 ziaren i zgłasza najlepsze
print(f"logistic regression, 200 seeds: mean {acc.mean():.1%}; best of 20 seeds {best.mean():.1%} on average (+{(best.mean() - acc.mean()) * 100:.1f} points), higher in {(best > acc.mean()).sum()} of 10")
Wynik
winner of 110 settings, 50 splits: CV 93.3%, held-out test 91.9%; CV higher in 33 of 50
all 569 biopsies: winner's CV 94.0%, nested CV 91.9%
logistic regression, 200 seeds: mean 93.7%; best of 20 seeds 96.4% on average (+2.6 points), higher in 10 of 10
Podziały są inne niż w labie, więc liczby też są inne. Obraz jest ten sam: zwycięzca strojenia ma w walidacji średnio 93,3%, a na odłożonym teście 91,9%; walidacja jest wyższa w 33 podziałach z 50. Zagnieżdżona walidacja daje 91,9% zamiast 94,0%, a najlepsze z 20 ziaren zawyża wynik o 2,6 pkt proc., u każdej z 10 osób.
Pobierz notebook (.ipynb). Otwórz go w Jupyterze albo wgraj do Google Colab; brakujące dane pobierze sam.
Dla praktyka
- W scikit-learn:
GridSearchCViRandomizedSearchCV. Wynikbest_score_jest zawyżony z tego samego powodu co w labie; oceniaj zwycięzcęscorena odłożonym teście. - Zagnieżdżona walidacja:
cross_val_score(GridSearchCV(...), X, y, cv=...). Strojenie idzie wtedy wewnątrz każdej części zewnętrznej. - Przy wielu hiperparametrach, z których ważnych jest niewiele, przeszukiwanie losowe zwykle znajduje dobre ustawienie szybciej niż siatka (Bergstra i Bengio, 2012).
- Ziarno losowania ustaw raz, przed eksperymentem, i zapisz. Podawaj średnią i rozrzut z kilku podziałów albo z walidacji krzyżowej, nie wynik najlepszego ziarna.
Czy to było pomocne?
Dzięki! To pomaga nam poprawiać Atlas.
Więcej w Atlasie
Hasła encyklopedii o pojęciach z tej lekcji: