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.
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ł.
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ź: 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.
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.
Pobierz notebook (.ipynb). Otwórz go w Jupyterze albo wgraj do Google Colab; brakujące dane pobierze sam.
Dla praktyka
- W scikit-learn:
PolynomialFeatures(2)dodaje kwadraty i iloczyny par cech,SplineTransformergładkie zakręty,FunctionTransformer(np.log1p)logarytm dla cech z długim ogonem. Wkładaj je domake_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 (
SelectKBestw 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.
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: