K-fold crossvalidatie: splitsen zonder datalekken
Cursisten implementeren 5-fold CV met cross_val_score, begrijpen waarom de testfold nooit tijdens het trainen wordt gebruikt en interpreteren het gemiddelde en de standaardafwijking van de CV-scores.
K-fold crossvalidatie: splitsen zonder datalekken 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.
Waarom één splitsing in training en toetsing riskant is
Wanneer je een model evalueert op één afzonderlijke toetsset, hangt het resultaat sterk af van welke voorbeelden toevallig in de toetsset terechtkwamen. Bij een kleine gegevensverzameling kunnen 80 toetsvoorbeelden ongewoon eenvoudig of moeilijk zijn, waardoor je schatting van de nauwkeurigheid misleidend wordt. K-voudige kruisvalidatie lost dit op door de nauwkeurigheid over meerdere toetsvouwen te middelen, wat een betrouwbaardere schatting geeft van hoe het model op nieuwe gegevens zal presteren. De gegevens worden ook efficiënter gebruikt: elk voorbeeld wordt in verschillende vouwen zowel voor training als voor toetsing gebruikt.
Hoe K-voudige CV stap voor stap werkt
K-voudige CV splitst de gegevensverzameling op in k delen van gelijke grootte, die vouwen worden genoemd. In elk van de k rondes wordt één vouw gebruikt als toetsvouw en vormen de resterende k-1 vouwen de trainingsset. Het model wordt vanaf nul getraind op de trainingsvouwen en geëvalueerd op de toetsvouw. Dit wordt herhaald totdat elke vouw precies één keer als toetsvouw heeft gediend. De uiteindelijke prestatieschatting is het gemiddelde (en de standaardafwijking) van de k scores. Gebruikelijke waarden zijn: k=5 of k=10.
cross_val_score: kruisvalidatie op één regel
De cross_val_score van scikit-learn verwerkt de volledige K-voudige lus: de functie maakt de vouwen, traint het model op elk trainingsgedeelte, evalueert het op de toetsvouw en retourneert een reeks scores. De parameter cv bepaalt het aantal vouwen. De parameter scoring specificeert de meetwaarde. Je kunt ook n_jobs=-1 meegeven om alle vouwen parallel te trainen, waardoor de verstreken tijd op machines met meerdere processorkernen aanzienlijk afneemt.
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy', n_jobs=-1)
print('Fold scores:', np.round(scores, 4))
print('Mean:', round(scores.mean(), 4), 'Std:', round(scores.std(), 4))De toetsvouw wordt nooit gezien tijdens de training
De kritieke regel van K-voudige CV is dat de toetsvouw nooit invloed mag hebben op het model of op een stap van de voorbewerking. Dit betekent dat de scaler alleen op de trainingsvouwen mag worden gefit en daarna op de toetsvouw moet worden toegepast — nooit op de gecombineerde gegevens mag worden gefit. Door een Pipeline met cross_val_score te gebruiken, wordt dit automatisch afgedwongen: scikit-learn roept binnen elke vouw fit aan op het trainingsgedeelte van de pipeline en predict op het toetsgedeelte, waardoor lekken wordt voorkomen.
# WRONG: fitting scaler on all data before CV causes leakage
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X) # leaks test fold statistics!
wrong_score = cross_val_score(LogisticRegression(max_iter=1000), X_scaled, y, cv=5).mean()
# CORRECT: Pipeline ensures scaler is fitted only on training folds
from sklearn.pipeline import make_pipeline
correct_score = cross_val_score(make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000)), X, y, cv=5).mean()
print('Wrong (leaky):', round(wrong_score, 4))
print('Correct (no leak):', round(correct_score, 4))De willekeurige seed instellen voor reproduceerbaarheid
Standaard husselt KFold de gegevens niet en maakt het voor dezelfde gegevensverzameling altijd dezelfde splitsingen, waardoor resultaten reproduceerbaar zijn. Als je shuffle=True instelt, geef dan een geheel getal als random_state mee zodat het husselen deterministisch is: KFold(n_splits=5, shuffle=True, random_state=42). Husselen wordt aanbevolen wanneer de gegevensverzameling op klasse of tijdvolgorde is gesorteerd, omdat opeenvolgende splitsingen zeer onrepresentatieve vouwen zouden opleveren. Documenteer de willekeurige toestand altijd in je experimenten voor reproduceerbaarheid.
from sklearn.model_selection import KFold, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import numpy as np
X, y = load_iris(return_X_y=True)
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(DecisionTreeClassifier(random_state=42), X, y, cv=kf)
print('Shuffled 5-fold scores:', np.round(scores, 4))
print('Mean:', round(scores.mean(), 4))Gemiddelde en standaardafwijking interpreteren
De gemiddelde CV-score schat de verwachte prestaties van je model op nieuwe gegevens. De standaardafwijking geeft aan hoe stabiel die prestaties zijn. Een gemiddelde van 0.93 met een standaardafwijking van 0.01 is veel betrouwbaarder dan 0.93 met een standaardafwijking van 0.08. Een hoge standaardafwijking geeft aan dat de modelprestaties gevoelig zijn voor welke voorbeelden in de trainingsset zitten — een teken van een kleine gegevensverzameling, een hoge modelvariantie of een niet-representatieve splitsing van de gegevens. Bij het vergelijken van twee modellen heeft het model met de lagere variantie (kleinere standaardafwijking) vaak de voorkeur, zelfs als het gemiddelde iets lager is.
K kiezen: 5-voudig versus 10-voudig versus LOOCV
De keuze van k brengt een afweging tussen bias en variantie met zich mee voor de CV-schatting zelf. k=5: elke trainingsset bevat 80% van de gegevens, snel te berekenen, iets meer bias. k=10: elke trainingsset bevat 90%, een betere schatting, meer rekenwerk. Leave-One-Out CV (LOOCV): k=n, bijna zonder bias maar uiterst traag voor grote gegevensverzamelingen en met een hoge variantie tussen vouwen. De standaardaanbeveling is k=5 of k=10. Voor zeer kleine gegevensverzamelingen (<100 voorbeelden) geeft LOOCV de meest gegevensefficiënte schatting.
from sklearn.model_selection import cross_val_score, LeaveOneOut
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
import numpy as np
X, y = load_iris(return_X_y=True)
knn = KNeighborsClassifier(n_neighbors=5)
for k in [5, 10]:
scores = cross_val_score(knn, X, y, cv=k)
print(f'{k}-fold CV: mean={scores.mean():.4f}, std={scores.std():.4f}')
# LOOCV is slow for large datasets; feasible here
loo_scores = cross_val_score(knn, X, y, cv=LeaveOneOut())
print(f'LOOCV: mean={loo_scores.mean():.4f}, std={loo_scores.std():.4f}')cross_validate: meerdere meetwaarden tegelijk
cross_validate is een krachtigere variant die meerdere meetwaarden tegelijk kan berekenen en ook trainingsscores en fit-/scoretijden kan retourneren. Dit is nuttig voor het vergelijken van trainings- en toetsscores (om overfitting vast te stellen) of voor het berekenen van meerdere meetwaarden (nauwkeurigheid, F1, AUC) in één CV-uitvoering, in plaats van CV afzonderlijk voor elke meetwaarde uit te voeren.
from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
rf = RandomForestClassifier(n_estimators=100, random_state=42)
results = cross_validate(rf, X, y, cv=5,
scoring=['accuracy', 'f1', 'roc_auc'],
return_train_score=True)
for metric in ['test_accuracy', 'test_f1', 'test_roc_auc']:
vals = results[metric]
print(f'{metric}: {vals.mean():.4f} (+/- {vals.std():.4f})')Wanneer K-voudige CV misleidend kan zijn
K-voudige CV geeft in verschillende situaties misleidende schattingen: (1) tijdreeksgegevens — husselen en splitsen negeert de temporele volgorde, waardoor lekken ontstaat waarbij toekomstige gegevens modellen trainen die worden gebruikt om het verleden te voorspellen; (2) gegroepeerde gegevens — als meerdere rijen bij dezelfde patiënt of gebruiker horen, lekken patronen op groepsniveau wanneer je ze over verschillende vouwen verdeelt; (3) sterk onevenwichtige klassen — bij willekeurige splitsingen kunnen alle positieve voorbeelden in de trainingsset terechtkomen. Gebruik gespecialiseerde CV-varianten: TimeSeriesSplit, GroupKFold en StratifiedKFold voor deze situaties.
Kruisvalidatie is evaluatie, geen training
Een veelvoorkomende misvatting: K-voudige CV levert geen inzetbaar model op. Elk van de k fits van het model wordt na de evaluatie verwijderd. Kruisvalidatie dient uitsluitend om te schatten hoe een model dat met je gekozen hyperparameters en pipeline is getraind, op ongeziene gegevens zal presteren. Zodra je tevreden bent met de CV-schatting, train je je uiteindelijke model opnieuw op de volledige trainingsgegevensverzameling (alle vouwen samengevoegd) met die hyperparameters en zet je dat model in. De CV-score is je eerlijke schatting van de verwachte prestaties ervan.
CV-resultaten rapporteren: gemiddelde en betrouwbaarheidsinterval
Rapporteer bij kruisvalidatieresultaten altijd zowel het gemiddelde als de standaardafwijking: 0.932 ± 0.012. Dit geeft niet alleen de prestaties weer, maar ook de stabiliteit. Voor publicaties of rapporten voor belanghebbenden kun je ook een betrouwbaarheidsinterval van 95% berekenen: mean ± 1.96 × std / sqrt(k). Controleer bij het vergelijken van twee modellen of hun betrouwbaarheidsintervallen overlappen — overlappende intervallen wijzen erop dat het verschil niet statistisch betekenisvol is en mogelijk alleen het gevolg is van willekeurige variatie in de splitsing van de gegevens.
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
scores = cross_val_score(RandomForestClassifier(n_estimators=100, random_state=42), X, y, cv=10)
mean, std = scores.mean(), scores.std()
ci95 = 1.96 * std / np.sqrt(len(scores))
print(f'CV Mean: {mean:.4f}')
print(f'CV Std: {std:.4f}')
print(f'95% CI: [{mean-ci95:.4f}, {mean+ci95:.4f}]')Snelle controle
Toets je begrip van K-voudige kruisvalidatie uit deze les.
Samenvatting van de les
In deze les heb je geleerd: K-voudige kruisvalidatie schat de generalisatie door scores over k niet-overlappende testvouwen te middelen, gebruik altijd een Pipeline om te voorkomen dat statistieken uit de testvouw via voorbewerking naar de training lekken en kruisvalidatie is een evaluatiehulpmiddel — train na het selecteren van hyperparameters opnieuw met alle gegevens. Hierna bekijken we gestratificeerde kruisvalidatie en kruisvalidatie voor tijdreeksen voor gespecialiseerde gegevenstypen.
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-fold crossvalidatie: splitsen zonder datalekken” gratis?
Ja — de volledige tekst van “K-fold crossvalidatie: splitsen zonder datalekken” 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-fold crossvalidatie: splitsen zonder datalekken”?
Cursisten implementeren 5-fold CV met cross_val_score, begrijpen waarom de testfold nooit tijdens het trainen wordt gebruikt en interpreteren het gemiddelde en de standaardafwijking van de CV-scores. 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 “K-fold crossvalidatie: splitsen zonder datalekken”?
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
- K-fold crossvalidatie: splitsen zonder datalekken
- Gestratificeerde crossvalidatie en crossvalidatie voor tijdreeksen
- Grid search versus random search
- Geneste crossvalidatie: selecteren en evalueren tegelijk