ML Atlas

Kurs uczenia maszynowego od zera · Lekcja 5.3 · 28 z 33 gotowych lekcji · 12 min

Gradient boosting: drzewa, które poprawiają błędy

W skrócie

Każde drzewo poprawia błędy poprzednich. Po 200 drzewach z krokiem 1 trening spada do 2287, a test rośnie do 5944, gorzej niż prosta (4095).

Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
Z lekcji 5.2: Zespoły modeli: czemu wiele drzew bije jedno Zwiększasz las losowy z 300 do 3000 drzew. Jaki jest najbardziej prawdopodobny skutek?

Pokaż odpowiedź

Poprawna odpowiedź: Trafność zostaje mniej więcej taka sama, a trening trwa dużo dłużej

Gdy niezależna część błędu już się uśredniła, kolejne drzewa dokładają obliczeń, ale mało trafności i żadnego dodatkowego uczenia na pamięć.

Z lekcji 5.1: Drzewa decyzyjne: dwadzieścia pytań do danych Jak drzewo decyzyjne wybiera pytanie na każdym kroku?

Pokaż odpowiedź

Poprawna odpowiedź: Sprawdza możliwe pytania i wybiera to, po którym grupy są najczystsze

Zachłanne szukanie ocenia kandydatów na podział i zostawia ten, który najbardziej obniża nieczystość, na przykład indeks Giniego.

W lekcji 5.2 las losowy uśredniał wiele drzew zbudowanych niezależnie od siebie i dokładanie drzew nie szkodziło. Gradient boosting buduje drzewa po kolei. Każde nowe drzewo uczy się reszt, czyli tego, o ile zespół drzew przed nim wciąż się myli przy każdym przykładzie. Do wyniku dokłada swoją poprawkę pomnożoną przez krok uczenia, liczbę od 0 do 1. Drzewa są małe, często z jednym pytaniem (taki pień) albo z trzema. Na tabelach średniej wielkości modele z drzew, z boostingiem na czele, zwykle wygrywają z sieciami neuronowymi (Grinsztajn i in., 2022). Boosting ma jednak cechę, której las nie ma: kolejne poprawki mogą zacząć poprawiać szum.

Przewidź, potem sprawdź Postęp cukrzycy po roku przewidujemy z samego BMI. Prosta regresja ma na pacjentach testowych błąd średniokwadratowy (MSE) 4095. Gradient boosting dokłada drzewa z najwyżej trzema pytaniami, każde z pełnym krokiem 1. Po 200 drzewach MSE na treningu spada z 3713 (jedno drzewo) do 2287. Jak wypada test?
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ź: Gorzej niż prosta, bo kolejne drzewa zaczęły poprawiać szum pacjentów treningowych

Gorzej: MSE na teście rośnie do 5944, choć na treningu spadło do 2287. Każde drzewo uczy się reszt poprzednich, a po kilku rundach w resztach zostaje głównie przypadkowy szum konkretnych pacjentów. Na 20 innych podziałach 200 takich drzew zawsze przegrywa z prostą na teście.

Spróbuj

  • Zacznij od startu: krok 1, głębokość 2, 200 drzew. Ile schodków ma funkcja zespołu i jak daleko leżą krzywe treningu i walidacji?
  • Przesuń liczbę drzew w dół. Przy ilu drzewach błąd walidacji jest najniższy? Dopiero potem spójrz na test.
  • Zmniejsz krok do 0,1 i weź pień. Jak teraz wygląda krzywa walidacji, gdy drzew przybywa?
  • Porównaj najlepszą walidację boostingu z przerywaną linią prostej. Która jest niżej?

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

Pomysł w prostych słowach

Pierwsze drzewo zadaje kilka pytań o BMI i przewiduje średni postęp choroby w każdej grupie. Myli się, więc liczymy reszty: ile brakuje do prawdy u każdego pacjenta. Drugie drzewo nie przewiduje już choroby, tylko te reszty. Jego wynik razy krok uczenia dokładamy do pierwszego. Trzecie drzewo uczy się tego, co zostało po dwóch, i tak dalej. Zespół rośnie z małych poprawek.

Na początku poprawki łapią prawdziwy wzór: większe BMI, większy postęp choroby. Gdy wzór jest już złapany, w resztach zostaje głównie szum, czyli przypadkowe odchylenia pacjentów, na których model się uczy. Kolejne drzewa uczą się właśnie jego. Przy kroku 1 i drzewach z trzema pytaniami trening spada z 3713 przy jednym drzewie do 2287 przy 200, a test rośnie z 4319 do 5944. To przeuczenie, tak jak przy zbyt głębokim drzewie, tylko tym razem rośnie z liczbą drzew. W lesie losowym każde drzewo widzi dane osobno, a uśrednianie gasi ich błędy. W boostingu każde drzewo dokłada się do błędów poprzednich.

Dlatego liczbę drzew, krok i głębokość wybiera walidacja, a nie test. Lab liczy błąd walidacji w walidacji krzyżowej na 5 części wewnątrz 309 pacjentów treningowych. Najniżej wypada pień z krokiem 0,1 i 50 drzewami: walidacja 3960. Prosta ma na tej samej walidacji 3823, więc na samym BMI wygrywa prosta. Test potwierdza to dopiero na końcu: 4154 dla boostingu wobec 4095 dla prostej.

Jak to policzono
  • Dane: Diabetes (Efron i in., 2004), w scikit-learn na licencji BSD-3-Clause. 442 pacjentów, 10 pomiarów, postęp choroby po roku. Bierzemy tylko BMI. Podział: 309 pacjentów do nauki, 133 do testu.
  • Model: gradient boosting z drzewami regresji głębokości 1 albo 2 na samym BMI, strata kwadratowa, krok 0,05 do 1, do 200 drzew; prosta regresja na BMI dla porównania. Liczby z labu zgadzają się z GradientBoostingRegressor z scikit-learn.
  • Walidacja: walidacja krzyżowa na 5 części wewnątrz 309 pacjentów treningowych, te same części dla każdego ustawienia i dla prostej.

Dlaczego to działa

Reszta y − F(x) to kierunek, w którym trzeba poprawić przewidywanie, żeby błąd kwadratowy najszybciej spadał. Każde drzewo robi więc mały krok spadku gradientu, tyle że w przestrzeni funkcji, a nie wag. Stąd nazwa: gradient boosting. Mały krok oznacza, że jedno drzewo poprawia tylko część błędu. Potrzeba więcej drzew, ale każde dokłada mniej szumu. Na 20 innych podziałach 200 drzew z trzema pytaniami i krokiem 0,1 ma na teście od 3747 do 4802, za każdym razem mniej niż te same drzewa z krokiem 1 (od 4617 do 6983).

Nie znaczy to, że boosting zawsze bije prostą. Na samym BMI związek z chorobą jest prawie liniowy, a drzewa umieją tylko naśladować prostą schodkami. Na 20 innych podziałach boosting wybrany walidacją wygrywa z prostą na teście w 7. Boosting błyszczy tam, gdzie cech jest wiele, a ich wpływ jest progowy i splątany. Wtedy kolejne drzewa łapią zależności, których prosta nie umie wyrazić.

Starszy krewny, AdaBoost, zamiast reszt zmienia wagi przykładów. Przykłady, które zespół myli, ważą w następnej rundzie więcej. W haśle Atlasu o AdaBoost pierwszy pień na guzach piersi myli 10,3% guzów treningowych. Przed drugą rundą te pomylone guzy niosą dokładnie 50% całej wagi, więc drugi pień uczy się głównie na nich.

Częsty błąd

Prawda czy fałsz: „więcej rund boostingu zawsze pomaga”. Fałsz. Każda runda poprawia trening, ale test tylko do pewnego momentu. Przy kroku 1 i drzewach z trzema pytaniami najlepiej na walidacji wypada 1 drzewo, a 200 drzew daje na teście 5944 zamiast 4319. W kodzie niżej test rośnie z 4079 po jednym drzewie do 6437 po 200, choć trening spada z 3827 do 2044.

Bezpieczna droga to mały krok, dużo drzew i wczesne zatrzymanie z lekcji 3.6: przestań dokładać drzewa, gdy błąd walidacji przestaje spadać. W kodzie niżej zatrzymanie zostawia 83 z 1000 drzew.

Quiz

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

1. Czego uczy się drugie drzewo w gradient boostingu?
Pokaż odpowiedź

Poprawna odpowiedź: Reszt pierwszego drzewa, czyli tego, o ile ono wciąż się myli

Każde kolejne drzewo dostaje reszty zespołu przed nim i dokłada poprawkę razy krok uczenia. Losowe próbki i niezależne drzewa to las losowy.

2. Krok 1, drzewa z trzema pytaniami: trening spada z 3713 do 2287, test rośnie z 4319 do 5944. Co się dzieje?
Pokaż odpowiedź

Poprawna odpowiedź: Przeuczenie: późne drzewa poprawiają szum pacjentów treningowych

Gdy prawdziwy wzór jest już złapany, w resztach zostaje szum. Kolejne drzewa uczą się go, a na nowych pacjentach ten szum się nie powtarza.

3. Prawda czy fałsz: „więcej rund boostingu zawsze pomaga”.
Pokaż odpowiedź

Poprawna odpowiedź: Fałsz, bo po pewnym czasie kolejne rundy poprawiają już tylko szum

Trening spada z każdą rundą, test nie. Przy kroku 1 najlepiej na walidacji wypada 1 drzewo, a 200 drzew daje na teście 5944.

Najważniejsze wnioski

  • Gradient boosting buduje drzewa po kolei: każde uczy się reszt zespołu przed nim i dokłada poprawkę razy krok uczenia.
  • W odróżnieniu od lasu boosting może się przeuczyć: przy kroku 1 test rośnie z 4319 do 5944, gdy trening spada.
  • Liczbę drzew, krok i głębokość wybieraj walidacją albo wczesnym zatrzymaniem, nigdy po teście.
  • Boosting nie zawsze bije prostą: na samym BMI prosta ma na walidacji 3823, a najlepszy boosting 3960.

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

Matematyka

Zespół po m drzewach: F_m(x) = F_{m−1}(x) + η · h_m(x), gdzie F_0 to średnia y na treningu, η to krok uczenia, a drzewo h_m dopasowuje reszty r_i = y_i − F_{m−1}(x_i).

Dla straty kwadratowej L = (y − F)² / 2 pochodna po F to −(y − F), więc reszta to minus gradient straty. Każde drzewo robi krok spadku gradientu w przestrzeni funkcji. W AdaBoost waga pomylonego przykładu rośnie razy e^α, gdzie α = ln((1 − ε) / ε), a ε to ważony błąd pnia.

W kodzie (Python)

Ten sam eksperyment w scikit-learn: 200 drzew z krokiem 1 krok po kroku, potem trzy ustawienia porównane walidacją krzyżową wewnątrz treningu i wczesne zatrzymanie.

from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error as mse

X, y = load_diabetes(return_X_y=True, as_frame=True)
x_tr, x_te, y_tr, y_te = train_test_split(X[["bmi"]], y, test_size=0.3, random_state=0)
big = GradientBoostingRegressor(n_estimators=200, max_depth=2, learning_rate=1.0, random_state=0).fit(x_tr, y_tr)
for m, (p_tr, p_te) in enumerate(zip(big.staged_predict(x_tr), big.staged_predict(x_te)), start=1):
    if m in (1, 10, 50, 200):
        print(f"step 1, depth 2, {m:3d} trees: train MSE {mse(y_tr, p_tr):.0f}, test MSE {mse(y_te, p_te):.0f}")
cv = KFold(5, shuffle=True, random_state=0)
models = {"line": LinearRegression(), "step 1, 200 trees": big,
          "step 0.1, 50 stumps": GradientBoostingRegressor(n_estimators=50, max_depth=1, learning_rate=0.1, random_state=0)}
for name, model in models.items():
    val = -cross_val_score(model, x_tr, y_tr, cv=cv, scoring="neg_mean_squared_error").mean()  # walidacja tylko wewnątrz treningu
    print(f"{name}: validation MSE {val:.0f}")
stop = GradientBoostingRegressor(n_estimators=1000, max_depth=1, learning_rate=0.1, validation_fraction=0.2, n_iter_no_change=10, random_state=0).fit(x_tr, y_tr)
print(f"early stopping kept {stop.n_estimators_} of 1000 trees; test MSE {mse(y_te, stop.predict(x_te)):.0f}, line {mse(y_te, models['line'].fit(x_tr, y_tr).predict(x_te)):.0f}")

Wynik

step 1, depth 2,   1 trees: train MSE 3827, test MSE 4079
step 1, depth 2,  10 trees: train MSE 3013, test MSE 4798
step 1, depth 2,  50 trees: train MSE 2122, test MSE 6233
step 1, depth 2, 200 trees: train MSE 2044, test MSE 6437
line: validation MSE 3956
step 1, 200 trees: validation MSE 5728
step 0.1, 50 stumps: validation MSE 4030
early stopping kept 83 of 1000 trees; test MSE 4062, line 3921

Podział jest inny niż w labie, więc liczby też są trochę inne. Obraz jest ten sam: przy kroku 1 trening spada z 3827 do 2044, a test rośnie z 4079 do 6437. Na walidacji prosta (3956) bije mały krok (4030), a 200 drzew z krokiem 1 wypada najgorzej (5728). Wczesne zatrzymanie zostawia 83 drzewa.

Dla praktyka
  • W scikit-learn: HistGradientBoostingRegressor i HistGradientBoostingClassifier są szybkie na dużych tabelach, same obsługują braki danych i mają wczesne zatrzymanie (early_stopping). Poza scikit-learn: XGBoost, LightGBM, CatBoost.
  • Typowy start: krok 0,05–0,1, płytkie drzewa, dużo drzew i wczesne zatrzymanie na walidacji. Głębokość i krok strój walidacją krzyżową (lekcja 3.5), a test zostaw na sam koniec.
  • Boosting jest wrażliwszy na szum w etykietach niż las: każdy błędny przykład zostaje w resztach i kolejne drzewa próbują go poprawić. Przy brudnych danych pomaga mniejszy krok, losowanie wierszy (subsample) i mocniejsza regularyzacja drzew.
  • Zanim sięgniesz po boosting, zmierz prosty punkt odniesienia (lekcja 1.3). Gdy związek jest prawie liniowy, prosta potrafi wygrać.

Więcej w Atlasie

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