ML Atlas

Kurs uczenia maszynowego od zera · Lekcja 5.5 · 30 z 33 gotowych lekcji · 12 min

Maszyny wektorów nośnych i jądra

W skrócie

SVM szuka najszerszego pasa między klasami. Gdy C rośnie z 0,01 do 100, pas kurczy się z 3,9 do 0,15 cm, a test prawie stoi. Jądro wycina środek osi.

Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
Z lekcji 5.4: Naiwny Bayes: fałszywe założenie, dobre decyzje U versicolor długość i szerokość płatka korelują z r = 0,80, a model trafia 93,3% kwiatów testowych. Co z tego wynika?

Pokaż odpowiedź

Poprawna odpowiedź: Do decyzji wystarczy, że właściwy gatunek dostaje największy iloczyn

Fałszywe założenie zmienia wartości iloczynów, ale rzadko ich kolejność, gdy gatunki leżą daleko od siebie. Model z korelacjami trafia średnio tylko trochę więcej.

Z lekcji 5.3: Gradient boosting: drzewa, które poprawiają błędy 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.

Dwa gatunki irysów, dwa pomiary płatka. Na treningu wiele prostych oddziela je równie dobrze. Maszyna wektorów nośnych (SVM, od ang. support vector machine) wybiera tę, wokół której zostaje najszerszy pusty pas, czyli margines. Kwiaty na brzegu pasa, w nim albo po złej stronie to wektory nośne. Tylko one wyznaczają granicę: resztę kwiatów można by usunąć, a granica zostałaby ta sama. Gdy klasy na siebie nachodzą, pas nie może być pusty, więc SVM płaci karę za każdy kwiat w pasie albo po złej stronie. Cenę tej kary ustawia liczba C. Małe C pozwala na szeroki pas z wieloma naruszeniami, duże C każe trzymać kwiaty po właściwej stronie, nawet kosztem wąskiego pasa.

Przewidź, potem sprawdź Liniowy SVM odróżnia irysy versicolor od virginiki po dwóch pomiarach płatka. Gdy C rośnie z 0,01 do 100, pas kurczy się z 3,9 cm do 0,15 cm, a granicę trzymają już tylko 4 kwiaty zamiast 70. Co dzieje się z trafnością na 30 kwiatach testowych?
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ź: Prawie się nie zmienia: przy każdym C model trafia 26 albo 27 z 30

Prawie bez zmian: przy wszystkich 9 wartościach C test to 26 albo 27 z 30. Pas zwęża się 26-krotnie, a wynik zmienia się o jeden kwiat. Na 20 innych podziałach trafność testowa przy różnych C różni się najwyżej o 2 kwiaty z 30.

Spróbuj

  • Zacznij od płatków przy C = 100. Ile kwiatów trzyma granicę i jak szeroki jest pas?
  • Przesuwaj C w dół. Przy którym C walidacja jest najlepsza, a przy którym pas jest najszerszy przy prawie tym samym wyniku?
  • Przełącz na działki kielicha. Czy jakieś C rozdziela tu gatunki?
  • Przejdź do win. Porównaj „tylko x”, cechy √2·x i x² oraz jądro (x·z + 1)². Potem włącz jądro RBF i przesuń γ (jak szybko maleje podobieństwo dwóch win, gdy się od siebie oddalają) aż do 1000.

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

Pomysł w prostych słowach

SVM nie liczy prawdopodobieństw jak regresja logistyczna. Rysuje granicę i dwie linie równoległe do niej, po jednej z każdej strony. Pas między nimi ma być jak najszerszy, a kwiaty mają leżeć poza nim, po swojej stronie. Kwiat, który się w to nie wpisuje, dostaje karę równą temu, jak głęboko wszedł w pas. To strata zawiasowa. Model szuka równowagi: szeroki pas z jednej strony, C razy suma kar z drugiej.

Przy C = 0,01 kary prawie nic nie kosztują. Pas ma 3,9 cm, a wszystkie 70 kwiatów treningowych to wektory nośne: każdy trochę przesuwa granicę. Przy C = 100 każde naruszenie jest drogie. Pas ma 0,15 cm, a granicę trzymają 4 kwiaty tuż przy niej. Test zmienia się przy tym o jeden kwiat. Na płatkach gatunki leżą na tyle daleko od siebie, że prawie każda rozsądna prosta trafia te same kwiaty.

C wybieramy jak każdy hiperparametr: walidacją, nie testem. Lab liczy walidację krzyżową na 5 części wewnątrz 70 kwiatów treningowych. Najlepsza wypada przy C = 10: 69 z 70. Przy C = 0,1 jest 68 z 70, a pas ma 1,4 cm zamiast 0,34 cm. Jeden kwiat różnicy to w walidacji szum, a szerszy pas opiera granicę na większej liczbie kwiatów. Najmniejsze C przesadza za to w drugą stronę: 64 z 70.

Granica nie musi być prosta. Na winach pytamy tylko, czy to odmiana 2, czy inna, więc klasy są dwie. Odmiana 2 leży pośrodku osi flawonoidów: odmiana 1 ma ich średnio 2,98, odmiana 2 2,08, a odmiana 3 0,78. Jeden próg nie wytnie środka, więc liniowy SVM woli tu nie wskazywać odmiany 2 nigdzie. Walidacja: 60,0%, tyle co odpowiedź „zawsze inna odmiana”. Zamieńmy x na dwie cechy: √2·x i x². Wina lądują na paraboli, a prosta w płaszczyźnie (√2·x, x²) to na osi dwa progi, czyli przedział. Walidacja rośnie do 72,0%.

Jądro robi to samo bez dopisywania kolumn. SVM potrzebuje tylko iloczynów skalarnych par przykładów. Iloczyn skalarny to suma iloczynów odpowiadających sobie współrzędnych dwóch przykładów; SVM używa go jako miary ich podobieństwa. Jądro (x·z + 1)² daje dokładnie iloczyn wektorów (1, √2·x, x²), więc granica wychodzi identyczna jak z cechami √2·x i x². To sztuczka jądrowa. Jądro RBF (od ang. radial basis function, funkcja radialna) exp(−γ(x − z)²) mierzy podobieństwo odległością: γ mówi, jak szybko podobieństwo maleje, gdy wina się od siebie oddalają. Odpowiada ono nieskończenie wielu takim cechom. Przy γ = 3 walidacja to 78,4%, najlepsza z ośmiu wartości γ, a test daje potem 84,9%. Przy γ = 0,3, 1 i 10 walidacja to 76,8%, tylko o 2 wina ze 125 mniej. Jak przy C na irysach, to praktycznie remis. Przy γ = 1000 trening rośnie do 89,6%, a walidacja spada do 69,6%. Granica rozpada się wtedy na 11 przedziałów dopasowanych do pojedynczych win. Najwyższy test, 86,8%, wypada przy γ = 100, ale wybór po teście to wybór na danych, którymi oceniasz.

Jak to policzono
  • Irysy: Iris (Fisher, 1936; UCI, licencja CC BY 4.0), 100 kwiatów versicolor i virginica. Pomiary w centymetrach bez skalowania, bo obie cechy mają tę samą jednostkę. Podział stratyfikowany: 70 kwiatów do nauki, 30 do testu.
  • Wina: Wine (Aeberhard i Forina, 1992; UCI, licencja CC BY 4.0), 178 win, sama zawartość flawonoidów, C = 1. Podział: 125 win do nauki, 53 do testu. Z-score liczony tylko z win uczących, a w walidacji z win uczących każdej części.
  • Walidacja: walidacja krzyżowa na 5 części ze stratyfikacją wewnątrz treningu. Model: SVM z miękkim marginesem; liczby zgadzają się z SVC z scikit-learn.

Dlaczego to działa

Szeroki pas to regularyzacja, jak kara w ridge z lekcji 3.4. Pas ma szerokość 2/‖w‖, więc szeroki pas to małe wagi i granica, która mniej zależy od pojedynczych kwiatów. Margines z karą za naruszenia opisali Cortes i Vapnik (1995). Sztuczkę jądrową do SVM wprowadzili wcześniej Boser, Guyon i Vapnik (1992): skoro model korzysta tylko z iloczynów skalarnych, każdy iloczyn można zastąpić jądrem.

To, że C zmienia geometrię bardziej niż wynik, nie jest przypadkiem jednego podziału. Na 20 innych podziałach irysów trafność testowa przy 9 wartościach C różni się najwyżej o 2 kwiaty z 30, a pas kurczy się z 3,8–4,1 cm do 0,17–0,36 cm.

Jądro RBF mierzy odległości, więc jednostki mają znaczenie. Wina mają 13 pomiarów: prolina sięga 1680, a odcień najwyżej 1,71. Bez skalowania odległość to prawie sama prolina. SVM z RBF na wszystkich 13 pomiarach trafia wtedy na 20 podziałach średnio 67,2% win walidacyjnych. Ze skalowaniem liczonym tylko na części do nauki: 97,9%.

Częsty błąd

Prawda czy fałsz: „zawsze bierz jądro RBF, bo jest najbardziej elastyczne”. Fałsz. Na płatkach irysów SVM liniowy i SVM z RBF, oba z ustawieniami wybranymi walidacją, trafiają na 20 podziałach średnio po 28,5 z 30 kwiatów testowych. RBF jest lepszy w 1 podziale i gorszy w 1. Granica jest tu prawie prosta, więc elastyczność nic nie daje, a kosztuje: dwa hiperparametry do strojenia zamiast jednego i łatwiejsze przeuczenie (γ = 1000 na winach). W kodzie niżej liniowy ma 0,950, RBF 0,947, a RBF jest lepszy w 2 podziałach i gorszy w 4.

Wniosek praktyczny: zacznij od jądra liniowego albo od regresji logistycznej. Po RBF sięgaj, gdy walidacja pokazuje, że granica nie jest prosta, jak na winach.

Quiz

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

1. Które kwiaty wyznaczają granicę liniowego SVM?
Pokaż odpowiedź

Poprawna odpowiedź: Wektory nośne: kwiaty na brzegu pasa, w nim albo za nim

Pozostałe kwiaty można usunąć, a granica się nie zmieni. Przy C = 100 trzymają ją 4 kwiaty z 70.

2. C rośnie z 0,01 do 100, pas kurczy się z 3,9 do 0,15 cm, a test zostaje przy 26–27 z 30. Co z tego wynika?
Pokaż odpowiedź

Poprawna odpowiedź: C zmienia geometrię bardziej niż wynik, bo gatunki leżą daleko

Na płatkach prawie każda rozsądna prosta trafia te same kwiaty. Nawet tu najmniejsze C ma na walidacji 64 z 70 wobec najlepszych 69, więc C i tak wybieraj walidacją.

3. Prawda czy fałsz: „zawsze bierz jądro RBF, bo jest najbardziej elastyczne”.
Pokaż odpowiedź

Poprawna odpowiedź: Fałsz, bo na płatkach liniowy trafia tyle samo, a RBF trzeba stroić

Na 20 podziałach oba trafiają średnio 28,5 z 30. Duże γ prowadzi do przeuczenia: na winach przy γ = 1000 trening 89,6%, walidacja 69,6%.

Najważniejsze wnioski

  • SVM wybiera granicę z najszerszym pasem; wyznaczają ją tylko wektory nośne.
  • C to cena naruszeń: od C = 0,01 do 100 pas kurczy się z 3,9 do 0,15 cm, a test prawie stoi (26–27 z 30).
  • Jądro daje granice, które nie są proste, bez liczenia nowych cech; (x·z + 1)² to dokładnie cechy √2·x i x².
  • C, jądro i γ wybieraj walidacją. RBF przy dużym γ się przeucza, a bez skalowania myli się dużo częściej.

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

Matematyka

Miękki margines: minimalizujemy ½‖w‖² + C · Σᵢ ξᵢ przy warunkach yᵢ(w·xᵢ + b) ≥ 1 − ξᵢ i ξᵢ ≥ 0. Szerokość pasa to 2/‖w‖, a ξᵢ = max(0, 1 − yᵢ f(xᵢ)) to strata zawiasowa.

W postaci dualnej f(x) = Σᵢ αᵢ yᵢ K(xᵢ, x) + b, gdzie 0 ≤ αᵢ ≤ C; wektory nośne to przykłady z αᵢ > 0. Jądro wielomianowe K(x, z) = (x·z + 1)² = φ(x)·φ(z) dla φ(x) = (1, √2·x, x²), jądro RBF K(x, z) = exp(−γ‖x − z‖²).

W kodzie (Python)

Ten sam eksperyment w scikit-learn: pas i wektory nośne przy trzech wartościach C, potem SVM liniowy i z jądrem RBF, oba z ustawieniami wybranymi walidacją, na 20 podziałach, a na koniec wina bez skalowania i ze skalowaniem.

import numpy as np
from sklearn.datasets import load_iris, load_wine
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

iris = load_iris(as_frame=True)
keep = iris.target > 0
X, y = iris.data.loc[keep, ["petal length (cm)", "petal width (cm)"]], iris.target[keep]
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, stratify=y, random_state=0)
for C in [0.01, 1, 100]:
    m = SVC(kernel="linear", C=C).fit(X_tr, y_tr)
    print(f"C = {C:>6}: band {2 / np.linalg.norm(m.coef_):.2f} cm, {m.n_support_.sum()} support vectors of {len(y_tr)}, test {m.score(X_te, y_te):.3f}")
grids = {"linear": {"svc__kernel": ["linear"], "svc__C": [0.01, 0.1, 1, 10, 100]},
         "RBF": {"svc__kernel": ["rbf"], "svc__C": [0.1, 1, 10, 100], "svc__gamma": [0.01, 0.1, 1, 10]}}
test = {k: [] for k in grids}
for seed in range(20):
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, stratify=y, random_state=seed)
    cv = StratifiedKFold(5, shuffle=True, random_state=seed)
    for k, grid in grids.items():
        search = GridSearchCV(make_pipeline(StandardScaler(), SVC()), grid, cv=cv).fit(X_tr, y_tr)
        test[k].append(search.score(X_te, y_te))
lin, rbf = np.array(test["linear"]), np.array(test["RBF"])
print(f"20 splits, settings chosen in validation: test linear {lin.mean():.3f}, RBF {rbf.mean():.3f}; RBF better {(rbf > lin).sum()}, worse {(rbf < lin).sum()}, equal {(rbf == lin).sum()}")
wine = load_wine()
cv = StratifiedKFold(5, shuffle=True, random_state=0)
for name, model in [("raw", SVC()), ("scaled inside each fold", make_pipeline(StandardScaler(), SVC()))]:
    print(f"wine, RBF SVM, {name}: validation {cross_val_score(model, wine.data, wine.target, cv=cv).mean():.3f}")

Wynik

C =   0.01: band 4.21 cm, 70 support vectors of 70, test 1.000
C =      1: band 0.71 cm, 22 support vectors of 70, test 1.000
C =    100: band 0.37 cm, 12 support vectors of 70, test 1.000
20 splits, settings chosen in validation: test linear 0.950, RBF 0.947; RBF better 2, worse 4, equal 14
wine, RBF SVM, raw: validation 0.657
wine, RBF SVM, scaled inside each fold: validation 0.983

Podział jest inny niż w labie, więc liczby też są trochę inne. Obraz jest ten sam: pas kurczy się z 4,21 do 0,37 cm, a test się nie zmienia (1,000). Jądro RBF na 20 podziałach nie bije liniowego (0,947 wobec 0,950). Bez skalowania SVM na winach ma 0,657, ze skalowaniem w każdej części 0,983.

Dla praktyka
  • W scikit-learn: SVC(kernel="linear") i SVC(kernel="rbf") (domyślnie gamma="scale"), a dla dużych zbiorów LinearSVC, który uczy się dużo szybciej. Według dokumentacji czas uczenia SVC rośnie co najmniej kwadratowo z liczbą przykładów, więc przy kilkudziesięciu tysiącach wierszy bywa niepraktyczny.
  • Cechy zawsze skaluj w pipeline'ie: make_pipeline(StandardScaler(), SVC()). Skaler w pipeline'ie uczy się tylko na części do nauki w każdej walidacji (lekcja 4.6).
  • C i γ strój razem, na siatce w skali logarytmicznej (GridSearchCV, lekcja 3.5). Duże C i duże γ to dwie drogi do przeuczenia.
  • SVM nie daje prawdopodobieństw wprost. SVC(probability=True) dopasowuje je osobną kalibracją w walidacji krzyżowej (lekcja 2.4), więc uczy się dłużej.

Więcej w Atlasie

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