Lecture 3: Hands-on machine learning met Python

1 Inleiding

In de vorige twee lessen legden we de theoretische grondslagen: kansverdelingen, regressie, loss-functies, cross-validatie, de bias-variance trade-off en een overzicht van de meest gebruikte machine learning-methoden. In deze les zetten we die kennis om in praktijk.

We doen dit via een combinatie van twee hulpmiddelen: Python als rekenwerktuig, en AI-assistenten die ons helpen om snel werkende code te schrijven. Het doel is niet om Python-expert te worden, maar om zelfstandig een machine learning-analyse te kunnen opzetten, te begrijpen wat de code doet, en de resultaten kritisch te interpreteren.

1.1 Je Python-omgeving kiezen

Je hebt Python nodig om de oefeningen te kunnen uitvoeren. Er zijn drie gangbare opties, elk met een andere afweging:

Optie 1 — JupyterLite (geen installatie vereist)

JupyterLite is een volledig in de browser draaiende Jupyter-omgeving. Je hoeft niets te installeren en er is geen account nodig.

Voordelen: onmiddellijk beschikbaar, geen installatie, werkt op elk apparaat.

Nadelen: beperkt aantal beschikbare packages, geheugen en rekenkracht. TensorFlow en PyMC werken niet in deze browseromgeving, waardoor de oefeningen over neurale netwerken en Bayesiaanse inferentie hier niet volledig kunnen worden uitgevoerd.

Bestanden kunnen in de lokale browseropslag bewaard blijven wanneer je later met hetzelfde browserprofiel terugkeert. Beschouw dit echter niet als een veilige back-up: bestanden kunnen verdwijnen wanneer browsergegevens worden gewist, een privatievenster wordt gesloten, het bedrijfsbeleid opslag opruimt of je van browser of computer wisselt. Download je notebook na iedere werksessie en bewaar het op een betrouwbare lokale, netwerk- of cloudlocatie.

Wanneer te gebruiken: als je snel wil starten zonder administratorrechten of als een installatie niet mogelijk is.

Optie 2 — Google Colab (krachtig, vereist Google-account)

Google Colab is een cloudplatform van Google dat Jupyter-notebooks in de browser uitvoert. Er is een gratis niveau en er kan GPU-capaciteit beschikbaar zijn voor neurale netwerken.

Voordelen: veel populaire packages zijn voorgeïnstalleerd, geen lokale Python-installatie en notebooks kunnen in Google Drive worden opgeslagen.

Nadelen: vereist voor duurzaam opslaan een Google-account, kan geblokkeerd zijn op bedrijfslaptops en sessies vervallen na inactiviteit. Gratis GPU-toegang is niet gegarandeerd en gebruikslimieten kunnen variëren. Een ontbrekend package moet aan het begin van de sessie opnieuw worden geïnstalleerd.

Wanneer te gebruiken: als je meer rekenkracht nodig hebt (bv. voor neurale netwerken in sectie 2) of als je de voorkeur geeft aan een cloudoplossing.

Optie 3 — Lokale Python-installatie met VS Code (aanbevolen)

Een lokale installatie biedt de beste ervaring op lange termijn: volledige controle over packages, betrouwbare bestanden en een volwassen ontwikkelomgeving. Voor deze cursus gebruiken we Python 3.12 of 3.13. Python 3.14 wordt voorlopig niet aanbevolen omdat niet alle benodigde packages, in het bijzonder TensorFlow, daarvoor beschikbaar zijn.

Aanbevolen aanpak:

  1. Installeer VS Code.

  2. Installeer uv — een moderne Python- en pakketbeheerder die ook een geschikte Python-versie kan installeren.

  3. Maak een nieuw project aan en start een notebook:

    uv init --python 3.13 mijn-ml-project
    cd mijn-ml-project
    uv add scikit-learn matplotlib seaborn pandas jupyter tensorflow pymc arviz
    uv run jupyter notebook
  4. Installeer de Jupyter-extensie voor VS Code om notebooks direct in VS Code te openen.

Voordelen: volledige flexibiliteit, alle packages beschikbaar en na installatie grotendeels offline bruikbaar.

Nadelen: vereist een eenmalige installatie — met uv gaat dit echter snel en probleemloos.

1.2 Welke oefeningen werken waar?

Oefening JupyterLite Google Colab Lokaal met Python 3.12–3.13
California Housing Ja, wanneer scikit-learn beschikbaar is Ja Ja
Fashion-MNIST met Keras Nee, TensorFlow is niet beschikbaar Ja Ja
Titanic Ja, maar het kan nodig zijn de dataset als bestand te uploaden Ja Ja
Bayesiaans model met PyMC Nee Ja, installeer PyMC indien nodig Ja

Geen enkele route is voor alle studenten vanzelfsprekend de beste. Kies de omgeving die op jouw computer toegelaten is. Wanneer een package ontbreekt of een website geblokkeerd is, bewaar je notebook en ga indien mogelijk verder via een van de andere routes. De statistische vragen en prompts blijven in alle omgevingen dezelfde.

1.3 AI-assistenten inzetten

Een AI-assistent kan helpen om Python-code te schrijven, foutmeldingen te onderzoeken, alternatieven te vergelijken en concepten te verduidelijken. Beschouw de assistent daarbij als een sparringpartner, niet als automatische piloot. Jij blijft verantwoordelijk voor de probleemstelling, de gemaakte keuzes en de interpretatie van het resultaat.

Een nuttige taakverdeling is:

  • Jij bepaalt welke vraag je wil beantwoorden, welke data relevant is en wanneer een resultaat geloofwaardig is.
  • De AI helpt om ideeën uit te werken, code voor te stellen, fouten te vinden en mogelijke verklaringen te formuleren.
  • Jij controleert of de code doet wat ze beweert, of de evaluatie correct is en of de conclusie door de data wordt gedragen.

AI-assistenten zijn onder meer beschikbaar als:

Online taalmodellen — via een browser:

  • ChatGPT (OpenAI) — breed toegankelijk, ook gratis versies beschikbaar
  • Claude (Anthropic) — sterk in technische uitleg en langere taken
  • Gemini (Google) — geïntegreerd in Google-producten, ook beschikbaar in Colab

Code-assistenten — geïntegreerd in je editor of terminal:

  • GitHub Copilot — werkt als autocomplete in VS Code, sterk voor code-aanvulling
  • Claude Code — volledig geïntegreerde assistent in de terminal of VS Code
  • Cursor — een op AI gerichte fork van VS Code
Aanbeveling

Voor de oefeningen in deze les volstaat een online taalmodel. Gebruik de startprompts als vertrekpunt voor een gesprek: lees het voorstel, voer het in kleine stappen uit en stel bij waar nodig. Het doel is niet dat de AI de oefening van je overneemt, maar dat ze je helpt sneller van een inhoudelijk idee naar een controleerbare analyse te gaan.

De prompts in deze les zijn bewust in het Engels geschreven. De meeste AI-assistenten verwerken technische instructies en Engelstalige bibliotheekterminologie daarin doorgaans consistenter. Je kan de uitleg of resultaten nog steeds in het Nederlands laten formuleren.

1.4 Samenwerken met een AI-assistent

Een goede samenwerking draait minder om de ene “perfecte prompt” dan om duidelijke context, kleine controleerbare stappen en kritisch bijsturen. Je hoeft niet alles vooraf vast te leggen: begin met wat je weet en verfijn de opdracht terwijl je meer over het probleem leert.

Begin bij het probleem, niet bij de code

Beschrijf eerst wat je wil onderzoeken en waarom. Vermeld relevante context, zoals de betekenis van de doelvariabele, belangrijke kolommen en de soort fout die in de toepassing het zwaarst weegt.

Slechte prompt Goede prompt
“Write machine-learning code.” “I want to predict which Titanic passengers survived and understand the errors made by the model. First propose a suitable approach and evaluation metrics. Briefly explain your choices before writing code.”
“Make a graph.” “Create a graph that helps me assess whether the decision tree is overfitting. Explain what I should compare in the graph.”

Geef richting waar die ertoe doet

Leg beperkingen vast die belangrijk zijn voor het leerdoel of de reproduceerbaarheid, bijvoorbeeld:

  • gebruik een train-, validatie- en testset zonder datalek;
  • gebruik random_state=42 zodat het resultaat reproduceerbaar is;
  • begin met een eenvoudig basismodel;
  • rapporteer metrics die bij het probleem passen.

Je hoeft niet altijd zelf een package of model te kiezen. Als die keuze deel is van de oefening, kan je de assistent eerst twee of drie opties laten vergelijken. Schrijf alleen een specifieke bibliotheek voor wanneer je daarmee wil oefenen of wanneer iedereen dezelfde reproduceerbare aanpak moet volgen.

Werk plan-gebaseerd en in controleerbare stappen

Laat niet meteen een volledige analyse genereren. Vraag de assistent eerst om het probleem op te delen, zonder al code te schrijven. Een bruikbare toevoeging aan een startprompt is:

“First propose a short plan with a clear purpose and expected output for each step. Do not write code yet. Wait for me to review the plan before implementing the first step.”

Controleer dat het plan de datasplitsing, een eenvoudige baseline, passende evaluatie en een eenmalige finale test bevat. Vraag om aanpassingen wanneer een stap onduidelijk is of datalek kan veroorzaken. Voer het plan daarna als een gesprek uit:

  1. Laat de assistent alleen de eerstvolgende stap implementeren.
  2. Voer de code zelf uit en bekijk data, waarschuwingen en uitvoer.
  3. Vraag wat de uitkomst betekent en of ze overeenkomt met de verwachting.
  4. Corrigeer eventuele problemen voordat je de volgende stap laat uitvoeren.
  5. Herhaal dit proces tot de validatie en interpretatie afgerond zijn.
  6. Gebruik de testset pas aan het einde en verander het model daarna niet meer.

De student bewaakt dus het plan en beslist wanneer de analyse verdergaat. Deel relevante uitvoer of een minimale foutmelding met de assistent, maar laat een geslaagde uitvoering nooit automatisch doorgaan voor een inhoudelijk correct resultaat.

Vraag om uitleg, alternatieven en kritiek

Nuttige vervolgvragen zijn bijvoorbeeld:

  • “What assumptions does this approach make?”
  • “Which simple baseline should I compare this with?”
  • “Where could data leakage occur in this workflow?”
  • “The graph has no axis labels. Add clear labels.”
  • “Which observation supports the conclusion that the model is overfitting?”
  • “Explain the confusion matrix in the context of the Titanic dataset.”
  • “Why is cross-entropy commonly used instead of MSE for classification?”
  • “Explain the Gini impurity used by scikit-learn to split decision trees.”
Jij blijft verantwoordelijk

AI-assistenten kunnen overtuigend klinkende maar foutieve code, verklaringen en referenties produceren. Controleer daarom altijd:

  • Werkt de code in een verse notebook?
  • Is er datalek? Transformaties zoals imputatie en normalisatie moeten op de trainset worden geleerd.
  • Wordt de testset maar eenmaal gebruikt, na alle modelkeuzes?
  • Past de evaluatiemetriek bij de toepassing? Accuracy alleen is bijvoorbeeld misleidend bij zeldzame defecten.
  • Volgt de conclusie werkelijk uit de analyse? Een voorspellend verband is nog geen causaal effect.
  • Zijn functies en parameters actueel? Controleer twijfelgevallen in de officiële documentatie.

Deel bovendien geen vertrouwelijke bedrijfsdata, persoonsgegevens, wachtwoorden, API-sleutels of andere gevoelige informatie met een publieke AI-dienst. Verwijder gevoelige inhoud uit foutmeldingen en deel alleen het minimale voorbeeld dat nodig is om het probleem te begrijpen.


2 Lineaire regressie: modelcomplexiteit in de praktijk

2.1 Dataset: California Housing

We werken in deze sectie met de California Housing-dataset, een klassieke dataset uit 1990 met gegevens over 20.640 geografische block groups in Californië. De taak is een regressieprobleem: voorspel de mediane huiswaarde (in honderdduizenden dollar) op basis van demografische en geografische kenmerken.

Kenmerk Beschrijving
MedInc Mediaan inkomen per blok (in tienduizenden dollar)
HouseAge Mediane leeftijd van de huizen in het blok
AveRooms Gemiddeld aantal kamers per huishouden
AveBedrms Gemiddeld aantal slaapkamers per huishouden
Population Bevolking van het blok
AveOccup Gemiddelde bezettingsgraad
Latitude Breedtegraad van het blok
Longitude Lengtegraad van het blok
MedHouseVal Doelvariabele: mediane huiswaarde (afgekapt op ongeveer 5)

De dataset kan met fetch_california_housing() worden geladen. Bij het eerste gebruik downloadt scikit-learn de data; daarna wordt ze lokaal gecachet.

2.2 Theoretisch concept: modelcomplexiteit en overfitting

We gebruiken deze sectie om het concept van modelcomplexiteit uit les 2 te illustreren. Door polynomiale regressie toe te passen met toenemende graad — van een rechte lijn tot een sterk kronkelende curve — onderzoeken we de overgang van underfitting naar overfitting.

  • Een polynoom van graad 1 is een rechte lijn. Als de werkelijke relatie kromgelijnd is, kan dit model underfitten: zowel de trainings- als de validatiefout blijven relatief hoog.
  • Bij een hogere graad wordt het model flexibeler. De trainingsfout kan verder dalen, maar het model kan ook toevallige patronen uit de trainingsdata volgen. De validatiefout stijgt dan opnieuw.
  • We kiezen de graad met de laagste validatiefout. De testset blijft tijdens deze keuze volledig buiten beeld en wordt slechts één keer gebruikt voor de eindevaluatie.
Een echte dataset geeft niet altijd een perfecte U

Met ruim 20.000 observaties en slechts één invoerkenmerk is zelfs een vrij flexibel polynoom moeilijk te overfitten. Daarom gebruiken we voor de hoofdfiguur bewust een reproduceerbare steekproef van 400 observaties. Zo wordt het effect van modelcomplexiteit beter zichtbaar. Achteraf herhalen we de oefening met meer data: de verwachting is dat het verschil tussen training en validatie kleiner wordt.

De curve hoeft niet exact U-vormig of glad te zijn. Dat is geen fout, maar een verschil tussen een theoretisch schema en echte, ruisende data.

2.3 Training, validatie en test

We gebruiken de termen in deze les als volgt:

  1. Training: de observaties waarop de modelcoëfficiënten worden geschat.
  2. Validatie: ongeziene observaties waarmee we de polynoomgraad kiezen. We gebruiken hiervoor 5-voudige cross-validatie.
  3. Test: een aparte hold-outset die pas na alle keuzes wordt gebruikt voor één finale prestatiemeting.

Eerst zetten we 20% van de volledige dataset opzij als testset. Uit de overige 80% trekken we 400 observaties voor de oefening. Binnen die ontwikkelsteekproef wisselen de observaties tijdens cross-validatie tussen training en validatie. Nadat de beste graad gekozen is, trainen we dat model opnieuw op alle 400 observaties en evalueren we het één keer op de testset.

2.4 Python-ecosysteem: scikit-learn

Voor lineaire en polynomiale regressie is scikit-learn de standaardkeuze. De relevante klassen:

Klasse Functie
LinearRegression Gewone kleinste kwadraten (OLS)
PolynomialFeatures Transformeert invoerkenmerken naar polynomiale termen
StandardScaler Brengt kenmerken op een vergelijkbare schaal en verbetert de numerieke stabiliteit
Pipeline Koppelt transformaties en een model samen
train_test_split Splitst de dataset in train- en testset
cross_validate Berekent trainings- en validatiescores via cross-validatie
mean_squared_error Berekent de MSE
Ridge, Lasso Geregulariseerde varianten van lineaire regressie

Een typische Pipeline voor polynomiale regressie van graad \(d\):

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.linear_model import LinearRegression

model = Pipeline([
    ("scale_x", StandardScaler()),
    ("poly", PolynomialFeatures(degree=d, include_bias=False)),
    ("scale_poly", StandardScaler()),
    ("linreg", LinearRegression())
])

De volledige pipeline wordt binnen elke cross-validatiefold opnieuw gefit. Daardoor worden ook de schalingsparameters uitsluitend uit het trainingsdeel van die fold geleerd en ontstaat geen datalek.

2.5 Startprompt

Kopieer de onderstaande prompt naar je AI-assistent:

Prompt: polynomial regression on California Housing
Use scikit-learn and the California Housing dataset to investigate model
complexity in polynomial regression. Predict MedHouseVal from MedInc. Reserve
20% of the complete dataset as an untouched test set, then draw a reproducible
sample of 400 observations from the remaining development data so that
overfitting has a chance to become visible.

Compare polynomial degrees 1 through 12 using five-fold cross-validation. Keep
all scaling and polynomial transformations inside a Pipeline to avoid leakage
and numerical problems. Use training and validation MSE to select the degree;
do not inspect the test set during this process.

The analysis should make the fitted curves and the training-versus-validation
error curve understandable. After selecting the degree, fit the final model on
the 400 development observations and use the test set once to report MSE and R².
Discuss whether a U-shape is actually visible rather than assuming that it must
be present.

First propose a short plan with the purpose and expected output of each step.
Do not write code yet. Wait for me to review the plan before implementing the
first step.

2.6 Verder verkennen

  • Meer data gebruiken: herhaal de validatiecurve met 2.000 observaties en daarna met alle ontwikkeldata. Onderzoek of de kloof tussen training en validatie kleiner wordt. Dit illustreert hoe meer data de variantie van een flexibel model kan verminderen.
  • Ridge- en Lasso-regressie: vervang LinearRegression door Ridge(alpha=1.0) en vergelijk de resultaten bij hoge polynoomgraad. Vraag je AI-assistent om te illustreren hoe de regularisatiesterkte alpha de coëfficiënten afvlakt.
  • Alle kenmerken gebruiken: gebruik alle 8 kenmerken in plaats van enkel MedInc. Merk op dat polynomiale expansie dan tot een explosief groot aantal termen leidt — dit is de vloek van dimensionaliteit in de praktijk.
  • Geografische visualisatie: California Housing bevat Latitude en Longitude. Vraag je AI-assistent om een geografische scatter te maken waarbij de kleur de huisprijs aangeeft. Je zal de kustlijn van Californië duidelijk herkennen.
  • Hyperparameteroptimalisatie: vervang de handmatige lus door GridSearchCV. Laat de testset opnieuw volledig onaangeroerd tot de beste graad gekozen en het finale model getraind is.

3 Neurale netwerken: leren en overfitting zichtbaar maken

3.1 Dataset: Fashion-MNIST

De Fashion-MNIST-dataset bevat 70.000 kleine grijswaardenafbeeldingen van kledingstukken uit 10 productcategorieën, zoals T-shirts, broeken, jurken, sneakers en tassen. Elke afbeelding bestaat uit 28×28 pixels. De taak is een meerklassen-classificatieprobleem: voorspel de productcategorie op basis van de afbeelding.

Fashion-MNIST is geschikt voor deze oefening omdat:

  • de invoer en voorspelling onmiddellijk visueel te begrijpen zijn;
  • sommige categorieën sterk op elkaar lijken, waardoor de fouten inhoudelijk interessant zijn;
  • beeldclassificatie herkenbaar is als bouwsteen voor toepassingen zoals productherkenning en visuele kwaliteitscontrole;
  • een compact netwerk snel kan trainen zonder gespecialiseerde hardware.

De dataset is wel een onderwijsbenchmark, geen volwaardig industrieel beeldprobleem. Echte productbeelden hebben onder meer variërende belichting, achtergrond, camerahoek en beeldkwaliteit.

Fashion-MNIST bevat 60.000 ontwikkelafbeeldingen en 10.000 testafbeeldingen. Keras levert deze oorspronkelijke splitsing rechtstreeks mee via keras.datasets.fashion_mnist. We splitsen alleen de 60.000 ontwikkelafbeeldingen verder op in training en validatie; de officiële testset blijft onaangeroerd tot de finale evaluatie.

3.2 Theoretisch concept: leren en overfitting doorheen de tijd

In les 2 bespraken we dat een model met veel capaciteit niet alleen het onderliggende patroon, maar ook toevalligheden in de trainingsdata kan leren. We maken dit zichtbaar door een compact en een groter neuraal netwerk te vergelijken.

Tijdens het trainen houdt Keras na iedere epoch twee verliezen bij:

  • Trainingsverlies: berekend op de observaties waarmee de gewichten worden aangepast.
  • Validatieverlies: berekend op aparte observaties die niet voor de gewichtsupdates worden gebruikt.

In het begin dalen doorgaans beide. Wanneer het trainingsverlies blijft dalen terwijl het validatieverlies stagneert of stijgt, ontstaat een generalization gap: het model past steeds beter bij de trainingsdata, maar niet bij nieuwe data. Dat is empirisch bewijs van overfitting. De testset is niet nodig om dit vast te stellen en wordt pas gebruikt nadat we onze keuzes hebben gemaakt.

Overfitting zichtbaar maken

Met alle 60.000 ontwikkelafbeeldingen kan zelfs het grotere netwerk behoorlijk goed generaliseren. Gebruik daarom voor de hoofdvergelijking een beperkte, gestratificeerde steekproef uit de ontwikkeldata. Dat versnelt de oefening en maakt het effect van modelcapaciteit duidelijker. De precieze omvang en architecturen hoef je niet vooraf blind vast te leggen: motiveer de keuze en pas ze aan wanneer de leercurven het bedoelde verschil niet tonen.

3.3 Python-ecosysteem: Keras

Voor deze oefening gebruiken we Keras met TensorFlow als backend. Keras is hier handiger dan MLPClassifier, omdat model.fit() na iedere epoch zowel het trainings- als validatieverlies bewaart in een History-object. Daardoor kunnen we de twee leercurven rechtstreeks vergelijken.

De belangrijkste bouwstenen zijn:

Onderdeel Functie
keras.datasets.fashion_mnist Laadt de afbeeldingen, labels en officiële testset
keras.Sequential Bouwt een netwerk als opeenvolging van lagen
Flatten en Dense Zetten het beeld om naar een vector en voeren de classificatie uit
model.fit(..., validation_data=...) Traint het model en bewaart de leercurven
History.history Bevat onder meer loss en val_loss per epoch

In een lokale omgeving kan TensorFlow worden toegevoegd met uv add tensorflow. In Google Colab is het doorgaans al beschikbaar.

3.4 Startprompt

Prompt: neural networks on Fashion-MNIST
Use Keras to compare a compact dense neural network with a substantially larger
one on Fashion-MNIST. The goal is to investigate how model capacity affects
training and validation loss and when overfitting becomes visible.

Use a limited, reproducible and stratified sample from the official development
data so the exercise remains quick. Keep the official test set completely
separate until all choices have been made. Choose and motivate suitable
architectures, preprocessing, loss function, optimizer and number of epochs.

Visualize training and validation loss per epoch for both models. Use these
curves to discuss which model generalizes better and when overfitting may begin.
Then evaluate only the selected model once on the test set. Show a few
predictions and use a confusion matrix to investigate which clothing categories
the model confuses most often.

Work in clear steps, briefly explain the important choices, and point out any
limitations or unexpected results. Do not claim overfitting unless the learning
curves provide evidence for it.

3.5 Verder verkennen

  • Meer trainingsdata: herhaal de vergelijking met een steeds grotere steekproef. Onderzoek hoe de generalization gap en testprestatie veranderen.
  • Early stopping: stop automatisch wanneer het validatieverlies niet meer verbetert en herstel de gewichten van de beste epoch. Vergelijk het gekozen stoppunt met de oorspronkelijke leercurve.
  • Regularisatie: voeg dropout of gewichtsregularisatie toe aan het grotere netwerk en onderzoek of het validatieverlies verbetert.
  • Convolutioneel netwerk (CNN): vervang het dense netwerk door een eenvoudig CNN. Een CNN benut de ruimtelijke structuur van afbeeldingen en is daardoor een natuurlijker model voor beeldclassificatie.
  • Fouten inspecteren: bekijk voorbeelden uit de meest verwarde klassen en formuleer hypotheses over waarom juist deze afbeeldingen moeilijk zijn.

4 Beslissingsbomen: interpreteerbaar leren op de Titanic

4.1 Dataset: Titanic

De Titanic-dataset beschrijft 891 passagiers van de RMS Titanic, afkomstig van de bekende Kaggle-competitie Titanic: Machine Learning from Disaster. De taak is een binair classificatieprobleem: voorspel wie de ramp overleefde.

Kenmerk Beschrijving
pclass Reisklasse (1, 2 of 3)
sex Geslacht (male / female)
age Leeftijd (bevat ontbrekende waarden)
sibsp Aantal broers/zussen of echtgenoten aan boord
parch Aantal ouders of kinderen aan boord
fare Betaald tarief
survived Doelvariabele: overleefde (1) of niet (0)

Een enkelvoudige, voldoende ondiepe beslissingsboom is hier aantrekkelijk omdat de geleerde regels direct leesbaar zijn: “Was de passagier een vrouw in eerste of tweede klasse? Dan was de overlevingskans hoog.” Voor één voorspelling kunnen we het gevolgde pad van wortel tot blad inspecteren.

Een random forest combineert daarentegen de voorspellingen van vele verschillende bomen. Dat levert vaak stabielere en betere voorspellingen op, maar er bestaat geen enkele boom die het volledige model samenvat. Een forest kan globale informatie zoals feature importances geven, maar is niet interpreteerbaar in dezelfde directe betekenis als één kleine boom. Deze oefening illustreert dus ook de afweging tussen voorspellende prestatie en uitlegbaarheid.

4.2 Theoretisch concept: de confusion matrix in de praktijk

In les 2 introduceerden we de confusion matrix als evaluatietool voor classificatiemodellen. Op de Titanic-dataset krijgt dit een concrete betekenis:

Voorspeld: Niet overleefd Voorspeld: Overleefd
Werkelijk: Niet overleefd True Negative (TN) — correct False Positive (FP) — niet-overlevende als overlevende voorspeld
Werkelijk: Overleefd False Negative (FN) — overlevende gemist True Positive (TP) — correct

Hier definiëren we overleven als de positieve klasse. Precision beantwoordt dan de vraag welk aandeel van de voorspelde overlevenden werkelijk overleefde; recall geeft aan welk aandeel van alle werkelijke overlevenden werd gevonden. Wanneer we de andere klasse als positief kiezen, berekenen we andere precision- en recallwaarden — ze worden niet eenvoudigweg omgewisseld. In een kwaliteitscontrole-context is de analogie direct: zoveel mogelijk defecte producten detecteren versus zo weinig mogelijk correcte producten onterecht afkeuren. De domeincontext bepaalt welke fout het zwaarst weegt.

4.3 Python-ecosysteem: scikit-learn

Klasse Functie
DecisionTreeClassifier Enkelvoudige beslissingsboom
RandomForestClassifier Ensemble van beslissingsbomen (bagging)
SimpleImputer Leert vervangwaarden voor ontbrekende gegevens uit de trainingsdata
ColumnTransformer, Pipeline Combineren preprocessing en model zonder datalek
plot_tree Visualiseer de beslissingsboom
confusion_matrix Bereken de confusion matrix
classification_report Druk precisie, recall en F1-score af

De Titanic-dataset kan via seaborn.load_dataset('titanic') worden geladen. Bij het eerste gebruik wordt de data via internet opgehaald; daarna kan seaborn een lokale kopie gebruiken.

4.4 Startprompt

Prompt: decision tree and random forest on Titanic
Write Python code that trains a decision tree and a random forest on the Titanic
dataset to predict passenger survival. Use the features pclass, sex, age, sibsp,
parch and fare.

Start with a stratified train/test split and keep the test set completely
untouched until the final evaluation. On the training data only, use
cross-validation to compare a shallow decision tree with a random forest and, if
needed, to tune hyperparameters.

Impute missing numerical values using medians learned exclusively inside each
training fold, and encode categorical features inside the same workflow. Prefer
a scikit-learn Pipeline so the same preprocessing is applied correctly to new
data without leakage. Do not remove observations merely because age is missing.

After choosing the model settings from the cross-validation results, fit both
models on the full training data. Only then evaluate them once on the test set.
Report accuracy and, for the survived class, precision, recall and F1-score;
show the test-set confusion matrices for both models. Visualize the individual
tree in a readable form, interpret the errors in the context of the passengers,
and briefly discuss why the individual tree is more directly interpretable than
the random forest.

4.5 Verder verkennen

  • Gradient boosting: vervang de random forest door GradientBoostingClassifier of — na uv add xgboost — door XGBClassifier. Zulke boostingmethoden zijn vaak sterke kandidaten voor gestructureerde tabeldata.
  • Feature engineering: voeg nieuwe kenmerken toe, bv. FamilySize = sibsp + parch + 1, of haal de titel (Mr., Mrs., Miss., Master…) uit de naamkolom. Onderzoek via cross-validatie of dit werkelijk helpt.
  • Hyperparameteroptimalisatie: gebruik GridSearchCV om de optimale combinatie van max_depth en n_estimators te vinden via 5-voudige cross-validatie.

5 Bayesiaanse inferentie: een heteroscedastisch regressiemodel met PyMC

5.1 Dataset: restaurantfooien (Tips)

De tips-dataset uit seaborn bevat 244 restaurantbetalingen met informatie over het rekenbedrag (total_bill) en de fooi (tip). De taak is een regressieprobleem: voorspel de hoogte van de fooi gegeven het rekenbedrag.

De scatterplot suggereert een eigenschap die ook in industriële meetdata vaak voorkomt: heteroscedasticiteit — de spreiding lijkt toe te nemen naarmate het rekenbedrag stijgt. Een klassiek lineair regressiemodel veronderstelt een constante variantie. We bouwen hier een model dat niet alleen het gemiddelde, maar ook de spreiding expliciet als functie van de invoer modelleert. Of de data werkelijk voldoende bewijs voor een toenemende spreiding bevat, is een vraag die het model moet helpen beantwoorden.

5.2 Theoretisch concept: een heteroscedastisch Bayesiaans model

Het model

We herschalen het rekenbedrag eerst naar het interval \([0,1]\):

\[\tilde{x} = \frac{x - \min(x)}{\max(x)-\min(x)}\]

Vervolgens modelleren we de fooi \(y\) als een normale verdeling waarvan zowel het gemiddelde als de standaardafwijking lineair afhangen van \(\tilde{x}\):

\[y \sim \mathcal{N}\!\bigl(\mu(x),\; \sigma(x)\bigr)\]

met

\[\mu(x) = \alpha + \beta \tilde{x}, \qquad \sigma(x) = \sigma_0 + \sigma_1 \tilde{x}\]

Voor de twee schaalparameters gebruiken we half-normale priors:

\[\sigma_0 \sim \operatorname{HalfNormal}(s_0), \qquad \sigma_1 \sim \operatorname{HalfNormal}(s_1)\]

Een half-normale verdeling is het positieve deel van een normale verdeling. Daardoor zijn \(\sigma_0\) en \(\sigma_1\) niet-negatief en blijft \(\sigma(x)\) over het volledige bereik positief. De parametrisatie heeft bovendien een directe interpretatie:

  • \(\sigma_0\) is de standaardafwijking bij het kleinste rekenbedrag;
  • \(\sigma_1\) is de bijkomende standaardafwijking over de stap van het kleinste naar het grootste rekenbedrag.

Omdat \(\sigma_1 \geq 0\) veronderstelt dit model dat de spreiding gelijk blijft of stijgt. Dat is een inhoudelijke aanname, geen conclusie die automatisch uit de data volgt.

Een positieve schaalfunctie in de industrie

In metrologie en analytische chemie groeit de absolute meetonzekerheid vaak mee met de gemeten grootheid. Een positieve lineaire schaalfunctie is een eenvoudige eerste benadering voor kalibratie-onzekerheid, sensorvalidatie of tolerantieanalyse. Ze is niet universeel: bij een ander proces kan de onzekerheid constant, dalend of niet-lineair zijn. Een plot en posterior-predictieve controle blijven daarom noodzakelijk.

Bayesiaans leren: prior, likelihood en posterior

We schatten de vier parameters \((\alpha, \beta, \sigma_0, \sigma_1)\) via Bayesiaanse inferentie, de regel van Bayes uit les 2:

\[P(\alpha, \beta, \sigma_0, \sigma_1 \mid \text{data}) \propto \underbrace{P(\text{data} \mid \alpha, \beta, \sigma_0, \sigma_1)}_{\text{likelihood}} \cdot \underbrace{P(\alpha, \beta, \sigma_0, \sigma_1)}_{\text{prior}}\]

  • Prior: onze aannames vóór het zien van de data — bijvoorbeeld welke fooien en spreidingen op deze schaal plausibel zijn.
  • Likelihood: de kans op de waargenomen fooien gegeven een stel parameterwaarden — bepaald door de normale verdeling in ons model.
  • Posterior: onze bijgewerkte kennis na het zien van de data.

Het resultaat is geen puntschatting maar een gezamenlijke posterior-verdeling over alle vier parameters. Daaruit kunnen we geloofwaardigheidsintervallen afleiden en onze onzekerheid over voorspellingen propageren.

Samplen via MCMC

De posterior-verdeling heeft geen analytische gesloten vorm voor dit model. PyMC benadert ze via MCMC (Markov Chain Monte Carlo): een algoritmische methode die duizenden steekproeven trekt uit de posterior, zodat we de volledige verdeling numeriek kunnen beschrijven en visualiseren.

5.3 Python-ecosysteem: PyMC en ArviZ

Bibliotheek Functie
pymc Specificatie van het probabilistisch model en MCMC-sampling
arviz Visualisatie en samenvatting van posterior-verdelingen
pytensor Numerieke backend van PyMC (automatisch mee geïnstalleerd)

Installeer via:

uv add pymc arviz

Kernconcepten in PyMC:

  • pm.Model() — contextmanager die het probabilistisch model definieert.
  • pm.Normal(name, mu, sigma) — normale prior of likelihood.
  • pm.HalfNormal(name, sigma) — positieve prior voor een schaalparameter.
  • pm.sample(draws, tune) — voert MCMC-sampling uit en retourneert een InferenceData-object.
  • pm.sample_prior_predictive() — controleert welke data de priors vóór het fitten plausibel maken.
  • pm.sample_posterior_predictive() — genereert voorspellingen waarin ook parameteronzekerheid wordt meegenomen.
  • az.summary(trace) — druk posterior-gemiddelden en HDI-intervallen af.
  • az.plot_trace() — helpt sampling en convergentie visueel beoordelen.

5.4 Startprompt

Prompt: heteroscedastic regression on the Tips dataset
Use PyMC to fit a heteroscedastic Bayesian regression model to the seaborn Tips
dataset. Predict tip from total_bill and rescale total_bill to the interval
[0, 1]. Use the following model:

    tip ~ Normal(mu(x), sigma(x))
    mu(x)    = alpha + beta * x_scaled
    sigma(x) = sigma_0 + sigma_1 * x_scaled

Use sensible normal priors for alpha and beta and half-normal priors for sigma_0
and sigma_1. Choose their scales based on plausible tips and briefly justify
them. Use prior-predictive simulation to check that these priors imply reasonable
data before fitting the model.

Sample the posterior using MCMC. Summarize and interpret all four parameters,
and check convergence using R-hat, effective sample size, trace plots and the
number of divergences. Explain what the posterior of sigma_1 says about changing
variability, while recognizing that its half-normal prior assumes variability
cannot decrease.

Use posterior-predictive draws to visualize the fitted relationship and its
uncertainty and to assess whether the model reproduces the important patterns in
the observed data. Do not construct a "posterior-predictive" interval merely by
plugging posterior mean parameters into mu ± sigma. Choose a clear plot layout
yourself and discuss any model limitations or sampling problems you find.

5.5 Verder verkennen

  • Vergelijking met een homoscedastisch model: fit een tweede PyMC-model met constante \(\sigma\) en vergelijk beide modellen met posterior-predictieve controles. Ga na of het complexere model een zichtbaar relevant patroon opvangt.
  • Gevoeligheid voor priors: probeer redelijk bredere en smallere half-normale priors. Onderzoek welke conclusies robuust blijven en welke sterk door de prior worden beïnvloed.
  • Dalende spreiding toelaten: gebruik een normale helling binnen een softplus-transformatie wanneer de standaardafwijking zowel mag stijgen als dalen. Vergelijk de extra flexibiliteit met de interpreteerbaarheid van het lineaire positieve model.
  • Meer predictoren: voeg size (tafelgrootte) en time (lunch / dinner) toe als extra predictoren. Bepaal vooraf of ze het gemiddelde, de spreiding of beide plausibel beïnvloeden.
  • Gamma-likelihood: voor strikt positieve doelgroepen zoals fooien is een Gamma-verdeling soms een beter alternatief voor de normale verdeling. De parametrisering tip ~ Gamma(mu=mu(x), sigma=sigma(x)) bakt positiviteit in op het niveau van de likelihood zelf.

6 Studiewijzer

De inhoud van deze les is niet te kennen voor het examen. De les zal hopelijk wel de theoretische concepten uit de vorige lessen helpen illustreren in de praktijk.