k kiezen: de elleboogmethode en validatiecurves
U doorloopt k van 1 tot en met 30, tekent de validatienauwkeurigheid en identificeert de optimale waarde die bias en variantie in balans brengt.
k kiezen: de elleboogmethode en validatiecurves is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 2 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.
Waarom de keuze van k belangrijk is
De waarde van k is de belangrijkste hyperparameter in KNN. Een te kleine k (bijvoorbeeld k=1) maakt het model zeer gevoelig voor ruis: elk trainingspunt vormt zijn eigen voorspellingsgebied, waardoor het model ruis onthoudt in plaats van patronen te leren. Een te grote k maakt de beslissingsgrens te glad en kan werkelijk verschillende klassen samenvoegen. De juiste k vinden is een bias-variantieprobleem: kleine k = lage bias, hoge variantie; grote k = hoge bias, lage variantie. De elleboogmethode en validatiecurven helpen empirisch de optimale k te bepalen.
# k=1: memorises training set perfectly
# Training accuracy = 100%, test accuracy low (overfitting)
# k=N (all neighbors): always predicts majority class
# Training accuracy = majority fraction (underfitting)
# Optimal k: somewhere in between
# Maximises test/validation accuracy
from sklearn.neighbors import KNeighborsClassifier
print('k=1 overfits (memorises noise)')
print('k=N underfits (ignores all variation)')
print('Best k: maximises cross-validated accuracy')k-waarden doorlopen: de basislus
De eenvoudigste aanpak is om KNN te trainen voor een reeks k-waarden, elke waarde op een validatieset te beoordelen en de k met de hoogste validatienauwkeurigheid te kiezen. Scikit-learn maakt dit eenvoudig: doorloop k van 1 tot een bepaalde maximumwaarde en pas elk model toe en beoordeel het. Beoordeel altijd op een apart gehouden validatieset of gebruik kruisvalidatie — beoordeling op de trainingsset zou altijd k=1 selecteren, omdat KNN met k=1 trainingspunten met 100% nauwkeurigheid voorspelt door ze uit het hoofd te leren.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_tr = scaler.fit_transform(X_train)
X_v = scaler.transform(X_val)
val_scores = []
for k in range(1, 31):
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_tr, y_train)
val_scores.append(knn.score(X_v, y_val))
best_k = val_scores.index(max(val_scores)) + 1
print('Best k:', best_k, 'with accuracy:', max(val_scores).round(3))De validatiecurve tekenen
Het visualiseren van de validatienauwkeurigheid tegenover k laat twee belangrijke patronen zien. Bij een lage k is de curve grillig met een hoge variantie (het model reageert op afzonderlijke trainingspunten). Naarmate k toeneemt, verbetert de nauwkeurigheid meestal tot een piek, waarna deze langzaam afneemt doordat het model te glad wordt. De optimale k ligt op de piek van de validatiecurve. Deze vorm is niet altijd duidelijk bij één enkele validatiesplitsing. Daarom geeft kruisvalidatie een betrouwbaardere schatting door het gemiddelde te nemen over meerdere splitsingen.
import matplotlib.pyplot as plt
import numpy as np
k_values = range(1, 31)
# val_scores computed from previous sweep
plt.figure(figsize=(10, 5))
plt.plot(k_values, val_scores, marker='o', label='Validation accuracy')
plt.axvline(x=best_k, color='r', linestyle='--', label=f'Best k={best_k}')
plt.xlabel('k (Number of Neighbors)')
plt.ylabel('Validation Accuracy')
plt.title('KNN Validation Curve')
plt.legend()
plt.grid(True)
plt.show()Kruisgevalideerde nauwkeurigheid per k
Een enkele validatiesplitsing kan worden vertekend door de specifieke voorbeelden die toevallig in de validatieset terechtkwamen. Kruisvalidatie neemt het gemiddelde over k splitsingen, wat een stabielere schatting oplevert. De cross_val_score van Scikit-learn kan voor elke k-waarde worden aangeroepen. De gemiddelde nauwkeurigheid laat de trend zien en de standaardafwijking over de vouwen geeft de betrouwbaarheid aan. Kies de k met de hoogste gemiddelde kruisgevalideerde nauwkeurigheid; als meerdere k-waarden dicht bij elkaar liggen, geef dan de voorkeur aan de grotere waarde voor soepelere, beter generaliseerbare voorspellingen.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
import numpy as np
X, y = load_iris(return_X_y=True)
cv_means, cv_stds = [], []
for k in range(1, 31):
pipe = Pipeline([('sc', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=k))])
scores = cross_val_score(pipe, X, y, cv=10)
cv_means.append(scores.mean())
cv_stds.append(scores.std())
best_k_cv = np.argmax(cv_means) + 1
print('Best k by CV:', best_k_cv, 'mean accuracy:', max(cv_means).round(3))Het concept van de elleboogmethode
De elleboogmethode is een visuele techniek om het optimale punt te vinden waarop de verbetering van de nauwkeurigheid marginaal wordt. Zet de validatienauwkeurigheid (of fout) uit tegen k; de curve vertoont meestal een sterke verbetering bij kleine k en vlakt daarna af. De elleboog — het punt waarop de curve van steil naar vlak buigt — is vaak de optimale k. De intuïtie hierachter is afnemende meeropbrengst: meer buren toevoegen voorbij dit punt verbetert de nauwkeurigheid niet betekenisvol, maar verhoogt de bias wel. De elleboog is niet altijd duidelijk. Daarom hebben kwantitatieve methoden zoals CV de voorkeur voor de uiteindelijke keuze.
import matplotlib.pyplot as plt
import numpy as np
k_range = range(1, 31)
error_rates = [1 - acc for acc in cv_means] # Convert accuracy to error
plt.figure(figsize=(10, 5))
plt.plot(list(k_range), error_rates, marker='o')
plt.xlabel('k')
plt.ylabel('Cross-Validated Error Rate')
plt.title('Elbow Method for Optimal k')
plt.grid(True)
# Mark the elbow visually
plt.axvline(x=best_k_cv, color='r', linestyle='--', label=f'Elbow at k={best_k_cv}')
plt.legend()
plt.show()validation_curve van scikit-learn gebruiken
Scikit-learn biedt validation_curve() als hulpfunctie die een bereik van hyperparameterwaarden doorloopt en voor elke waarde trainings- en validatiescores teruggeeft. Dit is overzichtelijker dan een handmatige lus, omdat de functie kruisvalidatie intern afhandelt. Het argument param_name gebruikt de notatie met dubbele underscores voor pijplijnparameters (bijvoorbeeld knn__n_neighbors). Door de trainings- en validatiecurven samen te tekenen, zie je of de lage prestaties worden veroorzaakt door onderfitting (beide laag), overfitting (training hoog, validatie laag) of goede generalisatie (beide hoog).
from sklearn.model_selection import validation_curve
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
pipe = Pipeline([('sc', StandardScaler()), ('knn', KNeighborsClassifier())])
train_scores, val_scores = validation_curve(
pipe, X, y,
param_name='knn__n_neighbors',
param_range=range(1, 31),
cv=10, scoring='accuracy'
)
train_mean = np.mean(train_scores, axis=1)
val_mean = np.mean(val_scores, axis=1)
print('Best k:', np.argmax(val_mean) + 1)De bias-variantieafweging in KNN
De validatiecurve illustreert de bias-variantieafweging rechtstreeks. Bij een kleine k nadert de trainingsnauwkeurigheid 100% (lage bias, het model past perfect op de trainingsgegevens), terwijl de validatienauwkeurigheid lager is (hoge variantie, het model is te gevoelig voor afzonderlijke punten). Bij een grote k daalt de trainingsnauwkeurigheid (het model underfit) en daalt ook de validatienauwkeurigheid (hoge bias). De optimale k ligt op het snijpunt waar het verschil tussen trainings- en validatienauwkeurigheid klein is en beide maximaal zijn — dit is het optimale punt voor generalisatie.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(10, 5))
k_range = list(range(1, 31))
ax.plot(k_range, train_mean, label='Training accuracy', color='blue')
ax.plot(k_range, val_mean, label='Validation accuracy', color='orange')
ax.fill_between(k_range,
np.mean(train_scores, axis=1) - np.std(train_scores, axis=1),
np.mean(train_scores, axis=1) + np.std(train_scores, axis=1),
alpha=0.1, color='blue')
ax.set_xlabel('k')
ax.set_ylabel('Accuracy')
ax.set_title('Bias-Variance Trade-off: KNN Validation Curve')
ax.legend()
plt.show()k kiezen op basis van oneven of even waarden
Geef bij binaire classificatie altijd de voorkeur aan oneven waarden van k om gelijke standen te voorkomen. Met k=4 en twee klassen kunnen beide klassen 2 stemmen krijgen — de regel voor het doorbreken van een gelijke stand bepaalt dan het resultaat, wat willekeurig kan zijn. Met k=3 of k=5 zijn gelijke standen bij twee klassen onmogelijk. Bij problemen met meerdere klassen met C klassen mag k om dezelfde reden geen veelvoud van C zijn. Dit is een klein maar praktisch belangrijk detail wanneer k-waarden in de buurt van het optimum vergelijkbare prestaties hebben.
# Best practice for binary classification: pick odd k
# For multi-class (C classes): avoid multiples of C
def recommend_k(k_optimal, n_classes):
if n_classes == 2:
# Make odd
return k_optimal if k_optimal % 2 == 1 else k_optimal + 1
else:
# Avoid multiples of n_classes
while k_optimal % n_classes == 0:
k_optimal += 1
return k_optimal
print('Binary, k=4 -> recommended:', recommend_k(4, 2)) # 5
print('3-class, k=6 -> recommended:', recommend_k(6, 3)) # 7GridSearchCV voor het kiezen van k
GridSearchCV automatiseert de keuze van k door elke kandidaatwaarde via kruisvalidatie te beoordelen en de beste waarde terug te geven. Combineer dit met een pijplijn voor schaling en geef param_grid door met de sleutel met dubbele underscore. GridSearchCV traint het beste model ook opnieuw op de volledige trainingsset, zodat grid.best_estimator_ direct na het trainen klaar is voor gebruik in productie. Dit is de aanbevolen aanpak wanneer de keuze van k deel uitmaakt van een grotere optimalisatie van hyperparameters.
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
pipe = Pipeline([
('sc', StandardScaler()),
('knn', KNeighborsClassifier())
])
param_grid = {
'knn__n_neighbors': list(range(1, 31, 2)), # odd values 1-29
'knn__weights': ['uniform', 'distance']
}
grid = GridSearchCV(pipe, param_grid, cv=10, scoring='accuracy', n_jobs=-1)
grid.fit(X_train, y_train)
print('Best k:', grid.best_params_['knn__n_neighbors'])
print('Best weights:', grid.best_params_['knn__weights'])
print('Best CV accuracy:', grid.best_score_.round(3))Resultaten interpreteren en de uiteindelijke k kiezen
Wanneer meerdere k-waarden vergelijkbare validatiescores opleveren, geef dan de voorkeur aan de grotere k voor soepelere, robuustere voorspellingen die minder gevoelig zijn voor afzonderlijke ruispunten. Bekijk de standaardafwijking van de kruisvalidatiescores: als een kleinere k een hoger gemiddelde maar ook een hogere standaardafwijking heeft, kan de grotere k in productie daadwerkelijk betrouwbaarder zijn. Het uiteindelijke model moet opnieuw worden getraind op de volledige trainingsset (niet alleen op de trainingsvouwen van de kruisvalidatie) met de geselecteerde k en één keer worden beoordeeld op de apart gehouden testset.
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# Select best k from validation
best_k = 11 # determined from CV
# Retrain on full training data
final_model = Pipeline([
('sc', StandardScaler()),
('knn', KNeighborsClassifier(n_neighbors=best_k, weights='distance'))
])
final_model.fit(X_train, y_train)
# Evaluate once on held-out test set
test_accuracy = final_model.score(X_test, y_test)
print(f'Final test accuracy with k={best_k}: {test_accuracy:.3f}')Veelvoorkomende valkuilen bij het kiezen van k
Drie veelvoorkomende fouten die je moet vermijden: (1) Beoordelen op trainingsgegevens — k=1 behaalt altijd 100%, waardoor deze waarde optimaal lijkt; gebruik altijd apart gehouden of kruisgevalideerde gegevens. (2) Kenmerken niet schalen voordat je k kiest — de optimale k hangt af van de geometrie van de afstanden, die door schaling verandert; neem de schaler altijd op in de pijplijn voordat je naar hyperparameters zoekt. (3) k onafhankelijk van de omvang van de gegevensverzameling kiezen — een vuistregel is om te beginnen met een k rond sqrt(N), waarbij N de omvang van de trainingsset is, en deze daarna met CV te verfijnen.
import numpy as np
N_train = 1000 # training samples
# Rule of thumb starting point
k_start = int(np.sqrt(N_train))
print(f'sqrt(N) starting point: k = {k_start}')
# Then sweep around this value
k_candidates = list(range(max(1, k_start - 10), k_start + 11, 2))
print('Candidates to sweep:', k_candidates)
# AVOID:
# knn.score(X_train, y_train) -- always pick k=1
# Not including scaler in pipeline before CVKorte 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 een kleine k overfitting veroorzaakt en een grote k underfitting, hoe je kruisvalidatie en validation_curve gebruikt om k-waarden te doorlopen en de optimale waarde te vinden, en waarom oneven k-waarden gelijke standen voorkomen bij binaire classificatie. Hierna bekijken we verschillende afstandsmaten — Euclidisch, Manhattan en Minkowski — en hoe je ertussen kiest.
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 “k kiezen: de elleboogmethode en validatiecurves” gratis?
Ja — de volledige tekst van “k kiezen: de elleboogmethode en validatiecurves” 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 “k kiezen: de elleboogmethode en validatiecurves”?
U doorloopt k van 1 tot en met 30, tekent de validatienauwkeurigheid en identificeert de optimale waarde die bias en variantie in balans brengt. 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 2 van 4.
Hoe lang duurt de les “k kiezen: de elleboogmethode en validatiecurves”?
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