Machine Learning Academy · Les

Waarom u niet op trainingsgegevens kunt evalueren

U toont datalekken aan door een gememoriseerd model te evalueren en ziet waarom achtergehouden testgegevens essentieel zijn voor eerlijke prestatie-inschattingen.

Les 1 van 412 stappen

Waarom u niet op trainingsgegevens kunt evalueren 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 evaluatievalkuil

Na het trainen van een model is het verleidelijkste wat je kunt doen het testen op dezelfde gegevens die je voor de training hebt gebruikt. Het model zal waarschijnlijk zeer hoog scoren — soms 100% accuracy — en dat voelt als succes. Dat is het niet. Dit is de meest fundamentele fout in machinaal leren en levert resultaten op die volledig onbruikbaar zijn voor het voorspellen van prestaties in de echte wereld.

Begrijpen waarom dit mislukt is niet slechts een technische bijzonderheid — het verandert hoe je naar het volledige doel van machinaal leren kijkt. Het doel is nooit om goed te presteren op trainingsgegevens. Het doel is altijd om te generaliseren naar nieuwe, ongeziene gegevens.

Memoriseren versus generaliseren

Denk aan het verschil tussen een student die elk antwoord uit een boek ter voorbereiding op een examen uit het hoofd leert en een student die de stof echt begrijpt. De eerste student behaalt perfecte scores op elke oefenopgave, maar faalt wanneer het echte examen een iets andere formulering gebruikt. De tweede student haalt misschien geen perfecte scores op oefenopgaven, maar behandelt nieuwe vragen vol vertrouwen.

Een ML-model dat trainingsvoorbeelden 'uit het hoofd leert' (een sterk overfit model) gedraagt zich precies als de eerste student. Het behaalt een perfecte trainings-accuracy, maar faalt op nieuwe invoer. Dit verschijnsel heet datam lek wanneer het tijdens de evaluatie gebeurt — je hebt de antwoorden als het ware naar de test laten lekken.

Een demonstratie: memoriseren in actie

Laten we dit empirisch bewijzen. Een beslisboom met onbeperkte diepte zal elk trainingsvoorbeeld perfect uit het hoofd leren en een trainings-accuracy van 100% behalen. De test-accuracy zal echter veel lager zijn, omdat de boom ruis heeft geleerd in plaats van het werkelijke onderliggende patroon.

Dit experiment maakt het probleem concreet en meetbaar: trainings-accuracy is betekenisloos als schatting van prestaties — het meet geheugen, geen intelligentie.

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Unlimited depth: memorises training data
model = DecisionTreeClassifier()  # no max_depth limit
model.fit(X_train, y_train)

train_acc = model.score(X_train, y_train)
test_acc  = model.score(X_test, y_test)

print(f'Training accuracy: {train_acc:.3f}')  # 1.000 -- perfect memorisation
print(f'Test accuracy:     {test_acc:.3f}')   # much lower
print(f'Overfit gap:       {train_acc - test_acc:.3f}')

Waarom trainings-accuracy optimistisch vertekend is

De parameters van het model zijn specifiek geoptimaliseerd om de fout op de trainingsset te minimaliseren. Dit betekent dat de trainingsfout voor elk redelijk complex model gegarandeerd lager is dan de werkelijke generalisatiefout. Het verschil tussen de trainingsfout en de testfout heet het optimisme van de trainingsfout.

Hoe meer parameters een model heeft in verhouding tot het aantal trainingsvoorbeelden, hoe sterker het optimisme. Een neuraal netwerk met miljoenen parameters en slechts 1.000 trainingsvoorbeelden kan gemakkelijk een trainingsfout van 0% behalen, terwijl het werkelijke foutpercentage 50% is. De trainingsfout is geen betrouwbare schatting van generalisatie — punt.

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import numpy as np

X, y = make_classification(n_samples=500, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

# KNN with k=1: memorises perfectly (always finds the exact training point)
knn1 = KNeighborsClassifier(n_neighbors=1)
knn1.fit(X_train, y_train)

print(f'k=1 Training accuracy: {knn1.score(X_train, y_train):.3f}')  # 1.000
print(f'k=1 Test accuracy:     {knn1.score(X_test, y_test):.3f}')    # lower

# k=10: generalisers better
knn10 = KNeighborsClassifier(n_neighbors=10)
knn10.fit(X_train, y_train)
print(f'k=10 Test accuracy:    {knn10.score(X_test, y_test):.3f}')

De achtergehouden testset: de oplossing

De oplossing is eenvoudig, maar moet strikt worden afgedwongen: reserveer een deel van je gegevens voordat je met modelleren begint en gebruik dit deel nooit voor training of voor beslissingen die het model beïnvloeden.

Deze achtergehouden testset is je eerlijke schatting van de generalisatieprestaties. Omdat het model deze gegevens nog nooit heeft gezien, zijn de prestaties op deze set de best beschikbare schatting van hoe het op toekomstige gegevens zal presteren. De testset is een meetinstrument voor eenmalig gebruik — als je deze meerdere keren gebruikt om je model af te stellen, maak je de set ongeldig.

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import numpy as np

X, y = load_breast_cancer(return_X_y=True)

# CORRECT workflow: split BEFORE any analysis
X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.20,   # 20% held out for final evaluation only
    random_state=42,  # reproducible split
    stratify=y        # maintain class ratio in both splits
)

print(f'Training set:  {X_train.shape[0]} examples')
print(f'Test set:      {X_test.shape[0]} examples')
print(f'Train class balance: {y_train.mean():.3f}')
print(f'Test class balance:  {y_test.mean():.3f}')

Dataclassificatie: de subtiele variant

Het gebruik van testgegevens voor de eindevaluatie is de meest voor de hand liggende vorm van datalekken. Er zijn subtielere vormen die net zo schadelijk zijn:

  • Datalekken bij voorbewerking: een scaler aanpassen op de volledige dataset voordat je deze splitst en daarna de trainings- en testgegevens schalen — de scaler heeft de statistieken van de testgegevens al 'gezien'.
  • Datalekken via kenmerken: een kenmerk opnemen dat is afgeleid van de doelvariabele (bijvoorbeeld een vlag 'diagnose bevestigd' die alleen wordt ingesteld wanneer een patiënt daadwerkelijk ziek is).
  • Datalekken door tijd: toekomstige gegevens gebruiken om gebeurtenissen uit het verleden te voorspellen (bijvoorbeeld verkoopgegevens van het derde kwartaal opnemen bij het voorspellen van uitkomsten voor het eerste kwartaal).
from sklearn.preprocessing import StandardScaler
import numpy as np

# WRONG: fit scaler on full dataset before splitting
X = np.random.randn(1000, 5)
scaler_wrong = StandardScaler()
X_scaled_all = scaler_wrong.fit_transform(X)  # leakage! scaler saw test data

# Correct: split first, then fit scaler ONLY on training data
from sklearn.model_selection import train_test_split
X_train, X_test = train_test_split(X, test_size=0.2)
scaler_correct = StandardScaler()
X_train_s = scaler_correct.fit_transform(X_train)  # fit on train only
X_test_s  = scaler_correct.transform(X_test)        # apply to test
print('Correct preprocessing: scaler fitted on training data only.')

Driedeling: training, validatie en test

Wanneer je de testset gebruikt om beslissingen te nemen — bijvoorbeeld om tussen twee modellen te kiezen of een drempelwaarde te selecteren — is deze niet langer een zuivere schatting van de generalisatie. Om de testset onaangetast te houden, voeg je een validatieset toe:

  • Trainingsset: modelparameters aanpassen.
  • Validatieset: hyperparameters afstemmen, modellen selecteren en drempelwaarden aanpassen.
  • Testset: eenmalige eindevaluatie. Gebruik deze slechts één keer, helemaal aan het einde.

Een gebruikelijke verdeling is 70% training / 15% validatie / 15% test. Kruisvalidatie biedt een efficiënter alternatief door de validatievouwen binnen de trainingsset afwisselend te gebruiken.

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True)

# First split off test set (15%)
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.15, random_state=42)
# Then split remaining into train and validation
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.176, random_state=42)
# 0.176 of 85% ≈ 15% of the original

print(f'Train: {X_train.shape[0]}')
print(f'Val:   {X_val.shape[0]}')
print(f'Test:  {X_test.shape[0]}')

Hoe besmetting van de testset resultaten opblaast

Stel dat je 10 verschillende modellen traint, elk model op de testset evalueert en vervolgens het model met de hoogste testnauwkeurigheid kiest. Door dit proces is de testset besmet — je hebt de prestaties op de testset gebruikt om een modelbeslissing te nemen. Het geselecteerde model is geoptimaliseerd voor de testset en de gerapporteerde nauwkeurigheid is nu te optimistisch.

Daarom hebben wedstrijden zoals Kaggle een openbaar klassement (validatieset) en een privéklassement (de echte testset, die pas aan het einde wordt onthuld). Teams die het openbare klassement overfitten door veel inzendingen te doen, presteren vaak slecht in het privéklassement.

from sklearn.datasets import make_classification
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
import numpy as np

X, y = make_classification(n_samples=500, random_state=99)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Contamination: picking best max_depth based on test set
best_acc, best_depth = 0, 1
for depth in range(1, 20):
    model = DecisionTreeClassifier(max_depth=depth)
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)
    if acc > best_acc:
        best_acc, best_depth = acc, depth

print(f'Best depth selected by test: {best_depth}, acc: {best_acc:.3f}')
print('This accuracy is now overly optimistic!')

Reproduceerbaarheid: de parameter random_state

De parameter random_state in train_test_split bepaalt welke voorbeelden in welke deelverzameling terechtkomen. Zonder deze parameter levert elke uitvoering een andere verdeling op, waardoor resultaten moeilijk te reproduceren en te vergelijken zijn.

Stel random_state altijd in op een vast geheel getal in alle code die je met anderen deelt of later opnieuw wilt uitvoeren. Elk geheel getal werkt — de conventie is om 42, 0 of 1 te gebruiken — zolang je maar documenteert welke waarde je hebt gebruikt. De specifieke waarde van het gehele getal maakt niet uit; consistentie wel.

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)

# Without random_state: different results every run
X_train1, X_test1, _, _ = train_test_split(X, y)          # no seed
X_train2, X_test2, _, _ = train_test_split(X, y)          # no seed
print('Different splits without seed:', not (X_train1 == X_train2).all())

# With random_state: same result every run
X_train3, X_test3, _, _ = train_test_split(X, y, random_state=42)
X_train4, X_test4, _, _ = train_test_split(X, y, random_state=42)
print('Same splits with seed:', (X_train3 == X_train4).all())

De gouden regel voor ML-evaluatie

De ene regel die alles in deze les omvat: de testset mag nooit invloed hebben op beslissingen die tijdens de modelontwikkeling worden genomen. Dit betekent:

  • Geen voorbewerking die is aangepast op testgegevens.
  • Geen model dat is geselecteerd op basis van prestaties op de testset.
  • Geen drempelwaarde die is afgestemd op prestaties op de testset.
  • Geen kenmerk dat is ontworpen nadat je de fouten op de testset hebt gezien.
  • De testset slechts één keer gebruiken, helemaal aan het einde, om de uiteindelijke prestaties te rapporteren.

Als je deze regel volgt, zijn je gerapporteerde prestaties een eerlijke schatting van hoe het model zich in productie op toekomstige gegevens zal gedragen.

Snelle controle

Test je begrip van de concepten rond machinaal leren met Python uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat de trainingsnauwkeurigheid altijd optimistisch vertekend is, omdat de modelparameters op die gegevens zijn geoptimaliseerd, dat een achtergehouden testset die geen enkele trainingsbeslissing beïnvloedt een eerlijke schatting van de generalisatie oplevert en dat datad lekkken — waaronder datalekken bij voorbewerking en besmetting van de testset — misleidend hoge schattingen van de prestaties opleveren. Hierna leer je de functie train_test_split van scikit-learn grondig beheersen, met aandacht voor verhoudingen van de testgrootte, willekeurige zaden en stratificatie voor classificatieproblemen met een ongelijke klassendistributie.

Gratis beginnen

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 “Waarom u niet op trainingsgegevens kunt evalueren” gratis?

Ja — de volledige tekst van “Waarom u niet op trainingsgegevens kunt evalueren” 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 “Waarom u niet op trainingsgegevens kunt evalueren”?

U toont datalekken aan door een gememoriseerd model te evalueren en ziet waarom achtergehouden testgegevens essentieel zijn voor eerlijke prestatie-inschattingen. 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 “Waarom u niet op trainingsgegevens kunt evalueren”?

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

  1. Waarom u niet op trainingsgegevens kunt evalueren
  2. train_test_split: verhoudingen, seeds en stratificatie
  3. Bias-variantieafweging: underfitting versus overfitting
  4. Basismodellen: versla altijd de DummyClassifier
← Terug naar Machine Learning Academy