ML Atlas

03 · Nadzorowane · 4 min czytania · Interaktywne · aktualizacja

Jak działa algorytm k najbliższych sąsiadów i jak dobrać k?

W skrócie

Metoda kNN klasyfikuje nowy punkt głosem k najbliższych przykładów treningowych. Jest prosta i elastyczna, ale wrażliwa na skalę cech i ich liczbę.

Co to jest

Metoda k najbliższych sąsiadów (k-nearest neighbors, kNN) to algorytm, który dla nowego przypadku znajduje k najbardziej podobnych przykładów w zbiorze treningowym i przypisuje mu klasę, która przeważa wśród tych sąsiadów. W regresji zamiast głosowania bierze średnią ich wartości. Podobieństwo mierzy się zwykle odległością euklidesową w przestrzeni cech.

To model „leniwy”: podczas treningu nie robi nic poza zapamiętaniem danych, cała praca dzieje się przy przewidywaniu. Nie ma wag do nauczenia ani wzoru do odczytania — model to po prostu zbiór treningowy plus reguła głosowania.

Intuicja jest codzienna: chcąc ocenić cenę mieszkania, patrzysz na kilka najbardziej podobnych ofert w okolicy. Analiza teoretyczna metody zaczęła się od pracy Fixa i Hodgesa (1951), a znany wynik Covera i Harta (1967) mówi, że przy nieskończenie wielu danych błąd reguły jednego sąsiada jest co najwyżej dwa razy większy od najmniejszego możliwego błędu.

Mechanizm — dlaczego tak działa

kNN opiera się na jednym założeniu: punkty bliskie w przestrzeni cech mają podobne odpowiedzi. Jeśli to prawda, lokalna większość jest dobrym przybliżeniem prawdopodobieństwa klasy w danym miejscu. Model nie zakłada żadnego kształtu granicy, więc może dopasować się do dowolnie skomplikowanego podziału — pod warunkiem, że ma dość danych.

Parametr k steruje kompromisem obciążenie–wariancja. Przy k = 1 model zapamiętuje każdy punkt, także błędnie oznaczony; granica jest postrzępiona, a trafność na treningu zawsze wynosi 100% (punkt jest swoim własnym sąsiadem). Większe k uśrednia więcej punktów: granica się wygładza, wpływ szumu maleje. Przy k równym liczbie danych model zawsze przewiduje klasę większościową. Dobre k leży gdzieś pomiędzy i dobiera się je walidacją krzyżową; przy dwóch klasach wybiera się k nieparzyste, żeby uniknąć remisów.

Najważniejsza praktyczna pułapka to skala cech. Odległość euklidesowa sumuje kwadraty różnic, więc cecha o dużych liczbach — masa w gramach, dochód w złotych — zdominuje cechy mierzone w małych jednostkach. Bez standaryzacji kNN de facto używa tylko jednej cechy.

Druga pułapka to wymiar. W wielu wymiarach odległości między punktami stają się do siebie podobne: „najbliższy” sąsiad jest niewiele bliżej niż przeciętny. To przejaw przekleństwa wymiarowości. Do tego każda nieistotna cecha dodaje do odległości szum, który rozmywa sygnał z cech ważnych. kNN nie umie sam zignorować bezużytecznych cech — trzeba je usunąć wcześniej.

Trzeci koszt: przewidywanie wymaga porównania z całym zbiorem treningowym. Struktury danych (drzewa KD, drzewa kul) przyspieszają to w niskich wymiarach; przy milionach wektorów stosuje się przybliżone wyszukiwanie sąsiadów, to samo, które napędza dziś wyszukiwanie wektorowe.

Na przykładzie

Palmer Penguins: 342 pingwiny, cztery pomiary (długość i głębokość dzioba w mm, długość płetwy w mm, masa w g), trzy gatunki; trening na 256, test na 86 (podział warstwowy, random_state=0). Bez skalowania kNN z k = 5 trafia w 86,0% przypadków. Dlaczego tak słabo? Weźmy pingwina Adelie (39,1; 18,7; 181; 3750) i Chinstrap (46,5; 17,9; 192; 3500). Ich odległość to 250,4, z czego niemal wszystko (99,7% sumy kwadratów) pochodzi z różnicy masy 250 g — a różnica 7,4 mm długości dzioba, która akurat najlepiej odróżnia te gatunki, prawie się nie liczy.

Po standaryzacji cech (średnia 0, odchylenie 1) ten sam model ma 98,8%. Wpływ k: dla k = 1, 3 i 5 — 98,8%, dla k = 11 i 25 — 97,7%, dla k = 51 — 96,5%, dla k = 101 — 87,2%, bo „sąsiedztwo” obejmuje już połowę mniej licznego gatunku. Przekleństwo wymiarowości też widać: gdy do czterech pomiarów dopiszemy losowe cechy-szum, trafność w 5-krotnej walidacji krzyżowej spada z 98,2% do 91,8% (10 cech szumu), 79,8% (50) i 63,7% (200).

Ta ilustracja działa w przeglądarce z włączonym JavaScriptem: k najbliższych sąsiadów na irysach Fishera: suwak k zmienia granice gatunków oraz trafność na treningu i teście.

Dane: Palmer Penguins (pingwiny z Antarktydy)

W praktyce

  • KNeighborsClassifier(n_neighbors=5) i KNeighborsRegressor; zawsze w potoku: make_pipeline(StandardScaler(), KNeighborsClassifier()).
  • k dobieraj przez GridSearchCV po kneighborsclassifier__n_neighbors; typowo 3–30, przy małych zbiorach mniej.
  • weights="distance" daje bliższym sąsiadom większy głos — pomaga, gdy gęstość danych jest nierówna.
  • Inne metryki przez metric=: "manhattan" bywa odporniejsza, "cosine" sprawdza się dla tekstu i osadzeń.
  • Dla dużych zbiorów i wielu wymiarów użyj przybliżonych bibliotek sąsiedztwa (np. FAISS, Annoy) zamiast wyszukiwania dokładnego.

Najczęstsze pytania

Jak wybrać k?
Walidacją krzyżową: sprawdź kilka wartości i wybierz tę z najlepszym wynikiem walidacyjnym. Reguła kciuka k ≈ √n bywa punktem startowym, ale nie zastępuje walidacji. Przy remisie wyników wybierz większe k — da gładszą, stabilniejszą granicę.
Czy kNN nadaje się do dużych zbiorów danych?
Trening jest natychmiastowy, ale każde przewidywanie wymaga szukania sąsiadów, a cały zbiór musi być w pamięci. Przy milionach przykładów stosuje się przybliżone wyszukiwanie sąsiadów, które poświęca odrobinę dokładności dla ogromnego przyspieszenia.
Dlaczego kNN źle działa przy wielu cechach?
Bo w wysokich wymiarach wszystkie punkty są od siebie podobnie daleko, a nieistotne cechy dodają szum do każdej odległości. Model nie potrafi sam ich pominąć. Pomaga selekcja cech, redukcja wymiaru (np. PCA) albo nauczenie lepszej reprezentacji przed zastosowaniem kNN.

Źródła

  • Cover T., Hart P. „Nearest Neighbor Pattern Classification”, IEEE Transactions on Information Theory 13(1), 1967.
  • Hastie T., Tibshirani R., Friedman J. „The Elements of Statistical Learning”, 2nd ed., 2009, rozdz. 13.3.
  • James G., Witten D., Hastie T., Tibshirani R. „An Introduction to Statistical Learning”, 2nd ed., 2021, rozdz. 2.2.3 i 4.
  • Dokumentacja scikit-learn, „Nearest Neighbors”: https://scikit-learn.org/stable/modules/neighbors.html

Zobacz też