Hoe KNN werkt: afstand, buren en stemmen
U visualiseert een 2D-dataset, berekent Euclidische afstanden, identificeert de k dichtstbijzijnde buren en voert een classificatie uit op basis van meerderheid van stemmen.
Hoe KNN werkt: afstand, buren en stemmen is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 1 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Machine Learning Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Machine Learning Academy bevat in totaal 4 lessen.
De basisintuïtie achter KNN
K-Nearest Neighbors (KNN) is een van de meest intuïtieve algoritmen voor machine learning: voorspel het label van een nieuw punt door naar de k dichtstbijzijnde gelabelde punten te kijken en een meerderheidstemming uit te voeren. Er is geen expliciete trainingsfase — het algoritme onthoudt eenvoudigweg de trainingsgegevens en voert alle berekeningen uit tijdens het voorspellen. Daarom is dit een luie leerling. Het werkt goed wanneer vergelijkbare invoer vergelijkbare uitvoer heeft, wat een redelijke aanname is in veel praktijkproblemen, zoals het aanbevelen van producten of het diagnosticeren van ziekten.
# Conceptual pseudocode
def knn_predict(X_train, y_train, x_new, k=3):
# 1. Compute distance from x_new to every training point
distances = [euclidean(x_new, x_i) for x_i in X_train]
# 2. Find indices of k smallest distances
nearest = sorted(range(len(distances)), key=lambda i: distances[i])[:k]
# 3. Majority vote among k neighbors
votes = [y_train[i] for i in nearest]
return max(set(votes), key=votes.count)Euclidische afstand: de standaardmaat
De meest gebruikte afstandsmaat in KNN is de Euclidische afstand, oftewel de rechte-lijnafstand tussen twee punten in de feature-ruimte. Voor twee punten A=(a1, a2) en B=(b1, b2) is de Euclidische afstand sqrt((a1-b1)^2 + (a2-b2)^2). In hogere dimensies wordt dezelfde formule uitgebreid over alle features. Omdat de Euclidische afstand alle dimensies gelijk behandelt, moeten features op dezelfde schaal staan — anders hebben features met grote waarden een overheersende invloed op de afstandsberekening en presteert KNN slecht.
import numpy as np
def euclidean_distance(a, b):
return np.sqrt(np.sum((a - b) ** 2))
point_a = np.array([1.0, 2.0])
point_b = np.array([4.0, 6.0])
dist = euclidean_distance(point_a, point_b)
print('Euclidean distance:', dist) # 5.0
# Verify with numpy
print('Using numpy:', np.linalg.norm(point_a - point_b))De k dichtstbijzijnde buren vinden
Voor een opgevraagd punt berekent KNN de afstanden tot alle N trainingspunten, sorteert deze en selecteert de k dichtstbijzijnde punten. Bij een kleine 2D-dataset kun je dit visualiseren door een cirkel rond het nieuwe punt te tekenen die groter wordt totdat deze precies k trainingsvoorbeelden bevat — dat zijn de buren. De rekenkosten zijn O(N * d) per voorspelling, waarbij N het aantal trainingspunten is en d het aantal features. Dit is prima voor kleine datasets, maar wordt onwerkbaar traag bij grote datasets.
import numpy as np
# Training data
X_train = np.array([[1,2],[2,3],[3,1],[6,5],[7,7],[8,6]])
y_train = np.array([0, 0, 0, 1, 1, 1]) # 0=class A, 1=class B
# Query point
x_new = np.array([4, 4])
# Distances to all training points
dists = np.linalg.norm(X_train - x_new, axis=1)
print('Distances:', dists.round(2))
# Indices of 3 nearest
k = 3
nearest_idx = np.argsort(dists)[:k]
print('3 nearest labels:', y_train[nearest_idx])Classificeren met een meerderheidstemming
Na het vinden van de k dichtstbijzijnde buren wijst KNN voor classificatie de klasse toe met de meeste stemmen onder de buren. Als bij k=3 twee buren klasse A hebben en één buur klasse B, is de voorspelling klasse A. Gelijkstanden worden door de implementatie opgelost (meestal door de klasse van de afzonderlijke dichtstbijzijnde buur te kiezen). Bij regressie berekent KNN het gemiddelde van de doelwaarden van de k buren in plaats van te stemmen. Een keuze voor k=1 is het flexibelst, maar ook erg gevoelig voor ruis; een grotere k geeft gladdere resultaten, maar kan leiden tot onderaanpassing.
from collections import Counter
import numpy as np
neighbor_labels = np.array([0, 0, 1]) # 2 votes for class 0, 1 for class 1
# Majority vote
vote_counts = Counter(neighbor_labels)
prediction = vote_counts.most_common(1)[0][0]
print('Predicted class:', prediction) # 0
# For regression: average instead of vote
neighbor_values = np.array([15.2, 18.7, 14.1])
prediction_reg = np.mean(neighbor_values)
print('Regression prediction:', prediction_reg.round(2))KNN met scikit-learn: KNeighborsClassifier
Scikit-learn implementeert KNN met KNeighborsClassifier en KNeighborsRegressor. Deze klassen volgen de standaard-API voor fitten en voorspellen. Belangrijke parameters zijn n_neighbors (de waarde van k), metric (de afstandsfunctie) en weights (uniforme of afstandsgewogen stemming). Afstandsgewogen stemming (weights='distance') geeft dichtstbijzijnde buren meer invloed. Dit verbetert de prestaties vaak doordat de invloed van de verste (minst vergelijkbare) buren binnen de gekozen k wordt beperkt.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
knn = KNeighborsClassifier(n_neighbors=5, weights='uniform')
knn.fit(X_train_s, y_train)
print('Test accuracy:', knn.score(X_test_s, y_test).round(3))De beslissingsgrens visualiseren
De beslissingsgrens van KNN is van nature niet-lineair en lokaal. Bij k=1 volgt de grens de trainingsgegevens exact (waardoor gekartelde, op Voronoi-regio's lijkende gebieden ontstaan), terwijl een grotere k gladdere grenzen oplevert. Je kunt dit visualiseren op een 2D-dataset door voorspellingen te doen over een fijnmazig raster en elk gebied in te kleuren volgens de voorspelde klasse. Een lage k past zich te veel aan de ruis in de trainingsgegevens aan (elk punt vormt zijn eigen klasse-eiland); een hoge k maakt te veel glad, waardoor afzonderlijke clusters mogelijk worden samengevoegd. De ideale k brengt deze afweging tussen bias en variantie in balans.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
# Create 2D mesh for decision boundary
def plot_decision_boundary(clf, X, y):
h = 0.02
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(
np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h)
)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:, 0], X[:, 1], c=y)Waarom het schalen van features cruciaal is voor KNN
KNN berekent afstanden in de feature-ruimte, dus de schaal van elke feature heeft rechtstreeks invloed op welke punten als dichtstbijzijnde worden beschouwd. Als één feature waarden in de duizenden heeft (bijvoorbeeld inkomen) en een andere uit één cijfer bestaat (bijvoorbeeld het aantal kinderen), zal de feature met de grote waarden alle afstandsberekeningen overheersen. Een buur die 1 verschilt in inkomen maar voor alle andere features identiek is, kan daardoor als verder weg worden beschouwd dan een punt dat op alle andere features sterk verschilt. Pas altijd StandardScaler of MinMaxScaler toe vóór KNN.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
# Without scaling
knn_raw = KNeighborsClassifier(n_neighbors=5)
raw_score = cross_val_score(knn_raw, X, y, cv=5).mean()
# With scaling inside pipeline
pipe = Pipeline([('sc', StandardScaler()), ('knn', KNeighborsClassifier(n_neighbors=5))])
scaled_score = cross_val_score(pipe, X, y, cv=5).mean()
print(f'Without scaling: {raw_score:.3f}')
print(f'With scaling: {scaled_score:.3f}')Afstanden en indexen van buren ophalen
Soms heb je meer nodig dan alleen de voorspelde klasse — je wilt weten welke trainingsvoorbeelden de buren waren en hoe ver ze weg waren. De methode kneighbors() van KNN retourneert zowel de afstanden als de indexen van de dichtstbijzijnde trainingsvoorbeelden. Dit is nuttig voor detectie van afwijkingen (een grote gemiddelde afstand tot buren wijst op een uitschieter), aanbevelingssystemen en het uitleggen van voorspellingen aan eindgebruikers door de meest vergelijkbare bekende voorbeelden te tonen.
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
X_train = np.array([[1,2],[2,3],[5,5],[8,7]])
y_train = np.array([0, 0, 1, 1])
knn = KNeighborsClassifier(n_neighbors=2)
knn.fit(X_train, y_train)
x_query = np.array([[4, 4]])
distances, indices = knn.kneighbors(x_query)
print('Neighbor indices:', indices)
print('Distances to neighbors:', distances.round(2))
print('Neighbor labels:', y_train[indices[0]])Afstandsgewogen stemmen
Bij een uniforme stemming tellen alle k buren even zwaar mee, ongeacht hoe dichtbij ze zijn. Afstandsgewogen stemming (weights='distance') geeft elke buur een gewicht dat evenredig is aan het omgekeerde van de afstand — zeer nabije buren hebben veel meer invloed dan verre buren. Dit is vooral nuttig bij beslissingsgrenzen, waar de dichtstbijzijnde en de verste buur zich mogelijk aan verschillende kanten van de werkelijke grens bevinden. Afstandsgewogen KNN presteert bijna altijd beter dan uniforme KNN, vooral wanneer k groot is.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_digits
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
X, y = load_digits(return_X_y=True)
uniform_pipe = Pipeline([('sc', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=7, weights='uniform'))])
distance_pipe = Pipeline([('sc', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=7, weights='distance'))])
print('Uniform: ', cross_val_score(uniform_pipe, X, y, cv=5).mean().round(3))
print('Distance: ', cross_val_score(distance_pipe, X, y, cv=5).mean().round(3))Klassekansen voorspellen
In plaats van een vast klasselabel kan KNN klassekansen retourneren met predict_proba(). Als bij k=5 drie buren klasse 1 hebben en twee klasse 0, is de voorspelde kans [0.4, 0.6]. Deze kansen kunnen worden voorzien van een drempel voor controle over precisie en terugvindpercentage, worden gebruikt in ensemblemodellen of worden gekalibreerd met CalibratedClassifierCV als de ruwe fracties geen werkelijke kansen vertegenwoordigen. Bij afstandsgewogen KNN zijn de kansen gewogen sommen in plaats van eenvoudige fracties.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
import numpy as np
X_train = np.array([[1,1],[1,2],[5,5],[6,5],[5,6]])
y_train = np.array([0, 0, 1, 1, 1])
scaler = StandardScaler()
X_s = scaler.fit_transform(X_train)
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_s, y_train)
x_new = scaler.transform([[3, 3]])
proba = knn.predict_proba(x_new)
print('Class probabilities:', proba)
print('Predicted class:', knn.predict(x_new))Sterke en zwakke punten van KNN
KNN heeft verschillende sterke punten: het is eenvoudig te begrijpen, vereist geen trainingstijd, verwerkt van nature problemen met meerdere klassen en kan complexe niet-lineaire grenzen modelleren. De zwakke punten zijn aanzienlijk voor grote gegevensverzamelingen: voorspellen is traag met O(N * d) per query, alle trainingsgegevens moeten in het geheugen staan en de prestaties nemen af in hoge dimensies (de vloek van dimensionaliteit). KNN is een sterke basislijn voor kleine tot middelgrote gegevensverzamelingen met goed geschaalde kenmerken, maar wordt in productieomgevingen op grote schaal meestal vervangen door snellere modellen.
# Summary of KNN trade-offs
strengths = [
'No training time -- all computation at prediction',
'No assumptions about data distribution',
'Naturally handles multi-class classification',
'Non-linear decision boundary',
]
weaknesses = [
'Slow prediction: O(N*d) per query',
'High memory: stores all training data',
'Sensitive to irrelevant and scaled features',
'Poor in very high dimensions (curse of dimensionality)',
]
for s in strengths: print('+', s)
for w in weaknesses: print('-', w)Korte controle
Toets je begrip van de concepten voor Machine Learning met Python uit deze les.
Samenvatting van de les
In deze les heb je geleerd: hoe KNN classificeert op basis van de meerderheid onder de k dichtstbijzijnde buren met behulp van de Euclidische afstand, waarom het schalen van kenmerken cruciaal is voordat je KNN toepast, en hoe stemmen met afstandsweging en predict_proba werken voor genuanceerdere voorspellingen. Hierna bekijken we hoe je de beste k kiest met de elleboogmethode en validatiecurven.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “Hoe KNN werkt: afstand, buren en stemmen” gratis?
Ja — de volledige tekst van “Hoe KNN werkt: afstand, buren en stemmen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Machine Learning Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Machine Learning Academy bevat in totaal 4 lessen.
Wat leer ik in “Hoe KNN werkt: afstand, buren en stemmen”?
U visualiseert een 2D-dataset, berekent Euclidische afstanden, identificeert de k dichtstbijzijnde buren en voert een classificatie uit op basis van meerderheid van stemmen. Je oefent met Machine Learning Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Machine Learning Academy te beginnen?
Ervaring vooraf is niet nodig. Machine Learning Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.
Hoe lang duurt de les “Hoe KNN werkt: afstand, buren en stemmen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Machine Learning Academy?
Ja. Elke les over Machine Learning Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Hoe KNN werkt: afstand, buren en stemmen
- k kiezen: de elleboogmethode en validatiecurves
- Afstandsmetrics: Euclidisch, Manhattan en Minkowski
- KNN voor regressie en schaalbaarheidsbeperkingen