Iteratief Werken
AI-ontwikkeling is inherent iteratief. Je begint zelden met de perfecte dataset of het ideale model — je verbetert stap voor stap. Dit hoofdstuk behandelt de tools en werkwijze voor effectief iteratief werken.
Jupyter Notebooks
Jupyter Notebooks zijn interactieve documenten waarin je code, output en documentatie combineert. Ze zijn de standaard werkomgeving voor data science en ML-experimenten.
Wat is een Jupyter Notebook?
Een notebook bestaat uit cellen die je individueel kunt uitvoeren:
| Celtype |
Inhoud |
Voorbeeld |
| Code |
Python (of andere taal) |
Data laden, model trainen |
| Markdown |
Tekst, koppen, lijsten |
Uitleg, conclusies, documentatie |
| Output |
Resultaat van code |
Grafieken, tabellen, print statements |
Waarom notebooks gebruiken?
| Voordeel |
Toelichting |
| Interactief |
Voer code stap voor stap uit, zie direct resultaat |
| Visueel |
Grafieken en tabellen inline |
| Documentatie |
Code en uitleg in één document |
| Experimenteren |
Snel variaties proberen zonder hele script te draaien |
| Delen |
Makkelijk resultaten delen met anderen |
Notebook workflow
| 1. Data laden en verkennen
↓
2. Preprocessing experimenteren
↓
3. Model trainen en evalueren
↓
4. Resultaten visualiseren
↓
5. Itereren (terug naar stap 2 of 3)
|
Best practices
| Practice |
Reden |
| Voer cellen van boven naar beneden uit |
Voorkomt verwarring over state |
| Herstart kernel regelmatig |
Garandeert reproduceerbaarheid |
| Houd cellen kort |
Makkelijker te debuggen en begrijpen |
| Gebruik markdown voor uitleg |
Documenteer je gedachtegang |
| Verplaats productie-code naar .py files |
Notebooks zijn voor experimenten, niet voor productie |
Basis commando's
| Actie |
Shortcut |
| Cel uitvoeren |
Shift + Enter |
| Cel uitvoeren, blijf in cel |
Ctrl + Enter |
| Nieuwe cel boven |
A (in command mode) |
| Nieuwe cel onder |
B (in command mode) |
| Cel verwijderen |
DD (in command mode) |
| Naar command mode |
Esc |
| Naar edit mode |
Enter |
Voorbeeld notebook structuur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | # Project: Churn Voorspelling
## 1. Data Laden
[code cel: imports en data laden]
[output: df.head()]
## 2. Exploratie
[code cel: df.describe(), visualisaties]
[output: grafieken]
## 3. Preprocessing
[code cel: missing values, encoding]
## 4. Model Training
[code cel: train_test_split, model.fit()]
## 5. Evaluatie
[code cel: metrics, confusion matrix]
[output: resultaten]
## 6. Conclusie
[markdown cel: bevindingen en volgende stappen]
|
!!! warning "Notebooks en versiebeheer"
Notebooks bevatten output en metadata, wat merge conflicts lastig maakt. Overweeg tools als nbstripout om output te verwijderen voor commits, of gebruik jupytext om notebooks als .py files op te slaan.
De Data-Model-Evaluatie Cyclus
Net zoals software development de "think-make-check" cyclus kent, heeft ML-ontwikkeling de data-model-evaluatie cyclus. Dit is de kern van iteratief werken in AI-projecten.
De cyclus
| ┌─────────────────────────────────────────┐
│ │
▼ │
┌───────┐ ┌───────┐ ┌───────────┐ │
│ DATA │ ──▶ │ MODEL │ ──▶ │ EVALUATIE │ ─┘
└───────┘ └───────┘ └───────────┘
│ │ │
│ │ │
▼ ▼ ▼
Verbeter Pas aan Analyseer
de data het model de fouten
|
Fase 1: Data
In deze fase verzamel, verken en bereid je de data voor.
| Activiteit |
Vragen om te stellen |
| Verzamelen |
Heb ik genoeg data? Is het representatief? |
| Verkennen |
Wat zijn de verdelingen? Zijn er patronen? Outliers? |
| Cleanen |
Hoe ga ik om met missing values? Duplicaten? |
| Transformeren |
Welke features maak ik? Welke encoding? |
| Splitten |
Train/val/test — is de verdeling stratified? |
Iteratie trigger: Als je model slecht presteert, kijk eerst naar de data:
- Meer data verzamelen
- Betere features maken
- Data balanceren
- Ruis verminderen
Fase 2: Model
In deze fase kies en train je een model.
| Activiteit |
Vragen om te stellen |
| Modelkeuze |
Welk type model past bij dit probleem? |
| Baseline |
Wat is de simpelste oplossing die werkt? |
| Training |
Hoe lang trainen? Wanneer stoppen? |
| Hyperparameters |
Welke instellingen proberen? |
Iteratie trigger: Als je model niet leert of overfit:
- Probeer een ander modeltype
- Pas hyperparameters aan
- Voeg regularisatie toe
- Versimpel of complexer maken
Fase 3: Evaluatie
In deze fase meet en analyseer je de prestaties.
| Activiteit |
Vragen om te stellen |
| Metrics kiezen |
Welke metrics zijn relevant voor dit probleem? |
| Meten |
Hoe presteert het model op train/val/test? |
| Analyseren |
Waar maakt het model fouten? Waarom? |
| Vergelijken |
Is dit beter dan de baseline? Dan vorige iteratie? |
Iteratie trigger: Analyse wijst naar verbetermogelijkheden:
- Model maakt fouten op specifieke subset → meer data van die groep
- Overfitting → regularisatie, minder complex model
- Underfitting → complexer model, betere features
- Bias gedetecteerd → data of model aanpassen
Iteratie in de praktijk
Iteratie log bijhouden
Houd een log bij van je experimenten:
| Iteratie |
Wijziging |
Val Accuracy |
Observatie |
| 1 |
Baseline: Logistic Regression |
0.72 |
Underfitting |
| 2 |
Random Forest, default params |
0.81 |
Beter, maar overfit |
| 3 |
RF + max_depth=10 |
0.79 |
Minder overfit |
| 4 |
RF + feature engineering |
0.84 |
Nieuwe features helpen |
| 5 |
XGBoost + tuning |
0.87 |
Beste tot nu toe |
| Tool |
Beschrijving |
| MLflow |
Open source, track experiments, modellen, metrics |
| Weights & Biases |
Cloud-based, mooie visualisaties |
| Neptune |
Experiment tracking en model registry |
| TensorBoard |
Vooral voor deep learning |
| Handmatig (spreadsheet) |
Simpel maar foutgevoelig |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | import mlflow
# Start een experiment run
with mlflow.start_run():
# Log parameters
mlflow.log_param("model_type", "RandomForest")
mlflow.log_param("n_estimators", 100)
# Train model
model.fit(X_train, y_train)
# Log metrics
accuracy = model.score(X_val, y_val)
mlflow.log_metric("val_accuracy", accuracy)
# Log model
mlflow.sklearn.log_model(model, "model")
|
Wanneer stoppen met itereren?
Niet elke iteratie levert verbetering op. Weet wanneer je moet stoppen:
| Situatie |
Actie |
| Diminishing returns |
Kleine verbeteringen kosten veel tijd |
| Target bereikt |
Je haalt de gewenste performance |
| Deadline |
Tijd om te shippen wat je hebt |
| Overfitting op validatieset |
Je optimaliseert te veel op val set |
Checklist voor "goed genoeg"
- [ ] Performance voldoet aan minimum requirements
- [ ] Model presteert consistent op verschillende data subsets
- [ ] Resultaten zijn reproduceerbaar
- [ ] Code is opgeruimd en gedocumenteerd
- [ ] Finale evaluatie op testset is gedaan
!!! tip "Timebox je iteraties"
Geef jezelf een tijdslimiet per iteratie. Na 2 uur hyperparameter tuning met marginale verbetering is het misschien beter om naar de data te kijken of een ander model te proberen.
Van notebook naar productie
Notebooks zijn ideaal voor experimenten, maar niet voor productie. Wanneer je iteraties klaar zijn:
| Stap |
Actie |
| 1 |
Opruimen: Verwijder dode code, experimentele cellen |
| 2 |
Refactoren: Zet herbruikbare code in functies/classes |
| 3 |
Verplaatsen: Kopieer productie-code naar .py modules |
| 4 |
Testen: Schrijf unit tests voor je functies |
| 5 |
Documenteren: Docstrings en README |
| 6 |
Pipeline maken: Automatiseer de data → model → evaluatie flow |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | # Notebook experiment
df = pd.read_csv("data.csv")
df = df.dropna()
df["feature_new"] = df["a"] / df["b"]
# ... meer code ...
# ↓ Wordt in productie ↓
# src/preprocessing.py
def load_and_clean_data(path: str) -> pd.DataFrame:
"""Laad data en voer basis cleaning uit."""
df = pd.read_csv(path)
df = df.dropna()
return df
def create_features(df: pd.DataFrame) -> pd.DataFrame:
"""Voeg engineered features toe."""
df["feature_new"] = df["a"] / df["b"]
return df
|