- Je scheidt promptvoorbeelden, ontwikkeling en eindtest op de juiste brongroep.
- Je berekent end-to-end- en groepsscores en een eenvoudig gepaard bootstrap-interval.
Een prompt haalt 100% accuracy op geldige antwoorden. Pas daarna blijkt dat de helft van alle antwoorden ongeldige JSON was. Een goede evaluatie (eval) maakt zulke fouten zichtbaar in plaats van ze uit de noemer te laten verdwijnen.
Leg vóór de meting gevallen, referenties, uitvoercontract en scores vast. Noteer bij echte modellen ook revisie, prompt, tokenizer, generatie-instellingen en herhalingen. Kies de variant op ontwikkeling; de eindtest komt pas nadat die keuze vaststaat.
1. Scheid gevallen op hun werkelijke bron
Twee verschillende vragen kunnen uit hetzelfde document komen. Als de ene een promptvoorbeeld is en de andere een testvraag, kan de evaluatie informatie uit de voorbeelden terugmeten. Gebruik daarom een brongroep als eenheid voor de splits.
rows = [
dict(id='e',group='g',
split='examples'),
dict(id='d',group='g',split='dev'),
dict(id='t',group='h',split='test')]
r = audit_eval_split(rows)
print(r['overlapping_groups'])
# {'g': ['dev', 'examples']}
print(r['missing_splits']) # []
De case-IDs zijn verschillend, maar brongroep g komt in twee splits voor. Maak audit_eval_split met counts, duplicate_ids, overlapping_groups en missing_splits. Het rapport verwijdert niets automatisch.
Een brongroep is iets anders dan een rapportagecategorie. Een document of gesprek hoort bij één split; een categorie zoals directe vraag mag juist in meerdere splits voorkomen. Verschillende bron-IDs kunnen nog steeds semantisch dezelfde bron verbergen, dus de metadata-audit vervangt geen inhoudelijke controle.
012. Rapporteer alle gevallen en alle categorieën
Neem vier directe vragen: alle uitvoer is geldig en drie antwoorden kloppen. Een vijfde vraag uit een kleine categorie geeft ongeldige uitvoer. Dan is validity 4/5=.8, totale accuracy 3/5=.6 en accuracy onder geldige uitvoer 3/4=.75.
Noem het totale aantal N, het aantal geldige antwoorden V en het aantal juiste antwoorden H. Deze twee accuracies beantwoorden verschillende vragen:
rows = [
dict(id=str(i),group='direct',
valid=True,correct=i<3)
for i in range(4)]
rows.append(dict(id='rare',group='rare',
valid=False,correct=False))
r = summarize_eval(rows)
overall = r['overall']
print(overall['validity']) # .8
print(overall['accuracy']) # .6
print(overall['accuracy_when_valid'])
# .75
print(r['macro_group_accuracy']) # .375
Maak summarize_eval met overall, groups en macro_group_accuracy. Iedere categorie krijgt haar eigen n en scores. De directe categorie haalt .75 en de kleine categorie nul; hun ongewogen gemiddelde is (.75+0)/2=.375.
De totale accuracy weegt iedere case even zwaar; macro weegt iedere categorie even zwaar. Geen van beide is altijd de juiste hoofdmaat. Bewaar groepsaantallen en de regel dat correct=True ook valid=True vereist; zonder geldige antwoorden is accuracy_when_valid None.
Acht directe vragen zijn goed. Verander het aantal moeilijke vragen en hun uitkomst; vergelijk de noemers.
- Accuracy over alle gevallen
- 80.0% 8 correct / 10 gevallen
- Accuracy bij geldige uitvoer
- 100.0% 8 correct / 8 geldig
- Geldig uitvoercontract
- 80.0% 8 geldig / 10 gevallen
- Macro per categorie
- 50.0% Iedere categorie telt even zwaar
Meer moeilijke gevallen veranderen de totale accuracy. Zolang de categorie-accuracies gelijk blijven, verandert macro niet.
3. Behoud de koppeling bij opnieuw trekken
Voor dezelfde zes gevallen scoort A tweemaal goed en B driemaal. Per geval is het verschil dᵢ gelijk aan correct(B) minus correct(A). In dit voorbeeld is die vector [0,−1,1,1,0,0], met gemiddelde 1/6.
Eén bootstrap-trekking kiest zes indices met teruglegging. De indices [2,2,3,0,4,5] leveren drie enen en drie nullen op: een nieuw gemiddelde .5. Dezelfde indices horen bij beide varianten.
import numpy as np
a = np.array([1,1,0,0,0,0],bool)
b = np.array([1,0,1,1,0,0],bool)
d = b.astype(float)-a.astype(float)
indices = [2,2,3,0,4,5]
print(d[indices].mean()) # .5
Herhaal dit en neem de 2,5e en 97,5e percentielen. Onze helper gebruikt een eenvoudig 95%-percentile-interval; dit is niet SciPy’s standaard BCa-methode. De seed maakt deze oefenmeting herhaalbaar.
r = paired_bootstrap(a,b,1000,7)
print(round(r['difference'],4)) # .1667
print(round(r['low'],4),
round(r['high'],4))
# -0.5 0.6667
Maak paired_bootstrap voor uitgelijnde booleaanse vectoren. Gebruik dezelfde getrokken indices, 100–5000 herhalingen en de opgegeven seed. Bij afhankelijke vragen moet je bijvoorbeeld complete brongroepen resamplen, omdat losse gevallen dan geen onafhankelijke eenheden zijn.
Een interval lost dataverschuiving, verkeerde labels of herhaald promptzoeken niet op. Met weinig data kan het ook misleidend smal zijn. Veranderen na het bekijken van testfouten vraagt voor een nieuwe onafhankelijke eindclaim om nieuwe testdata.
03Wat neem je mee?
- Brongroepen bewaken de split; categorieën maken verschillen zichtbaar.
- Ongeldige uitvoer blijft in de totale noemer.
- Gepaard resamplen bewaart welke antwoorden bij hetzelfde geval horen.
Hierna controleer je de beoordelaar die de uitkomsten van modellen vergelijkt.