Validatie¶
Krijg je een foutmelding? Spring direct naar Een validatiefout oplossen.
De pipeline voert vóór de ETL automatisch een datakwaliteitscontrole uit op alle ruwe inputbestanden. Dit voorkomt dat fouten in de brondata pas later in de pipeline of in de output zichtbaar worden.
Gebruik --noetl om zowel de ETL als de validatie over te slaan (alleen als de data eerder al gevalideerd is).
Bestandsoverzicht bij opstart¶
Bij het starten van de validatie toont de pipeline een overzichtstabel met de status van alle verwachte inputbestanden. Dit helpt je snel te zien wat aanwezig is, wat ontbreekt, en welke run-modi (-d) beschikbaar zijn.
==== Valideren van ruwe inputdata ====
Bestand Status Nodig voor
──────────────────────────────────────────────────────────────────
data/input_raw/telbestanden ✓ -d cumulative, -d both
data/input_raw/individuele_aanmelddata.csv ✗ -d individual, -d both
data/input_raw/oktober_bestand.xlsx ✓ studentaantallen (optioneel, telbestand studenten)
Beschikbare modi:
-d cumulative ✓
-d individual ✗ individuele_aanmelddata.csv ontbreekt
-d both ✗ individuele_aanmelddata.csv ontbreekt
De ✓ en ✗ symbolen worden in kleur weergegeven (groen/rood) als de terminal dat ondersteunt. Als alle bestanden aanwezig zijn, wordt de modi-sectie vervangen door een compacte bevestiging.
Drie typen bevindingen¶
| Type | Gedrag | Wanneer gebruiken |
|---|---|---|
| Hard error | Pipeline stopt direct | Data is structureel onbruikbaar (ontbrekende kolommen, onleesbaar bestand) |
| Soft error | Pipeline vraagt om bevestiging | Data is twijfelachtig maar niet per se fout (onverwachte waarden, mogelijk verkeerd jaar) |
| Waarschuwing | Pipeline loopt door, melding in console | Automatisch gecorrigeerd, of niet-kritiek |
In geautomatiseerde runs (CI/CD) gebruik je --yes om de soft-error prompt te omzeilen.
Een validatiefout oplossen¶
Hard error — ontbrekende kolommen:
De kolomnaam in jouw bestand wijkt af van de kanonieke naam. Voeg een kolomnamen-mapping toe in configuration.json onder columns.individual of columns.oktober (de mapping voor het telbestand studenten).
Soft error — onverwacht collegejaar:
Controleer of het bestand het juiste studiejaar bevat. Als de afwijking verwacht is (bijv. historische data), kun je collegejaar_min_offset verhogen of met --yes doorgaan.
Soft error — ongeldige herkomstwaarden:
Jouw instelling gebruikt mogelijk "ONBEKEND" of een andere waarde. Voeg die toe aan validation.telbestand.herkomst_allowed in je configuratie.
Waarschuwing — witruimte gestript: De data wordt automatisch gecorrigeerd. Overweeg de brondata te corrigeren om dit te voorkomen.
Gevalideerde bestanden¶
Telbestanden (data/input_raw/telbestanden/)¶
| Controle | Type | Wat wordt gecheckt |
|---|---|---|
| Map bestaat | Hard error | data/input_raw/telbestanden/ moet bestaan |
| Bestanden aanwezig | Hard error | Minimaal één bestand dat matcht met telbestand_filename_patterns (default: telbestandY{jaar}W{week}.csv) |
| Verplichte kolommen | Hard error | Studiejaar, Isatcode, Groepeernaam, Aantal, meercode_V, Status, Herinschrijving, Herkomst |
| Weeknummer in bestandsnaam | Hard error | Weeknummer moet tussen 1 en 53 liggen |
| Collegejaar bereik | Soft error | Studiejaar buiten [huidig jaar − 15, huidig jaar + 2] |
| Herkomst geldige waarden | Soft error | Elke waarde in Herkomst moet N, E of R zijn |
| Herinschrijving geldige waarden | Soft error | Elke waarde moet J of N zijn |
| Aantal < 0 | Soft error | Negatieve aantallen zijn inhoudelijk onjuist |
Ontbrekende waarden Aantal |
Waarschuwing / Soft error | > 5% ontbrekend → waarschuwing; > 30% → soft error |
| Gaten tussen weken | Waarschuwing | Gat van > 2 weken binnen een jaar |
| Witruimte in categorische waarden | Waarschuwing | Automatisch gestript ("J " → "J") |
Individuele aanmelddata (data/input_raw/individuele_aanmelddata.csv)¶
| Controle | Type | Wat wordt gecheckt |
|---|---|---|
| Bestand bestaat | — | Wordt getoond in het bestandsoverzicht bij opstart |
| Verplichte kolommen | Hard error | Collegejaar, Croho, Inschrijfstatus, Datum Verzoek Inschr (via kolomnamen-mapping) |
| Ontbrekende waarden | Waarschuwing / Soft error | Per verplichte kolom, zelfde drempels als telbestanden |
Telbestand studenten (data/input_raw/oktober_bestand.xlsx)¶
Telbestand met studentaantallen, door de instelling zelf aangeleverd — zie Je data klaarzetten. De bestandsnaam heet historisch oktober_bestand.xlsx.
| Controle | Type | Wat wordt gecheckt |
|---|---|---|
| Bestand bestaat | — | Wordt getoond in het bestandsoverzicht bij opstart |
| Verplichte kolommen | Hard error | Collegejaar, Isatcode, Aantal eerstejaars croho, EER-NL-nietEER, Examentype code, Aantal Hoofdinschrijvingen (Isatcode is de joinsleutel met de vooraanmeldingen; Groepeernaam Croho is niet langer verplicht) |
| Collegejaar bereik | Soft error | Zelfde bereikcontrole als telbestanden |
| Ontbrekende waarden | Waarschuwing / Soft error | Per verplichte kolom |
Pre-prediction checks¶
Vóór elke modelrun voert de pipeline vier aanvullende checks uit op de cumulatieve vooraanmelddata. Ze draaien per (jaar, week)-combinatie, na ETL maar vóór de modellen.
Alleen actief als cumulatieve data beschikbaar is
De pre-prediction checks worden overgeslagen als de pipeline zonder cumulatieve data draait (individueel-enkel modus, -d i). In dat geval is er geen Gewogen vooraanmelders-kolom om te valideren.
| Check | Type | Wat wordt gecheckt |
|---|---|---|
| Decimaalintegriteit | Hard stop | Gewogen vooraanmelders bevat strings met komma's of niet-numerieke waarden |
| Lege dataset | Hard stop | Geen rijen aanwezig voor het gevraagde jaar+week |
| Trainingshistorie | Hard stop / waarschuwing | Geen historische collegejaren (Collegejaar < voorspeljaar) aanwezig om op te trainen |
| Historisch realisme | Hard stop / waarschuwing | Afwijking t.o.v. dezelfde week vorig jaar per opleiding/herkomst/examentype |
Trainingshistorie — waarom deze check bestaat¶
Het cumulatieve spoor leidt twee voorspellingen af uit historische collegejaren:
- het XGBoost-instroommodel (kolom
SARIMA_cumulative) traint opCollegejaar < voorspeljaar; - het ratio-model (kolom
Prognose_ratio) middelt de aanmelder/student-ratio over de drie jaren vóór het voorspeljaar.
Bevat de cumulatieve data alleen het voorspeljaar (bijv. een df_cum die per ongeluk op het huidige jaar is gefilterd), dan hebben beide modellen geen trainingsdata en geven ze voor élke opleiding NaN terug. De SARIMA-vooraanmeldforecast (Voorspelde vooraanmelders) heeft géén historie nodig en vult zich wél — daardoor oogt de output compleet terwijl er geen bruikbare instroomvoorspelling in zit. Dit faalde vroeger stil; de check maakt het nu expliciet.
| Situatie | Gedrag |
|---|---|
Geen enkel jaar < voorspeljaar aanwezig |
Hard stop — pipeline stopt (te omzeilen met --yes) |
| Minstens één historisch jaar aanwezig | Check slaagt stilzwijgend |
Oplossing
Voeg historische collegejaren toe aan de cumulatieve data (idealiter de drie jaren vóór het voorspeljaar) en verwerk opnieuw. Controleer bij in-memory gebruik dat df_cum niet op één jaar gefilterd is: sorted(df_cum["Collegejaar"].unique()).
In-memory API-pad waarschuwt in plaats van te stoppen
run_pipeline_from_dataframes draait altijd met --yes zodat een bibliotheekaanroep de aanroepende toepassing niet afbreekt: bij ontbrekende historie verschijnt daar een waarschuwing in plaats van een hard stop. De cumulatieve kolommen blijven dan NaN.
Historisch realisme — drempelwaarden¶
Vergelijking per (Croho groepeernaam, Herkomst, Examentype):
| Situatie | Gedrag |
|---|---|
Afwijking > max(25, 70% van vorig jaar) |
Hard stop — pipeline stopt |
Afwijking > max(15, 30% van vorig jaar) |
Waarschuwing — pipeline loopt door |
De absolute vloer (max(…)) voorkomt vals-positieven bij kleine opleidingen: een programma met 10 studenten vorig jaar en 18 dit jaar (80% relatief, 8 absoluut) triggert geen hard stop omdat de absolute drempel (25) niet gehaald wordt.
Numerus-fixus-opleidingen (examentype Bachelor) worden overgeslagen — hun aanmeldpatroon is beleidsmatig bepaald en niet vergelijkbaar met het historische patroon.
Als er geen vorig-jaar-data beschikbaar is (nieuwe opleiding), wordt de check stilzwijgend overgeslagen.
Hard stop omzeilen met --yes¶
De decimaalcheck en lege-dataset-check zijn nooit te omzeilen: corrupte of afwezige data heeft geen veilige fallback. De trainingshistorie- en historisch-realismecheck wél — gebruik --yes om een ontbrekende historie of extreme afwijking te accepteren en door te gaan:
Met --yes verschijnt een waarschuwing in de console maar stopt de pipeline niet. Gebruik dit bewust: een extreme afwijking kan duiden op een Studielink-probleem dat je niet wilt meenemen in de modeltraining.
Numerus-fixus-sleutels¶
Als een numerus-fixus-sleutel niet exact overeenkomt met een opleiding in je data, werd die vroeger stil genegeerd: de speciale numerus-fixus-behandeling (aparte regressor, capaciteitsplafond, aparte foutrapportage) greep dan ongemerkt niet aan, zonder foutmelding. Nu krijg je vóór de voorspelling een duidelijke melding als een sleutel uit numerus_fixus niet voorkomt in je opleidingen.
| Situatie | Gedrag |
|---|---|
| Sleutel matcht geen enkel geladen spoor | Hard stop — pipeline stopt (waarschijnlijk een typefout of verkeerd formaat) |
| Sleutel matcht wel het ene, maar niet het andere geladen spoor | Waarschuwing — bekende naam-versus-Isatcode-verschil tussen de twee sporen |
| Elke sleutel matcht alle geladen sporen | Check slaagt stilzwijgend |
Technische achtergrond
De check draait direct na het preprocessen op de genormaliseerde, gepreprocesste data, zodat het exacte dtype van de programmakolom (Croho groepeernaam) wordt gezien. Een niet-matchende sleutel leverde bij .isin/== simpelweg False op zonder foutmelding (issue #258); het gedeeltelijke-match-geval is de bekende namen-vs-Isatcodes-mismatch uit issue #238.
Oplossing
Gebruik voor het cumulatieve spoor de numerieke Isatcode als sleutel, voor het individuele spoor de leesbare opleidingsnaam — precies de waarde zoals die in de programmakolom van dat spoor staat. Zie numerus_fixus.
Post-prediction checks¶
Nadat het ensemble zijn voorspellingen heeft opgeleverd, krijg je nog twee informatieve checks. Ze stoppen de pipeline nooit — je ziet alleen een waarschuwing in de console als de uitkomst opvalt.
| Check | Wat wordt gecheckt |
|---|---|
| Trend-realisme YoY | Ensemble_prediction wijkt > 50% én > 20 absoluut af van Gewogen vooraanmelders dezelfde week vorig jaar |
| Trend-realisme WoW | Ensemble_prediction wijkt > 30% én > 15 absoluut af van de voorspelling van de vorige week |
| NF-cap overschrijding | Gesommeerde Ensemble_prediction per numerus-fixus-opleiding overschrijdt het geconfigureerde plafond |
Pre-master-rijen worden uitgesloten van de NF-cap-check: ze tellen niet mee als nieuwe eerstejaars.
De week-op-week-check slaat de eerste week van elke run over (geen vorige week beschikbaar) en week 39 (eerste week van het nieuwe aanmeldseizoen — de vorige week, 38, is het einde van het vorige seizoen en geen zinvolle referentie).
Alleen beschikbaar in combinatiemodus
De post-prediction checks zijn alleen actief als de pipeline wordt gestart met -d both of -d b. In cumulatief-enkel (-d c) of individueel-enkel (-d i) modus bestaat de Ensemble_prediction-kolom niet en worden de checks stilzwijgend overgeslagen.
Drempels aanpassen¶
De standaarddrempels voor NaN-percentages en jaarbereiken zijn instelbaar via configuration.json. Zie Configuratie — validation.