ML Atlas

Kurs uczenia maszynowego od zera · Lekcja 4.4 · 23 z 33 gotowych lekcji · 12 min

Inżynieria cech

W skrócie

Odmiana 2 leży pośrodku osi i żaden próg jej nie wytnie. Nowa kolumna x² daje 77,4% zamiast 60,4%, a 200 kolumn szumu obniża kNN z 98,1% do 77,4%.

Rozgrzewka Dwa pytania z wcześniejszych lekcji. Minuta, a lekcji nie blokuje.
Z lekcji 4.3: Kategorie i skalowanie Dlaczego kNN bez skalowania ma na winach trafność tylko 0,695?

Pokaż odpowiedź

Poprawna odpowiedź: Bo prolina ma ogromny rozrzut i to ona rządzi całą odległością

Prolina ma odchylenie standardowe 314, najmniej zmienny pomiar 0,124. Bez skalowania odległość to prawie sama różnica proliny. Po standaryzacji trafność rośnie do 0,963.

Z lekcji 4.2: Braki danych BMI brakuje u 110 najcięższych pacjentów. Co robi wpisanie średniej z pozostałych?

Pokaż odpowiedź

Poprawna odpowiedź: Osłabia związek BMI z chorobą, bo chorzy najbardziej lądują przy przeciętnym BMI

Korelacja spada z 0,586 do 0,352. 110 pacjentów z dużym postępem choroby siedzi w jednym punkcie: przy średniej 24,3.

W lekcji 4.3 zmienialiśmy zapis cech: skalę liczb i kod kategorii. Dziś robimy nowe cechy z tych, które już są. Inżynieria cech to dodawanie kolumn, które lepiej pokazują modelowi to, czego szuka: kwadratu, ilorazu, różnicy, liczby dni od zdarzenia. Jedna dobra cecha potrafi z trudnego problemu zrobić łatwy. Wiele słabych potrafi zepsuć model, który działał.

Przewidź, potem sprawdź Wina z trzech odmian. Model liniowy ma odróżnić odmianę 2 od pozostałych tylko po zawartości flawonoidów. Na jednej osi model liniowy stawia jeden próg: po jednej stronie „odmiana 2”, po drugiej „inna”. Odmiana 2 ma średnio 2,08, odmiana 1 ma 2,98, a odmiana 3 ma 0,78. Czy jeden próg oddzieli odmianę 2?
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ź: Nie, bo odmiana 2 leży pośrodku i z obu stron ma wina z innych odmian

Nie. Pośrodku osi jeden próg zawsze zostawia po stronie „odmiana 2” jedną z dwóch pozostałych odmian. Najlepszy próg na treningu trafia 61,6%, ledwie więcej niż 60,0% za mówienie „inna odmiana” o każdym winie, a na winach testowych tyle samo co ono: 60,4%. Liniowy SVM z labu nie wskazuje odmiany 2 nigdzie. Dopiero nowa kolumna x² pozwala wyciąć środkowy przedział.

Spróbuj

  • Zacznij od samego x. Gdzie model przewiduje odmianę 2? Ile wynosi trafność na teście i skąd się bierze?
  • Dodaj kolumnę x². Jak wygląda granica w płaszczyźnie (x, x²), a jak na samej osi flawonoidów?
  • Przejdź do szumu. Przesuń suwak od 200 kolumn w dół. Kiedy kNN rozpoznaje odłożone wina najlepiej?
  • Patrz na kontrast odległości. Co się dzieje z różnicą między najbliższym a najdalszym winem, gdy kolumn przybywa?

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

Pomysł w prostych słowach

Model liniowy na jednej osi umie tylko jedno: postawić próg. Odmiana 2 leży pośrodku osi flawonoidów, więc próg nie wytnie jej z żadnej strony: odetnie najwyżej jedną z sąsiednich odmian. Najlepszy taki próg odcina odmianę 3 i trafia na treningu 61,6%, a mówienie „inna odmiana” o każdym winie 60,0%. Zysk jest znikomy, a na teście znika. Liniowy SVM z labu nie wskazuje odmiany 2 nigdzie i ma trafność 60,4%, tyle, ile udział pozostałych odmian wśród 53 win testowych. Dodajmy kolumnę x², czyli kwadrat flawonoidów po standaryzacji. Wina z obu końców osi mają duże x², wina ze środka małe. Ten sam model liniowy kładzie teraz prostą w płaszczyźnie (x, x²). Na osi flawonoidów to dwa progi, czyli przedział od 1,11 do 2,82. Trafność rośnie do 77,4%. Model się nie zmienił, zmieniło się to, co dostaje.

Więcej cech nie znaczy jednak lepiej. kNN (k = 5) na 13 pomiarach chemicznych rozpoznaje 98,1% odłożonych win. Dokładamy kolumny czystego szumu, liczb losowych w tej samej skali. Przy 200 takich kolumnach trafność spada do 77,4%. Każda kolumna szumu dokłada do odległości tyle samo co prawdziwy pomiar, więc „najbliższe” wina przestają być podobne. To przekleństwo wymiarowości: w wielu wymiarach wszystkie punkty leżą prawie tak samo daleko od siebie.

Jak to policzono
  • Wina: Wine (Aeberhard i Forina, 1992; UCI, licencja CC BY 4.0), 178 win, 13 pomiarów chemicznych, 3 odmiany. Podział stratyfikowany: 125 win do nauki, 53 do testu.
  • Nowa cecha: model liniowy (liniowa maszyna wektorów nośnych, C = 1) na flawonoidach po standaryzacji, odmiana 2 przeciw pozostałym. Średnie flawonoidów liczone na wszystkich 178 winach.
  • Szum: kNN z k = 5 na 13 pomiarach po standaryzacji i 0 do 200 kolumnach liczb z rozkładu normalnego (średnia 0, odchylenie 1), losowanych z ustalonym ziarnem.

Dlaczego to działa

Model liniowy dzieli przestrzeń prostą (w wyższych wymiarach płaszczyzną). Na jednej osi prosta to jeden punkt, czyli próg. Kolumna x² dodaje drugą oś. Wina z obu końców osi flawonoidów lądują wysoko na paraboli, a wina ze środka nisko. Teraz odmianę 2 da się odciąć prostą od góry. Na 20 innych podziałach win bez x² liniowy SVM nie wskazuje odmiany 2 ani razu, a najlepszy pojedynczy próg z treningu bije na teście „zawsze inna” tylko w 1 z 20. Z x² zawsze wycina jeden przedział: na teście od 67,9 do 84,9%.

Z szumem jest odwrotnie. Odległość w kNN to suma kwadratów różnic ze wszystkich kolumn. Przy 13 pomiarach najdalsze wino treningowe leży średnio o 296,5% dalej niż najbliższe. Przy 200 kolumnach szumu już tylko o 25,7%. Różnice w szumie są przypadkowe, a jest ich dużo, więc przykrywają 13 prawdziwych różnic. Na 20 losowaniach szumu 200 kolumn daje od 64,2 do 83,0%, zawsze mniej niż 98,1% bez szumu.

Częsty błąd

Prawda czy fałsz: „więcej cech to lepszy model”. Fałsz. Cecha pomaga, gdy niesie informację w kształcie, który model umie użyć, jak x² dla odmiany 2. Kolumny bez informacji szkodzą: 200 kolumn szumu obniża kNN z 98,1% do 77,4%. W kodzie niżej trafność kNN spada z 0,962 bez szumu do 0,689 przy 200 kolumnach.

Dobra nowa cecha zwykle wynika ze zrozumienia problemu: co powinno mieć znaczenie i w jakim kształcie. Dokładanie wszystkiego, co się da, to zaproszenie dla szumu.

Quiz

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

1. Dlaczego jeden próg na samych flawonoidach nie oddzieli odmiany 2?
Pokaż odpowiedź

Poprawna odpowiedź: Bo odmiana 2 leży pośrodku osi, a jeden próg nie wytnie środkowego przedziału

Średnio 2,08 przy 2,98 i 0,78 dla pozostałych. Każdy próg zostawia po stronie „odmiana 2” też inną odmianę. Najlepszy próg trafia na treningu 61,6% wobec 60,0% za „zawsze inna”, a liniowy SVM nie wskazuje odmiany 2 nigdzie: 60,4%.

2. Do 13 pomiarów win dokładasz 200 kolumn losowego szumu. Co dzieje się z kNN?
Pokaż odpowiedź

Poprawna odpowiedź: Trafność spada, bo szum przykrywa w odległości prawdziwe różnice między winami

Trafność spada z 98,1% do 77,4%. Każda kolumna szumu waży w odległości tyle co prawdziwy pomiar.

3. Prawda czy fałsz: „więcej cech to lepszy model”.
Pokaż odpowiedź

Poprawna odpowiedź: Fałsz, bo cechy bez informacji dokładają szum i potrafią obniżyć trafność

200 kolumn szumu obniża kNN z 98,1% do 77,4%. Pomaga cecha z informacją w dobrym kształcie, jak x² dla odmiany 2.

Najważniejsze wnioski

  • Jedna cecha w dobrym kształcie robi z trudnego problemu łatwy: x² podnosi trafność z 60,4% do 77,4%.
  • Model liniowy z nowymi kolumnami wciąż jest liniowy; zmienia się to, co dostaje na wejściu.
  • Kolumny bez informacji szkodzą: 200 kolumn szumu obniża kNN z 98,1% do 77,4%.
  • W wielu wymiarach odległości się wyrównują, więc modele oparte na odległości tracą najszybciej.

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

Matematyka

Nowa cecha: z = (x − x̄) / s, a model liniowy dostaje (z, z²). Granica w₁ · z + w₂ · z² + b = 0 to równanie kwadratowe w z, więc ma do dwóch pierwiastków: dwa progi na osi x i przedział między nimi.

Odległość w kNN: d(a, b)² = Σⱼ (aⱼ − bⱼ)² po wszystkich kolumnach. Dla m kolumn szumu z rozkładu N(0, 1) każda dokłada średnio 2 do d² (wariancja różnicy dwóch niezależnych liczb), niezależnie od odmiany. Przy m dużym suma szumu przykrywa 13 prawdziwych składników, a kontrast (d_max − d_min) / d_min maleje.

W kodzie (Python)

Ten sam eksperyment w scikit-learn: model liniowy na flawonoidach bez x² i z x² w walidacji krzyżowej 10 × 5, potem kNN na 13 pomiarach i coraz większej liczbie kolumn szumu.

import numpy as np
from sklearn.datasets import load_wine
from sklearn.model_selection import cross_val_score, RepeatedStratifiedKFold
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier

wine = load_wine(as_frame=True)
x, is2 = wine.data[["flavanoids"]], (wine.target == 1).astype(int)
cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=10, random_state=0)
line = make_pipeline(StandardScaler(), SVC(kernel="linear", C=1))
squared = make_pipeline(StandardScaler(), PolynomialFeatures(2, include_bias=False), StandardScaler(), SVC(kernel="linear", C=1))  # nowa kolumna x²
a, b = cross_val_score(line, x, is2, cv=cv), cross_val_score(squared, x, is2, cv=cv)
print(f"cultivar 2 vs the rest from flavanoids, 10 x 5 CV: x only {a.mean():.3f}, x and x^2 {b.mean():.3f}; always 'other' {1 - is2.mean():.3f}")
print(f"x only predicts cultivar 2 for {line.fit(x, is2).predict(x).sum()} of {len(x)} wines; x and x^2 wins in {(b > a).sum()} of 50 folds")
X, y = wine.data.to_numpy(), wine.target.to_numpy()
noise = np.random.default_rng(0).normal(size=(len(X), 200))  # kolumny czystego szumu
for m in [0, 10, 50, 200]:
    acc = cross_val_score(make_pipeline(StandardScaler(), KNeighborsClassifier(5)), np.hstack([X, noise[:, :m]]), y, cv=cv)
    print(f"kNN on 13 measurements + {m} noise columns: {acc.mean():.3f}")

Wynik

cultivar 2 vs the rest from flavanoids, 10 x 5 CV: x only 0.601, x and x^2 0.755; always 'other' 0.601
x only predicts cultivar 2 for 0 of 178 wines; x and x^2 wins in 49 of 50 folds
kNN on 13 measurements + 0 noise columns: 0.962
kNN on 13 measurements + 10 noise columns: 0.940
kNN on 13 measurements + 50 noise columns: 0.842
kNN on 13 measurements + 200 noise columns: 0.689

Podziały i szum są inne niż w labie, więc liczby też są trochę inne. Obraz jest ten sam: bez x² model ani razu nie wskazuje odmiany 2 (0,601, tyle co „zawsze inna”), z x² ma 0,755 i wygrywa w 49 z 50 części walidacyjnych. Szum obniża kNN z 0,962 do 0,689.

Dla praktyka
  • W scikit-learn: PolynomialFeatures(2) dodaje kwadraty i iloczyny par cech, SplineTransformer gładkie zakręty, FunctionTransformer(np.log1p) logarytm dla cech z długim ogonem. Wkładaj je do make_pipeline, żeby walidacja krzyżowa widziała całą drogę.
  • Najlepsze cechy biorą się z wiedzy o problemie: iloraz (cena za metr), różnica (dni od ostatniego zakupu), część daty (dzień tygodnia). Model sam ich nie wymyśli, jeśli nie dostanie surowych składników w dobrej postaci.
  • Gdy cech jest dużo, wybieraj je w każdym podziale osobno (SelectKBest w pipeline'ie) albo użyj modelu z regularyzacją (lekcja 3.4). Wybór cech na całych danych przed walidacją to wyciek (lekcja 4.5).
  • Metody jądrowe, które poznasz przy maszynach wektorów nośnych, liczą wynik tak, jakby dodały takie kolumny, ale bez tworzenia ich wprost.

Więcej w Atlasie

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