ML Atlas

Kurs uczenia maszynowego od zera · Lekcja 3.4 · 17 z 33 gotowych lekcji · 12 min

Regularyzacja: ridge i lasso

W skrócie

Kara za duże wagi uspokaja model. Ridge ściąga wszystkie wagi, lasso zeruje je po kolei: przy 3 cechach z 10 R² na teście spada z 0,470 do 0,386.

Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
Z lekcji 3.3: Krzywe uczenia: więcej danych czy lepszy model? 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.

Z lekcji 3.2: Walidacja i walidacja krzyżowa Model A ma średnią trafność z walidacji krzyżowej odrobinę wyższą niż model B, ale rozrzut między foldami jest dużo większy niż ta różnica. Co z tego wynika?

Pokaż odpowiedź

Poprawna odpowiedź: Dane nie pokazują wiarygodnej różnicy między tymi modelami

Gdy różnica średnich jest mniejsza niż zmienność między foldami, łatwo może wynikać z przypadku.

W lekcji 3.1 model z wieloma parametrami nauczył się szumu: błąd treningowy spadał, a testowy rósł. Zamiast odbierać modelowi cechy, można mu za nie liczyć. Regularyzacja to kara dopisana do błędu treningowego: im większe wagi, tym większa kara. Siłę kary ustawia liczba α. Dziś sprawdzisz dwie kary na 10 cechach pacjentów z cukrzycą i zobaczysz, że jedna z nich wybiera cechy sama.

Przewidź, potem sprawdź Regresja liniowa przewiduje postęp cukrzycy po roku z 10 cech: wiek, płeć, BMI, ciśnienie krwi i sześć wyników krwi (s1–s6). Lasso to kara, która przy rosnącym α zeruje wagi cech po kolei. Która cecha zostanie ostatnia?
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ź: BMI, czyli wskaźnik masy ciała, bo sam niesie najwięcej informacji

Ostatnie zostaje BMI: przy α = 39,8 to jedyna cecha z wagą. Pierwsza na stałe znika s2 (od α = 0,398). Przy 3 cechach (BMI, ciśnienie i s5) R² na teście spada z 0,470 do 0,386.

Spróbuj

  • Przesuwaj α w lasso od najmniejszej wartości. W jakiej kolejności linie wag dochodzą do zera? Ile cech zostaje przy α = 15,8 i ile kosztuje to na teście?
  • Obserwuj s3. Kiedy pierwszy raz dotyka zera i co dzieje się z nią potem?
  • Przełącz na ridge i przesuń α do końca. Czy którakolwiek waga staje się dokładnie zerem?

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

Pomysł w prostych słowach

Zwykła regresja liniowa dobiera wagi tak, żeby błąd na danych treningowych był jak najmniejszy. Regularyzacja dopisuje do tego błędu karę za wielkość wag. Model musi teraz wybrać: lepiej dopasować dane czy mieć mniejsze wagi. Cecha zachowuje dużą wagę tylko wtedy, gdy naprawdę poprawia przewidywania.

Ridge karze sumę kwadratów wag. Ściąga wszystkie wagi w stronę zera, ale żadnej nie zeruje: w labie przy α = 398 R² na teście spada do 0,405, a wagę wciąż ma wszystkie 10 cech. Lasso karze sumę wartości bezwzględnych wag i zeruje je po kolei. Przy α = 15,8 zostają trzy cechy: BMI, ciśnienie i s5. Bez kary R² na teście wynosi 0,470, z trzema cechami 0,386. Model jest prostszy i tańszy w użyciu, ale gorzej przewiduje.

Cechy są wyrażone w odchyleniach standardowych. To ważne: kara liczy wielkość wag, więc cecha mierzona w dużych jednostkach miałaby małą wagę i uciekałaby karze.

Jak to policzono
  • Dane: Diabetes, Efron i in. (2004), Annals of Statistics. 442 pacjentów, 10 cech zmierzonych na początku badania, cel: postęp choroby po roku. Autorzy nie podali licencji; zbiór rozpowszechnia scikit-learn (licencja BSD-3-Clause).
  • Podział losowy: 309 pacjentów do nauki, 133 do testu. Średnie i odchylenia cech liczone tylko na części treningowej.
  • Lasso: 11 wartości α od 0,01 do 100. Ridge: 11 wartości α od 0,1 do 100000 (ridge w scikit-learn liczy karę w innej skali niż lasso, stąd inne liczby).
  • R² na teście: jaka część zmienności wyniku pacjentów testowych model wyjaśnia (1 = wszystko, 0 = tyle co średnia).

Dlaczego to działa

Kara lasso rośnie liniowo: zmniejszenie wagi o jednostkę zawsze oszczędza tyle samo kary, czy waga jest duża, czy mała. Jeśli cecha poprawia dopasowanie słabiej, niż kosztuje kara, opłaca się dać jej wagę dokładnie zero. Kara ridge rośnie z kwadratem wagi, więc przy małych wagach prawie nic nie kosztuje. Ridge zmniejsza wagę coraz bardziej, ale nigdy nie musi jej zerować.

Kara uspokaja też wagi cech, które mówią prawie to samo. s1 i s2 to dwa wyniki krwi silnie ze sobą powiązane (w kodzie niżej korelacja wynosi 0,90). Przy najsłabszej karze lasso s1 ma wagę −39,0, a s2 +26,2: dwie duże liczby o przeciwnych znakach, które prawie się znoszą. Takie wagi bardzo zmieniają się od próbki do próbki. Kara je ściąga, a lasso po chwili usuwa s2 w ogóle, bo s1 przenosi prawie tę samą informację.

To nie jest przypadek jednego podziału. W kodzie niżej ten sam eksperyment idzie na 50 losowych podziałach: BMI zostaje ostatnie w 37 z nich, s5 w pozostałych 13. Cecha, która znika pierwsza, zmienia się jeszcze bardziej: wiek w 21 podziałach, s2 w 16.

Częsty błąd

Prawda czy fałsz: „lasso dało cesze wagę zero, więc ta cecha nie ma znaczenia”. Fałsz. s2 znika jako pierwsza, choć jest silnie powiązana z s1: lasso wybiera z pary jedną cechę, a druga dostaje zero, bo nie wnosi nic nowego obok s1. Bez s1 s2 mogłaby być ważna. W labie widać to też na s3: przy α = 0,158 ma wagę zero, a przy α = 0,398 wraca, bo jest powiązana z s4 (r = −0,73) i lasso przerzuca wagę między nimi.

Wybór między skorelowanymi cechami bywa przypadkowy. W kodzie niżej pierwsza znika raz s2, raz wiek, a nawet ostatnie zostaje czasem s5 zamiast BMI, zależnie od tego, którzy pacjenci trafią do nauki. Zero w lasso znaczy: „ta cecha nie była potrzebna temu modelowi, przy tych danych i tym α”. Nie znaczy: „ta cecha nie ma związku z chorobą”.

Quiz

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

1. 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.

2. W labie lasso zostawia 3 cechy, a R² na teście spada z 0,470 do 0,386. Co to znaczy?
Pokaż odpowiedź

Poprawna odpowiedź: Że prostszy model kosztuje trochę trafności: trzeba ważyć oba cele

Mniej cech to model łatwiejszy w użyciu i wyjaśnieniu, ale tu wyjaśnia mniejszą część zmienności wyniku. Siłę kary wybiera się na walidacji, ważąc prostotę i trafność.

3. Prawda czy fałsz: „lasso dało cesze wagę zero, więc nie ma ona związku z chorobą”.
Pokaż odpowiedź

Poprawna odpowiedź: Fałsz, bo z pary skorelowanych cech lasso często zostawia jedną

s2 znika pierwsza, choć jest silnie powiązana z s1. Nie wnosi nic nowego obok s1, więc lasso daje jej zero. W 50 podziałach pierwsza znika raz s2, raz wiek.

Najważniejsze wnioski

  • Regularyzacja dopisuje do błędu karę za duże wagi; siłę kary ustawia α.
  • Ridge ściąga wszystkie wagi i żadnej nie zeruje; lasso zeruje je po kolei i wybiera cechy.
  • Prostszy model zwykle kosztuje trochę trafności: α wybierasz na walidacji, nie na teście.
  • Waga zero w lasso nie znaczy, że cecha jest bez znaczenia: z pary skorelowanych cech lasso często zostawia jedną.

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

Matematyka

Ridge: min_w ‖y − Xw‖² + α · Σⱼ wⱼ². Lasso: min_w (1/(2n)) · ‖y − Xw‖² + α · Σⱼ |wⱼ|. Tak liczy scikit-learn, dlatego te same liczby α znaczą w obu karach co innego.

Dlaczego lasso zeruje: przy cechach o średniej 0 i wariancji 1 jedna waga po poprawce ma postać wⱼ = sign(ρⱼ) · max(|ρⱼ| − α, 0), gdzie ρⱼ = (1/n) · xⱼᵀ rⱼ to związek cechy z resztą błędu bez niej. Gdy |ρⱼ| ≤ α, waga jest dokładnie zerem. Ridge daje wⱼ = ρⱼ / (1 + α/n) przy tych samych założeniach: waga maleje, ale zerem staje się tylko wtedy, gdy ρⱼ = 0.

R²: R² = 1 − Σ(yᵢ − ŷᵢ)² / Σ(yᵢ − ȳ)², liczone na pacjentach testowych.

W kodzie (Python)

Ten sam eksperyment w scikit-learn na 50 losowych podziałach (70% do nauki, 30% do testu): która cecha zostaje w lasso ostatnia, która znika pierwsza i ile kosztuje zostawienie najwyżej 3 cech.

import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, Lasso, lars_path
from sklearn.metrics import r2_score

X, y = load_diabetes(return_X_y=True)
names = np.array(["age", "sex", "bmi", "bp", "s1", "s2", "s3", "s4", "s5", "s6"])
alphas = 10 ** np.linspace(-2, 2, 41)  # zakres kar z labu, gęściej
last, first, r2 = [], [], []
for s in range(50):
    tr, te = train_test_split(np.arange(len(y)), test_size=0.3, random_state=s)
    sc = StandardScaler().fit(X[tr])
    Xtr, Xte = sc.transform(X[tr]), sc.transform(X[te])
    path_alphas, _, coefs = lars_path(Xtr, y[tr] - y[tr].mean(), method="lasso")  # dokładna ścieżka lasso, od najmocniejszej kary w dół
    enters = [np.flatnonzero(coefs[j])[0] if coefs[j].any() else len(path_alphas) for j in range(10)]  # gdzie każda cecha pierwszy raz dostaje wagę
    last.append(names[np.argmin(enters)]); first.append(names[np.argmax(enters)])  # pierwsza z wagą = ostatnia, która ją traci, gdy kara rośnie
    W = np.array([Lasso(alpha=a, max_iter=100000).fit(Xtr, y[tr]).coef_ for a in alphas])
    k3 = min(k for k in range(len(alphas)) if (W[k] != 0).sum() <= 3)  # najsłabsza kara, która zostawia najwyżej 3 cechy
    m3 = Lasso(alpha=alphas[k3], max_iter=100000).fit(Xtr, y[tr])
    r2.append((r2_score(y[te], LinearRegression().fit(Xtr, y[tr]).predict(Xte)), r2_score(y[te], m3.predict(Xte))))
r2 = np.array(r2)
print(f"last feature lasso keeps, 50 splits: {', '.join(f'{n} {last.count(n)}' for n in sorted(set(last), key=lambda n: (-last.count(n), n)))}")
print(f"first feature it drops for good: {', '.join(f'{n} {first.count(n)}' for n in sorted(set(first), key=lambda n: (-first.count(n), n)))}")
print(f"test R2: no penalty {r2[:, 0].mean():.3f}, at most 3 features {r2[:, 1].mean():.3f}; lower with 3 in {(r2[:, 1] < r2[:, 0]).sum()} of 50")
print(f"correlation of s1 and s2: {np.corrcoef(X[:, 4], X[:, 5])[0, 1]:.2f}")

Wynik

last feature lasso keeps, 50 splits: bmi 37, s5 13
first feature it drops for good: age 21, s2 16, s4 9, s1 2, s6 2
test R2: no penalty 0.471, at most 3 features 0.379; lower with 3 in 50 of 50
correlation of s1 and s2: 0.90

Podziały są inne niż w labie, więc liczby też są inne. Obraz jest ten sam: BMI zostaje ostatnie w 37 podziałach z 50 (s5 w pozostałych 13), a najwyżej 3 cechy obniżają R² na teście w każdym podziale, średnio z 0,471 do 0,379. Pierwsza znika raz s2, raz wiek: lasso wybiera między powiązanymi cechami, a wybór zależy od tego, którzy pacjenci trafili do nauki.

Dla praktyka
  • W scikit-learn: Ridge, Lasso i ElasticNet (mieszanka obu kar, pomocna przy grupach skorelowanych cech). Standaryzację wkładaj do pipeline'u (make_pipeline(StandardScaler(), Lasso())), żeby średnie i odchylenia liczyły się tylko na treningu.
  • Siłę kary wybieraj walidacją krzyżową: RidgeCV i LassoCV robią to od razu. Nie wybieraj α po wyniku testu: to strojenie na zbiorze testowym (lekcja 3.5).
  • Regresja logistyczna w scikit-learn ma karę ridge domyślnie (penalty="l2"); siłę ustawia C, czyli odwrotność α: mniejsze C to mocniejsza kara.
  • Jeśli chcesz mówić o ważności cech, nie czytaj samych zer z lasso. Sprawdź stabilność wyboru na wielu podziałach albo użyj metod z modułu 6.

Więcej w Atlasie

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