Învățare supervizată

2.4 Algoritmul K-Nearest Neighbors (K-NN)

Cel mai intuitiv algoritm de clasificare: „spune-mi cu cine te asemeni, ca să-ți spun cine ești". Un exemplu nou primește clasa majoritară a celor mai apropiați k vecini.

Teorie

Principiul celor mai apropiați vecini

K-NN nu „învață" nimic la antrenare — memorează pur și simplu datele. La predicție: calculează distanța de la exemplul nou la toate exemplele din train, ia cele mai apropiate k, și votează: clasa majoritară câștigă (la regresie: media valorilor vecinilor).

Alegerea parametrului k

k mic (1–3)k mare (31+)
granițe de decizie foarte fine; sensibil la zgomot → risc de overfitting granițe foarte netede; ignoră structura locală → risc de underfitting

Practic: se încearcă mai multe valori impare (evită egalitatea la vot) și se alege cea cu cel mai bun scor pe validare sau prin cross-validation.

Alegerea metricii de distanță

Euclidiană (implicit): √(Σ(aᵢ−bᵢ)²) — linia dreaptă dintre puncte.

Manhattan: Σ|aᵢ−bᵢ| — distanța „pe străzi", mai robustă la outlieri.

Minkowski: generalizarea ambelor (parametrul p: p=2 euclidiană, p=1 Manhattan).

Distanțele amestecă scările coloanelor: o coloană în mii domină una în zecimi. Standardizarea este obligatorie înainte de K-NN.

Utilizarea scikit-learn

from sklearn.neighbors import KNeighborsClassifier, KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score

sc = StandardScaler()
X_tr = sc.fit_transform(X_train)

for k in [1, 3, 5, 7, 11, 21]:
    model = KNeighborsClassifier(n_neighbors=k, metric="euclidean")
    scoruri = cross_val_score(model, X_tr, y_train, cv=5)
    print(f"k={k}: {scoruri.mean():.3f}")

# weights="distance": vecinii mai apropiați au vot mai greu
model = KNeighborsClassifier(n_neighbors=5, weights="distance")

Problemă rezolvată: Iris cu K-NN

Clasificarea speciilor Iris — varianta K-NN Ușor Rezolvată

Aceeași problemă din lecția 1.4, acum cu K-NN și alegerea sistematică a lui k — ca să compari direct cele două modele.

Soluția pas cu pas
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score

train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
feats = ["sepal_length", "sepal_width", "petal_length", "petal_width"]

sc = StandardScaler()
X = sc.fit_transform(train[feats])
y = train["species"]

# alegem k prin cross-validation
best_k, best_s = None, 0
for k in range(1, 22, 2):
    s = cross_val_score(KNeighborsClassifier(n_neighbors=k), X, y, cv=5).mean()
    if s > best_s:
        best_k, best_s = k, s
print("Cel mai bun k:", best_k, "scor:", round(best_s, 3))

model = KNeighborsClassifier(n_neighbors=best_k).fit(X, y)
pred = model.predict(sc.transform(test[feats]))
pd.DataFrame({"SampleID": test["SampleID"], "species": pred}) \
  .to_csv("submission.csv", index=False)

Probleme propuse

1. K-NN pe hârtie Exercițiu

Ai punctele A(1,1)→roșu, B(2,2)→roșu, C(5,5)→albastru, D(6,5)→albastru. Ce clasă primește punctul (4,4) cu k=1 și cu k=3, folosind distanța euclidiană? Calculează manual.

2. Curba k → acuratețe Exercițiu

Pe orice dataset de clasificare, desenează acuratețea pe train și pe validare pentru k de la 1 la 50. Identifică zonele de overfitting și underfitting pe grafic.

3. Metrici de distanță Exercițiu

Compară euclidiană vs Manhattan pe un dataset cu outlieri adăugați artificial. Care rezistă mai bine și de ce?

4. Clasificarea vinului cu K-NN Platformă

Rezolvă problema vinului cu K-NN + scalare + alegerea lui k și compară cu soluția de referință.