Machine Learning Academy · Les

Voorspellingsverdelingen en betrouwbaarheidsscores monitoren

Cursisten loggen voorspellingskansen naar een tijdreeksopslag, plotten de voortschrijdende gemiddelde betrouwbaarheid en markeren wanneer de gemiddelde betrouwbaarheid onder een implementatiedrempel daalt.

Les 3 van 413 stappen

Voorspellingsverdelingen en betrouwbaarheidsscores monitoren is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Machine Learning Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Machine Learning Academy bevat in totaal 4 lessen.

Waarom voorspellingen monitoren en niet alleen invoer?

Monitoring van invoerkenmerken detecteert datadrift, maar vereist dat je elk kenmerk monitort. Monitoring van voorspellingen levert één geïntegreerd signaal: als een combinatie van veranderingen in de invoer ervoor zorgt dat het model andere uitvoer produceert, wordt dat zichtbaar in de voorspellingsverdeling — zelfs als geen afzonderlijk kenmerk de driftdrempel overschrijdt. Het monitoren van voorspellingen is aanvullend op het monitoren van invoer: het vangt op wat invoermonitoring mist door te kijken naar de geïntegreerde reactie van het model op alle invoer samen.

Voorspellingen in productie loggen

De basis van monitoring van voorspellingen is een voorspellingslogboek: de kenmerken, het voorspelde label, de voorspelde waarschijnlijkheden en het tijdstip van elk inferentieverzoek worden opgeslagen in een database of bestand. Dit logboek maakt retrospectieve analyse mogelijk wanneer drift of prestatieverlies wordt gedetecteerd. Ontwerp het schema zo dat het naast de details van de voorspelling ook de aanvraag-ID (om later te kunnen koppelen aan werkelijke labels), de modelversie en de latentie bevat.

import datetime
import json
import os
import torch
import torch.nn.functional as F

PREDICTION_LOG = '/tmp/prediction_log.jsonl'

def predict_and_log(features, model, model_version='v1.2.3'):
    import numpy as np
    with torch.no_grad():
        logits = model(torch.tensor(features, dtype=torch.float32).unsqueeze(0))
        probs = F.softmax(logits, dim=1).squeeze().numpy()
    pred_class = int(probs.argmax())
    confidence = float(probs.max())

    record = {
        'timestamp': datetime.datetime.utcnow().isoformat(),
        'model_version': model_version,
        'predicted_class': pred_class,
        'confidence': round(confidence, 4),
        'probabilities': probs.tolist()
    }
    with open(PREDICTION_LOG, 'a') as f:
        f.write(json.dumps(record) + '\n')
    return pred_class, confidence

Voortschrijdende gemiddelde betrouwbaarheidsscore

Het gemiddelde vertrouwen van voorspellingen is een van de gevoeligste vroege waarschuwingssignalen voor concept drift. Wanneer het model gegevens buiten de trainingsverdeling tegenkomt, worden de softmax-kansen gelijkmatiger over de klassen verdeeld (dichter bij een uniforme verdeling), waardoor de maximale kans afneemt. Zet het voortschrijdende gemiddelde vertrouwen uit tegen de tijd: een aanhoudende daling onder een implementatiedrempel (meestal ingesteld op het 5e percentiel van het kalibratievertrouwen) geeft aan dat het model onzeker wordt over invoer uit de productieomgeving.

import numpy as np
import pandas as pd

np.random.seed(42)

# Simulate confidence scores over 12 weeks
# First 6 weeks: healthy (high confidence)
week1to6 = np.random.beta(8, 2, 600)   # mean ~0.8
# Last 6 weeks: degrading (lower confidence)
week7to12 = np.random.beta(3, 3, 600)  # mean ~0.5

all_scores = np.concatenate([week1to6, week7to12])
dates = pd.date_range('2024-01-01', periods=len(all_scores), freq='h')

df = pd.DataFrame({'timestamp': dates, 'confidence': all_scores})
df['week'] = df['timestamp'].dt.isocalendar().week
weekly_mean = df.groupby('week')['confidence'].mean()

threshold = weekly_mean.iloc[:6].quantile(0.05)  # 5th percentile of healthy period
print(f'Alert threshold: {threshold:.4f}')
for week, mean_conf in weekly_mean.items():
    status = 'ALERT' if mean_conf < threshold else 'OK'
    print(f'Week {week}: mean confidence = {mean_conf:.4f} [{status}]')

Monitoring van de verdeling van voorspelde klassen

De verdeling van voorspelde klassen hoort in de loop van de tijd stabiel te blijven als het model en de gegevens uit de echte wereld goed op elkaar aansluiten. Een verschuiving in het voorspelde positieve percentage — bijvoorbeeld wanneer een binaire classificator tijdens de training in 30% van de gevallen positief voorspelt, maar in productie in slechts 5% — is een sterk signaal van drift. Controleer de verdeling van voorspelde klassen wekelijks en geef een waarschuwing wanneer het aandeel van een klasse meer dan een bepaalde drempel afwijkt van de trainingsbasislijn. Gebruik hiervoor een chi-kwadraattoets.

import numpy as np
from scipy.stats import chi2_contingency

# Baseline class distribution from training predictions
train_predictions = np.array([0, 1]).repeat([700, 300])  # 70% neg, 30% pos
np.random.shuffle(train_predictions)

# Current week production predictions (shifted distribution)
prod_predictions = np.random.choice([0, 1], p=[0.92, 0.08], size=500)

train_counts = [np.sum(train_predictions == 0), np.sum(train_predictions == 1)]
prod_counts  = [np.sum(prod_predictions == 0),  np.sum(prod_predictions == 1)]

chi2, p_val, _, _ = chi2_contingency([train_counts, prod_counts])
print(f'Train distribution: {train_counts[0]/len(train_predictions):.2%} neg, {train_counts[1]/len(train_predictions):.2%} pos')
print(f'Prod  distribution: {prod_counts[0]/len(prod_predictions):.2%} neg, {prod_counts[1]/len(prod_predictions):.2%} pos')
print(f'Chi-squared: {chi2:.2f}, p-value: {p_val:.4f}')
print('Prediction distribution drift:', p_val < 0.05)

Vertrouwenskalibratie: zijn de kansen betrouwbaar?

Kalibratie meet of de voorspelde kansen van een model overeenkomen met de werkelijke frequenties. Een perfect gekalibreerd model dat 80% vertrouwen voorspelt, hoort in 80% van de gevallen gelijk te hebben. Niet-gekalibreerde modellen — wat vaak voorkomt bij gradient boosting en deep learning — leveren kansen die te veel of te weinig vertrouwen uitdrukken. Controleer de kalibratie in de loop van de tijd met een betrouwbaarheidsdiagram: deel voorspellingen op basis van hun vertrouwen in intervallen in en vergelijk binnen elk interval de voorspelde nauwkeurigheid met de waargenomen nauwkeurigheid.

import numpy as np
from sklearn.calibration import calibration_curve

np.random.seed(42)
# Overconfident model: high probabilities but not that accurate
y_true = np.random.binomial(1, 0.6, 1000)
y_prob_uncalibrated = np.clip(
    np.random.beta(5, 2, 1000) * (y_true * 0.6 + 0.2), 0, 1
)

fraction_of_positives, mean_predicted = calibration_curve(
    y_true, y_prob_uncalibrated, n_bins=10
)

print('Bin | Predicted | Observed')
for pred, obs in zip(mean_predicted, fraction_of_positives):
    gap = abs(pred - obs)
    status = '*** MISCALIBRATED' if gap > 0.1 else 'OK'
    print(f'{pred:.2f} | {obs:.2f} {status}')

Verwachte kalibratiefout

De Expected Calibration Error (ECE) is één getal dat de kwaliteit van de kalibratie samenvat. Het is het gewogen gemiddelde van het verschil tussen het voorspelde vertrouwen en de waargenomen nauwkeurigheid over alle vertrouwensintervallen, waarbij elk interval wordt gewogen op basis van het aantal voorbeelden erin. Een ECE rond 0 betekent een uitstekende kalibratie; een ECE boven 0,05 verdient nader onderzoek; een ECE boven 0,1 betekent dat je de kansen van het model zonder herkalibratie niet zou moeten vertrouwen.

import numpy as np
from sklearn.calibration import calibration_curve

def expected_calibration_error(y_true, y_prob, n_bins=10):
    fraction_pos, mean_pred = calibration_curve(y_true, y_prob, n_bins=n_bins)
    bin_sizes = []
    bins = np.linspace(0, 1, n_bins + 1)
    for i in range(n_bins):
        in_bin = (y_prob >= bins[i]) & (y_prob < bins[i+1])
        bin_sizes.append(in_bin.sum())

    n = len(y_true)
    ece = sum(
        (bin_size / n) * abs(pred - obs)
        for bin_size, pred, obs in zip(bin_sizes[:len(mean_pred)],
                                        mean_pred, fraction_pos)
    )
    return round(ece, 4)

np.random.seed(42)
y_true = np.random.binomial(1, 0.5, 1000)
y_prob = np.random.beta(3, 3, 1000)
ece = expected_calibration_error(y_true, y_prob)
print(f'ECE: {ece}')
print('Calibration quality:', 'Good' if ece < 0.05 else 'Poor')

Verzoeken met weinig vertrouwen markeren

Markeer in productie verzoeken die onder een vertrouwensdrempel vallen voor beoordeling door een mens of afhandeling via een terugvaloptie. Dit is vooral belangrijk in domeinen met grote gevolgen: een kredietaanvraag met 51% voorspeld vertrouwen dat de aanvrager niet zal terugbetalen, hoort naar een menselijke kredietbeoordelaar te gaan in plaats van automatisch te worden afgewezen. Stel de drempel in op het punt waarop je organisatie onzekerheid kan verdragen en log alle gemarkeerde verzoeken in een beoordelingswachtrij, samen met de volledige kenmerkvector en voorspelling, zodat analisten ze kunnen inspecteren.

import datetime

CONFIDENCE_THRESHOLD = 0.75
REVIEW_QUEUE = []

def predict_with_human_review(request_id, features, model_func):
    pred_class, confidence = model_func(features)

    result = {
        'request_id': request_id,
        'predicted_class': pred_class,
        'confidence': confidence,
        'timestamp': datetime.datetime.utcnow().isoformat(),
        'needs_review': confidence < CONFIDENCE_THRESHOLD
    }

    if result['needs_review']:
        REVIEW_QUEUE.append({**result, 'features': features})
        print(f'Request {request_id} FLAGGED for review (conf={confidence:.2f})')
    else:
        print(f'Request {request_id} auto-decided: class={pred_class} (conf={confidence:.2f})')

    return result

Voorspellingen opslaan in een tijdreeksdatabase

Schrijf voor schaalbare monitoring voorspellingsrecords naar een tijdreeksopslag zoals PostgreSQL met een tijdstempelindex, InfluxDB of een clouddatawarehouse. Vraag aggregaten op (het gemiddelde vertrouwen per uur of per dag, de klassenverdeling) met SQL-vensterfuncties. Stel automatische dashboards in Grafana of een BI-hulpmiddel in die elk uur worden vernieuwd, zodat het team realtime inzicht heeft zonder handmatig monitoringscripts te schrijven.

import psycopg2
import json
from datetime import datetime

# Schema (run once):
# CREATE TABLE prediction_log (
#     id SERIAL PRIMARY KEY,
#     request_id TEXT,
#     model_version TEXT,
#     predicted_class INT,
#     confidence FLOAT,
#     probabilities JSONB,
#     timestamp TIMESTAMPTZ DEFAULT NOW()
# );

def log_prediction_to_db(conn, request_id, model_version, pred_class, confidence, probs):
    cur = conn.cursor()
    cur.execute(
        '''INSERT INTO prediction_log
           (request_id, model_version, predicted_class, confidence, probabilities)
           VALUES (%s, %s, %s, %s, %s)''',
        (request_id, model_version, pred_class, confidence, json.dumps(probs))
    )
    conn.commit()

print('DB logging function ready.')

Implementatiedrempels instellen op basis van kalibratie

Kies de vertrouwensdrempel voor implementatie op basis van kalibratiegegevens in plaats van intuïtie. Zet de ECE en nauwkeurigheid uit bij verschillende vertrouwensdrempels: bij welk vertrouwensniveau bereikt het model 95% nauwkeurigheid? Dat niveau wordt de drempel voor automatische goedkeuring. Daaronder gaan verzoeken naar menselijke beoordeling. Zo ontstaat een principieel routeringssysteem op basis van vertrouwen, dat een hoge nauwkeurigheid behoudt bij automatisch goedgekeurde verzoeken en onzekere gevallen doorstuurt voor menselijke beoordeling.

import numpy as np

np.random.seed(42)
# Calibrated model: high confidence = high accuracy
y_true = np.random.binomial(1, 0.6, 10000)
base_prob = np.where(y_true == 1, np.random.beta(7, 2, 10000),
                                   np.random.beta(2, 7, 10000))
y_prob = np.clip(base_prob, 0, 1)

results = []
for threshold in np.arange(0.5, 0.96, 0.05):
    mask = y_prob > threshold
    if mask.sum() < 100:
        break
    acc = (y_true[mask] == (y_prob[mask] > 0.5)).mean()
    coverage = mask.mean()
    results.append({'threshold': round(threshold, 2), 'accuracy': round(acc, 3),
                    'coverage': round(coverage, 3)})

import pandas as pd
df = pd.DataFrame(results)
print(df.to_string(index=False))

Waarschuwingen instellen voor dalend vertrouwen

Automatiseer de monitoring van vertrouwen door een gepland script uit te voeren dat dagelijks vertrouwensstatistieken berekent en een waarschuwing activeert als het voortschrijdende gemiddelde onder de implementatiedrempel daalt. Gebruik een z-scoretoets: bereken hoeveel standaardafwijkingen het huidige dagelijkse gemiddelde vertrouwen onder de trainingsbasislijn ligt en geef een waarschuwing als dit meer dan 2 standaardafwijkingen is. Deze aanpak past zich automatisch aan natuurlijke variatie in vertrouwen aan, zonder hardgecodeerde drempels.

import numpy as np

# Training period confidence stats (computed once during deployment)
train_conf_mean = 0.82
train_conf_std = 0.08
Z_THRESHOLD = 2.0  # alert if > 2 std below baseline

def check_confidence_alert(daily_confidences):
    daily_mean = np.mean(daily_confidences)
    z_score = (train_conf_mean - daily_mean) / train_conf_std

    status = 'ALERT' if z_score > Z_THRESHOLD else 'OK'
    print(f'Daily mean: {daily_mean:.4f}')
    print(f'Z-score below baseline: {z_score:.2f}')
    print(f'Status: {status}')
    return status

# Healthy day
check_confidence_alert(np.random.beta(8, 2, 500))  # mean ~0.8
print()
# Degraded day
check_confidence_alert(np.random.beta(3, 3, 500))  # mean ~0.5

Monitoring van vertrouwen per segment

Geaggregeerde monitoring van vertrouwen kan problemen missen die alleen specifieke gebruikerssegmenten treffen. Een model kan gemiddeld een stabiel vertrouwen behouden, terwijl het vertrouwen voor een recent verworven klantcohort sterk daalt. Splits de monitoring altijd uit naar belangrijke dimensies: segment van klantduur, productcategorie, geografie en apparaattype. Een plotselinge daling van het vertrouwen in een specifiek segment is vaak het eerste symptoom van concept drift binnen dat segment, voordat dit zichtbaar wordt in het totaalbeeld.

import pandas as pd
import numpy as np

# Simulated prediction log
df = pd.DataFrame({
    'segment': np.random.choice(['new_user', 'returning', 'premium'], 1000, p=[0.3, 0.5, 0.2]),
    'confidence': np.random.beta(8, 2, 1000),
    'week': np.random.choice(range(1, 9), 1000)
})
# Simulate drop for new_user segment in weeks 6-8
mask = (df['segment'] == 'new_user') & (df['week'] >= 6)
df.loc[mask, 'confidence'] *= 0.6

print(df.groupby(['week', 'segment'])['confidence'].mean().round(3).to_string())

Korte controle

Test je begrip van de concepten rond machine learning met Python uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat het loggen van voorspellingen met tijdstempels een auditspoor creëert waarmee zowel analyse achteraf als realtime monitoring mogelijk wordt, dat het voortschrijdende gemiddelde vertrouwen en de verdeling van voorspelde klassen vroege waarschuwingssignalen zonder labels zijn voor verslechtering van het model en dat Expected Calibration Error meet hoe betrouwbaar voorspelde kansen zijn en in de loop van de tijd moet worden gemonitord. Hierna gebruiken we de Evidently AI-bibliotheek om uitgebreide geautomatiseerde driftrapporten te genereren en deze te integreren in waarschuwingspijplijnen.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “Voorspellingsverdelingen en betrouwbaarheidsscores monitoren” gratis?

Ja — de volledige tekst van “Voorspellingsverdelingen en betrouwbaarheidsscores monitoren” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Machine Learning Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Machine Learning Academy bevat in totaal 4 lessen.

Wat leer ik in “Voorspellingsverdelingen en betrouwbaarheidsscores monitoren”?

Cursisten loggen voorspellingskansen naar een tijdreeksopslag, plotten de voortschrijdende gemiddelde betrouwbaarheid en markeren wanneer de gemiddelde betrouwbaarheid onder een implementatiedrempel… Je oefent met Machine Learning Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Machine Learning Academy te beginnen?

Ervaring vooraf is niet nodig. Machine Learning Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Voorspellingsverdelingen en betrouwbaarheidsscores monitoren”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Machine Learning Academy?

Ja. Elke les over Machine Learning Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Datadrift: verschuivingen in featureverdelingen door de tijd
  2. Conceptdrift: wanneer de relatie tussen X en Y verandert
  3. Voorspellingsverdelingen en betrouwbaarheidsscores monitoren
  4. Een driftwaarschuwingspipeline bouwen met Evidently AI
← Terug naar Machine Learning Academy