Skip to content

Model Training

Dit hoofdstuk behandelt het trainen van machine learning modellen, het maken van voorspellingen, het evalueren van resultaten en het herkennen van overfitting en underfitting.


Model trainen

Het trainen van een model betekent dat je het algoritme laat leren van je data. Het model past zijn interne parameters aan om zo goed mogelijk te presteren op de trainingstaak.

Basis workflow

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

# 1. Data splitsen
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 2. Model instantiëren
model = RandomForestClassifier(n_estimators=100, random_state=42)

# 3. Model trainen
model.fit(X_train, y_train)

# 4. Model is nu klaar voor voorspellingen

Wat gebeurt er tijdens training?

Model type Wat het leert
Linear Regression Gewichten (coëfficiënten) voor elke feature
Decision Tree Splitsingspunten en drempelwaarden
Random Forest Meerdere decision trees
Neural Network Gewichten en biases in alle lagen
KNN Niets — slaat alleen data op (lazy learning)

Training parameters

Parameter Beschrijving
Hyperparameters Instellingen die je vóór training kiest (learning rate, max_depth)
Epochs Aantal keer dat het model de hele dataset ziet (neural networks)
Batch size Aantal samples per update (neural networks)
Early stopping Stop training als validatie-performance niet meer verbetert

Voorbeeld: Neural Network training

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from tensorflow import keras

model = keras.Sequential([
    keras.layers.Dense(64, activation='relu', input_shape=(n_features,)),
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy']
)

# Training met validatie
history = model.fit(
    X_train, y_train,
    epochs=100,
    batch_size=32,
    validation_split=0.2,
    callbacks=[keras.callbacks.EarlyStopping(patience=5)]
)

Runnen van predictions

Na het trainen kun je het model gebruiken om voorspellingen te doen op nieuwe, ongeziene data.

Basis voorspellingen

1
2
3
4
5
6
7
8
# Voorspel klassen (classificatie)
y_pred = model.predict(X_test)

# Voorspel waarschijnlijkheden (classificatie)
y_pred_proba = model.predict_proba(X_test)

# Voorspel continue waarden (regressie)
y_pred = model.predict(X_test)

Verschil predict vs. predict_proba

Methode Output Voorbeeld
predict() Klasse-labels [0, 1, 1, 0, 1]
predict_proba() Kansen per klasse [[0.8, 0.2], [0.3, 0.7], ...]

Voorspellingen interpreteren

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Classificatie
y_pred = model.predict(X_test)
print(f"Voorspelde klasse: {y_pred[0]}")

# Met waarschijnlijkheden
y_pred_proba = model.predict_proba(X_test)
print(f"Kans op klasse 0: {y_pred_proba[0][0]:.2%}")
print(f"Kans op klasse 1: {y_pred_proba[0][1]:.2%}")

# Pas threshold aan (standaard 0.5)
threshold = 0.7
y_pred_custom = (y_pred_proba[:, 1] >= threshold).astype(int)

Voorspelling op nieuwe data

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Nieuwe, ongeziene data
nieuwe_klant = [[35, 50000, 2, 1]]  # leeftijd, inkomen, producten, actief

# Let op: zelfde preprocessing als trainingsdata!
nieuwe_klant_scaled = scaler.transform(nieuwe_klant)

# Voorspelling
voorspelling = model.predict(nieuwe_klant_scaled)
kans = model.predict_proba(nieuwe_klant_scaled)

print(f"Voorspelling: {'Churn' if voorspelling[0] == 1 else 'Geen churn'}")
print(f"Zekerheid: {max(kans[0]):.1%}")

!!! warning "Preprocessing niet vergeten" Nieuwe data moet exact dezelfde preprocessing ondergaan als de trainingsdata (scaling, encoding, etc.). Gebruik dezelfde scaler/encoder objecten die je op de trainingsdata hebt gefit.


Evaluatiemetrics

Evaluatiemetrics meten hoe goed je model presteert. Welke metric je kiest hangt af van je probleem.

Classificatie metrics

Confusion Matrix basis

Voorspeld: Positief Voorspeld: Negatief
Werkelijk: Positief True Positive (TP) False Negative (FN)
Werkelijk: Negatief False Positive (FP) True Negative (TN)

Accuracy

Formule: $(TP + TN) / (TP + TN + FP + FN)$

Wanneer gebruiken Wanneer niet
Gebalanceerde klassen Ongebalanceerde data (90% negatief)
Alle fouten even erg FP en FN hebben verschillende kosten
1
2
3
4
from sklearn.metrics import accuracy_score

accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2%}")

Precision

Formule: $TP / (TP + FP)$

"Van alle positieve voorspellingen, hoeveel waren correct?"

Wanneer belangrijk
False positives zijn kostbaar (spam detectie, fraude alerts)

Recall (Sensitivity)

Formule: $TP / (TP + FN)$

"Van alle werkelijk positieve cases, hoeveel hebben we gevonden?"

Wanneer belangrijk
False negatives zijn kostbaar (ziekte detectie, security threats)

F1-Score

Formule: $2 \times (Precision \times Recall) / (Precision + Recall)$

Het harmonisch gemiddelde van precision en recall. Nuttig wanneer je beide wilt balanceren.

1
2
3
4
5
6
7
8
9
from sklearn.metrics import precision_score, recall_score, f1_score

precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print(f"Precision: {precision:.2%}")
print(f"Recall: {recall:.2%}")
print(f"F1-Score: {f1:.2%}")

Classification Report

1
2
3
from sklearn.metrics import classification_report

print(classification_report(y_test, y_pred))

Output:

1
2
3
4
5
6
              precision    recall  f1-score   support
           0       0.85      0.90      0.87       100
           1       0.78      0.70      0.74        50
    accuracy                           0.83       150
   macro avg       0.81      0.80      0.81       150
weighted avg       0.83      0.83      0.83       150

ROC en AUC

ROC (Receiver Operating Characteristic) curve toont de trade-off tussen True Positive Rate en False Positive Rate bij verschillende thresholds.

AUC (Area Under Curve) is de oppervlakte onder de ROC curve — hoe hoger (max 1.0), hoe beter.

AUC waarde Interpretatie
0.5 Random gokken
0.7 - 0.8 Acceptabel
0.8 - 0.9 Goed
0.9+ Uitstekend
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt

# Bereken ROC curve
y_pred_proba = model.predict_proba(X_test)[:, 1]
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)

# Bereken AUC
auc = roc_auc_score(y_test, y_pred_proba)

# Plot
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, label=f'ROC curve (AUC = {auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--', label='Random')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
plt.show()

Regressie metrics

Metric Formule Interpretatie
MAE Gemiddelde absolute fout Makkelijk te interpreteren, zelfde eenheid als target
MSE Gemiddelde kwadratische fout Straft grote fouten zwaarder
RMSE Wortel van MSE Zelfde eenheid als target
Verklaarde variantie 0-1, hoe hoger hoe beter
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np

mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)

print(f"MAE: {mae:.2f}")
print(f"RMSE: {rmse:.2f}")
print(f"R²: {r2:.2f}")

NLP metrics

Voor tekstgeneratie en vertaling worden specifieke metrics gebruikt:

BLEU (Bilingual Evaluation Understudy)

Meet overlap van n-grams tussen gegenereerde tekst en referentietekst. Vooral gebruikt voor machine translation.

1
2
3
4
5
6
7
from nltk.translate.bleu_score import sentence_bleu

reference = [['dit', 'is', 'een', 'test', 'zin']]
candidate = ['dit', 'is', 'een', 'voorbeeld', 'zin']

bleu = sentence_bleu(reference, candidate)
print(f"BLEU score: {bleu:.2f}")

ROUGE (Recall-Oriented Understudy for Gisting Evaluation)

Meet overlap tussen gegenereerde samenvatting en referentiesamenvatting. Vooral voor summarization.

Variant Meet
ROUGE-1 Overlap van individuele woorden
ROUGE-2 Overlap van bigrammen
ROUGE-L Langste gemeenschappelijke subsequentie
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from rouge_score import rouge_scorer

scorer = rouge_scorer.RougeScorer(['rouge1', 'rouge2', 'rougeL'])
scores = scorer.score(
    'dit is de referentie tekst',
    'dit is de gegenereerde tekst'
)

for metric, score in scores.items():
    print(f"{metric}: Precision={score.precision:.2f}, Recall={score.recall:.2f}")

Overfitting en Underfitting

Overfitting en underfitting zijn de twee hoofdproblemen bij model training.

Underfitting

Underfitting betekent dat je model te simpel is om de patronen in de data te leren.

Symptomen Oorzaken
Lage training score Model te simpel
Lage validatie score Te weinig features
Training ≈ Validatie (beide laag) Te veel regularisatie
1
2
3
Training accuracy:   65%
Validation accuracy: 63%
→ Beide laag = underfitting

Overfitting

Overfitting betekent dat je model de trainingsdata "uit het hoofd leert", inclusief de ruis, en niet generaliseert naar nieuwe data.

Symptomen Oorzaken
Hoge training score Model te complex
Lage validatie score Te weinig data
Groot verschil train/val Te lang getraind
1
2
3
Training accuracy:   98%
Validation accuracy: 72%
→ Groot verschil = overfitting

Visueel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
        Error
          │
  High    │   Underfitting              Overfitting
          │       ╲                         ╱
          │        ╲    ┌─────────┐        ╱
          │         ╲   │ Optimal │       ╱
          │          ╲  │  Zone   │      ╱
  Low     │           ╲─┴─────────┴─────╱
          │
          └────────────────────────────────▶
              Simple    Model Complexity    Complex

Diagnose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Train en validatie scores vergelijken
train_score = model.score(X_train, y_train)
val_score = model.score(X_val, y_val)

print(f"Training score: {train_score:.2%}")
print(f"Validation score: {val_score:.2%}")

if train_score < 0.7 and val_score < 0.7:
    print("→ Mogelijk underfitting")
elif train_score - val_score > 0.1:
    print("→ Mogelijk overfitting")
else:
    print("→ Goede balans")

Learning curves

Learning curves helpen bij het diagnosticeren:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt

train_sizes, train_scores, val_scores = learning_curve(
    model, X, y, cv=5, 
    train_sizes=np.linspace(0.1, 1.0, 10)
)

plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_scores.mean(axis=1), label='Training score')
plt.plot(train_sizes, val_scores.mean(axis=1), label='Validation score')
plt.xlabel('Training set size')
plt.ylabel('Score')
plt.title('Learning Curve')
plt.legend()
plt.show()

Oplossingen

Underfitting oplossen

Strategie Implementatie
Complexer model Meer layers, meer bomen, hogere max_depth
Meer features Feature engineering
Minder regularisatie Verlaag alpha, C, dropout
Langer trainen Meer epochs
Ander algoritme Probeer non-lineair model

Overfitting oplossen

Strategie Implementatie
Meer data Verzamel meer training samples
Simpeler model Minder layers, lagere max_depth
Regularisatie L1/L2, dropout, early stopping
Data augmentatie Meer variatie in trainingsdata
Cross-validation Robuustere evaluatie
Feature selection Verwijder irrelevante features
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Voorbeeld: Regularisatie in Random Forest
from sklearn.ensemble import RandomForestClassifier

# Voorkom overfitting met constraints
model = RandomForestClassifier(
    n_estimators=100,
    max_depth=10,           # Beperk diepte
    min_samples_split=10,   # Minimum samples voor split
    min_samples_leaf=5,     # Minimum samples per blad
    random_state=42
)

# Voorbeeld: Early stopping in neural networks
from tensorflow.keras.callbacks import EarlyStopping

early_stop = EarlyStopping(
    monitor='val_loss',
    patience=10,
    restore_best_weights=True
)

model.fit(X_train, y_train, 
          validation_split=0.2,
          callbacks=[early_stop])

Samenvatting

Situatie Train Score Val Score Actie
Underfitting Laag Laag Complexer model, meer features
Overfitting Hoog Laag Regularisatie, meer data, simpeler model
Goed Hoog Hoog (vergelijkbaar) Model is klaar

!!! tip "Altijd beginnen met de data" Voordat je aan modelcomplexiteit sleutelt, kijk eerst naar je data. Vaak is meer of betere data effectiever dan een complexer model.