Drifting i monitoratge
- Introducció
- Per què les dades canvien?
- Tipus de drift
- Detecció de drift amb mètodes estadístics
- Monitoratge de qualitat de dades
- Monitoratge en producció
- Observabilitat (Observability)
- Establint alertes
- Resum
Introducció
Quan un model de machine learning arriba a producció, el nostre treball no s’acaba: tot just comença una nova fase. El món real és dinàmic, i les dades que el model veu en producció poden ser molt diferents de les que va veure durant l’entrenament. Aquest fenomen s’anomena canvi en la distribució de dades (data distribution shift o simplement drift).
En aquest capítol explorarem els diferents tipus de drift, com detectar-los, i com establir un sistema de monitoratge que ens permeti saber si el nostre model segueix funcionant correctament.
Per què les dades canvien?
Imaginem que hem entrenat un model per predir quins productes comprarà un client. El model va funcionar molt bé durant les proves, però després d’uns mesos en producció, les prediccions ja no són tan bones. Què ha passat?
Les causes poden ser múltiples:
- Canvis en el comportament dels usuaris: Nous hàbits de consum, modes, temporades
- Canvis en el mercat: Nous competidors, canvis de preus, situació econòmica
- Canvis en la recollida de dades: Actualitzacions en l’aplicació, nous camps, errors en sensors
- Canvis en la població: Nous segments de clients, expansió a nous mercats
El problema és que el model va aprendre patrons d’unes dades concretes, i quan aquestes dades canvien, el model pot quedar obsolet.
Tipus de drift
No tots els canvis en les dades són iguals. Distingim tres tipus principals:
Covariate Shift (Canvi en les covariables)
El covariate shift es produeix quan la distribució de les variables d’entrada (features) canvia, però la relació entre les entrades i la sortida es manté.
Exemple: Un model per detectar correu brossa entrenat amb correus d’oficina. Quan l’empresa comença a rebre més correus de màrqueting (nova distribució d’entrades), el model pot fallar perquè mai havia vist aquest tipus de correus, tot i que la definició de “brossa” no ha canviat.
Com detectar-ho: Comparar la distribució de les features entre entrenament i producció.
Label Shift (Canvi en les etiquetes)
El label shift es produeix quan la distribució de les sortides (etiquetes) canvia.
Exemple: Un model de diagnòstic mèdic entrenat amb dades on el 5% dels pacients tenien la malaltia. Si en producció aquest percentatge puja al 20% (per exemple, durant un brot), el model pot tenir problemes perquè els seus llindars de decisió estaven calibrats per a una prevalença diferent.
Entrenament: 95% sans, 5% malalts
Producció: 80% sans, 20% malalts ← El model pot subestimar casos positius
Com detectar-ho: Monitoritzar la distribució de les prediccions (si no tenim etiquetes reals) o de les etiquetes reals (si les obtenim amb retard).
Concept Drift (Canvi de concepte)
El concept drift és el més problemàtic: la relació entre les entrades i la sortida canvia.
Exemple: Un model per predir si un client pagarà un préstec, entrenat abans d’una crisi econòmica. Després de la crisi, clients que abans eren bons pagadors ara no poden pagar. Les mateixes features (ingressos, edat, historial) ara porten a resultats diferents.
Abans: Ingressos alts + Historial bo → Alta probabilitat de pagar
Després: Ingressos alts + Historial bo → Probabilitat incerta (crisi!)
Com detectar-ho: Només es pot detectar amb certesa si tenim les etiquetes reals de producció. Altrament, podem inferir-ho si detectem degradació en les mètriques del model.
Detecció de drift amb mètodes estadístics
Per detectar drift, comparem distribucions: les dades d’entrenament (o d’un període de referència) contra les dades actuals de producció. Hi ha diversos mètodes estadístics per fer-ho.
Tests de dues mostres (Two-sample tests)
Aquests tests responen a la pregunta: “Aquestes dues mostres provenen de la mateixa distribució?”
Test de Kolmogorov-Smirnov (KS)
El test KS mesura la màxima diferència entre les funcions de distribució acumulada de dues mostres. És útil per a variables numèriques contínues.
from scipy import stats
# Per cada feature numèrica, comparar distribucions
statistic, p_value = stats.ks_2samp(reference_data['age'], current_data['age'])
if p_value < 0.05:
print(f"Drift detectat (p={p_value:.4f})")
Interpretació: Un p-valor baix (típicament < 0.05) indica que les dues mostres probablement no vénen de la mateixa distribució.
Per a variables categòriques, el test chi-quadrat (scipy.stats.chisquare) compara les freqüències observades amb les esperades.
Population Stability Index (PSI)
El PSI és una mètrica molt utilitzada en la indústria financera per mesurar quant ha canviat una distribució.
import numpy as np
def calculate_psi(reference, current, bins: int = 10, smoothing: float = 1e-4) -> float:
"""
Calculate Population Stability Index.
Returns PSI value: < 0.1 insignificant, 0.1-0.2 investigate, > 0.2 action required.
"""
# Crear bins basats en la distribució de referència
breakpoints = np.percentile(reference, np.linspace(0, 100, bins + 1))
breakpoints[0] = -np.inf
breakpoints[-1] = np.inf
# Calcular proporcions per cada bin
ref_counts = np.histogram(reference, bins=breakpoints)[0]
cur_counts = np.histogram(current, bins=breakpoints)[0]
ref_pct = ref_counts / len(reference)
cur_pct = cur_counts / len(current)
# Evitar divisió per zero
ref_pct = np.where(ref_pct == 0, smoothing, ref_pct)
cur_pct = np.where(cur_pct == 0, smoothing, cur_pct)
# Calcular PSI
psi = np.sum((cur_pct - ref_pct) * np.log(cur_pct / ref_pct))
return psi
Interpretació del PSI:
- PSI < 0.1: Canvi insignificant
- 0.1 ≤ PSI < 0.2: Canvi moderat, investigar
- PSI ≥ 0.2: Canvi significatiu, acció requerida
Finestres de temps
Per aplicar aquests tests en producció, necessitem definir finestres de temps (time windows):
- Finestra de referència: Dades d’entrenament o d’un període estable
- Finestra actual: Dades recents de producció (últimes hores, dies, o setmanes)
Simular drift amb dades estàtiques
Un repte comú durant el desenvolupament és: com testem la nostra detecció de drift si encara no tenim dades de producció? La resposta és simular drift artificialment amb dades estàtiques.
⚠️ Tècnica de desenvolupament: Aquesta és una tècnica per a desenvolupament i testing, no una pràctica de producció. En sistemes reals de producció, la detecció de drift es fa amb dades que arriben contínuament de tràfic real, no amb datasets estàtics pre-dividits. Simular drift és útil per validar el codi abans de desplegar-lo.
Per què simular drift?
Durant la fase de desenvolupament i testing:
- No tenim dades de producció encara
- Volem verificar que el nostre codi de detecció funciona correctament
- Necessitem provar diferents escenaris de drift
- Volem establir llindars abans de desplegar
Simular drift no és fer trampes - és una tècnica estàndard per desenvolupar i validar sistemes de monitoratge.
Estratègia: Modificar features artificialment
La idea central és crear un drift conegut per verificar que el nostre sistema de detecció funciona correctament. Agafem un conjunt de dades i l’alterem deliberadament de formes específiques.
Tipus de modificacions comunes:
-
Shift additiu (covariate drift numèric)
- Exemple: Augmentar l’edat de tots els registres en 5 anys
- Simula: Envelliment de la població, canvis generacionals
-
Shift multiplicatiu (canvis d’escala)
- Exemple: Multiplicar els preus per 1.3
- Simula: Inflació, canvis en unitats de mesura
-
Canvis en distribucions categòriques
- Exemple: Canviar 30% dels registres de “urbà” a “rural”
- Simula: Canvis demogràfics, preferències d’usuaris
-
Introducció d’outliers
- Exemple: Afegir valors extrems en algunes features
- Simula: Esdeveniments inusuals, errors de dades
Workflow de testing amb drift simulat
El procés típic per validar un sistema de detecció:
- Preparar dades de referència: Usar el training set o un batch inicial conegut
- Crear escenaris de drift: Modificar una còpia de les dades de diferents formes
- Executar detecció: Aplicar els tests estadístics (KS, PSI, chi-square) a cada escenari
- Verificar resultats:
- Casos sense drift → El sistema NO hauria de disparar alarmes
- Casos amb drift lleu → Depèn dels llindars configurats
- Casos amb drift fort → El sistema SÍ hauria de detectar-lo
Aquest workflow es pot automatitzar amb tests unitaris que verifiquen el comportament esperat.
Escenaris de drift per validar
És recomanable testejar diferents intensitats de drift per calibrar llindars:
| Intensitat | Exemple de modificació | Objectiu del test |
|---|---|---|
| Cap drift | Dades originals | Verificar que NO genera falsos positius |
| Shift lleu | Canvis petits (age + 2) | Verificar tolerància a variació normal |
| Shift moderat | Canvis mitjans (age + 5, income × 1.15) | Ajustar llindars d’alerta |
| Shift fort | Canvis grans (age + 15, price × 2) | Verificar detecció clara |
Aquesta gradació ajuda a establir llindars abans de desplegar a producció: on posem el límit entre “variació acceptable” i “drift que requereix acció”?
Quan usar aquesta tècnica?
Usar simulació de drift per:
- ✅ Desenvolupar i debugar codi de detecció de drift
- ✅ Establir llindars abans de producció
- ✅ Tests automatitzats de la lògica de detecció
- ✅ Entrenar l’equip sobre què esperar en producció
- ✅ Validar que les alertes funcionen correctament
NO substitueix:
- ❌ Monitoratge real de producció (necessitem dades reals!)
- ❌ Anàlisi de causes de drift (simulació no explica per què passa)
- ❌ Decisions de reentrenament (basades en impacte real, no simulat)
Conclusió: Simular drift és una eina de desenvolupament i validació, no de producció. Un cop desplegat, cal monitoritzar dades reals.
Monitoratge de qualitat de dades
La detecció de drift és essencial, però no és l’única cosa que hem de monitoritzar. Les dades poden tenir problemes de qualitat que afecten el model sense que hi hagi drift estadístic.
Tipus de problemes de qualitat
1. Integritat de les dades
- Valors nuls: percentatge de missing values per feature
- Duplicats: registres repetits
- Violacions d’esquema: tipus de dades incorrectes, columnes inesperades
2. Qualitat de les features
- Outliers: valors fora del rang esperat
- Violacions de rang: valors fora dels límits coneguts
- Canvis de cardinalitat: noves categories en features categòriques
3. Qualitat de les prediccions
- Distribució de confiança: les prediccions són menys segures?
- Calibratge: les probabilitats predites coincideixen amb les freqüències reals?
Què validar?
- Valors nuls: Percentatge de missing values per feature
- Outliers: Valors a més de 3 desviacions estàndard
- Noves categories: Categories no vistes durant l’entrenament
- Violacions de rang: Valors fora dels límits esperats (edat negativa, etc.)
La validació s’hauria de fer abans d’usar les dades per entrenar o servir prediccions. Si es detecten problemes crítics, el pipeline hauria d’avortar i alertar.
Diferència clau: El drift mesura canvis en distribucions; la qualitat mesura problemes en les dades mateixes.
Monitoratge en producció
Detectar drift és només una part del monitoratge. Un sistema de monitoratge complet ha de vigilar múltiples aspectes.
Emmagatzematge de prediccions per monitoratge
Abans de poder monitoritzar el nostre model, necessitem guardar les prediccions que fem en producció. Sense aquest registre, no podem detectar drift, calcular mètriques, ni analitzar el comportament del model.
Què cal guardar?
Per a cada predicció, hauríem de registrar:
Essencial:
- Timestamp: Quan s’ha fet la predicció
- Input features: Les dades d’entrada (sense informació sensible!)
- Prediction: La sortida del model
- Request ID: Identificador únic de la petició (opcional però útil)
Recomanat:
- Model version: Quina versió del model ha fet la predicció
- Confidence/probability: Si el model retorna probabilitats
- Latency: Temps que ha trigat la predicció
Opcional:
- User ID: Si és rellevant i permet privacitat
- Context: Informació addicional del context de la petició
On guardar les prediccions?
Tenim diverses opcions, depenent de l’escala i complexitat:
Fitxers de log JSON (recomanat per començar):
import json, logging
from datetime import datetime
pred_logger = logging.getLogger('predictions')
pred_logger.addHandler(logging.FileHandler('logs/predictions.jsonl'))
def log_prediction(inputs: dict, prediction: float, model_version: str, latency: float):
entry = {
'timestamp': datetime.now().isoformat(),
'inputs': inputs,
'prediction': prediction,
'model_version': model_version,
'latency_ms': latency * 1000
}
pred_logger.info(json.dumps(entry))
Això genera un fitxer predictions.jsonl amb una línia JSON per predicció, fàcil d’analitzar amb pandas o scripts.
Per a volums més alts, es pot usar SQLite (queries SQL ràpides) o PostgreSQL (escalable, concurrent).
Consideracions de privacitat i seguretat
⚠️ Molt important: No guardar dades sensibles sense anonimitzar!
def anonymize_inputs(inputs: dict) -> dict:
"""Elimina o anonimitza dades sensibles."""
safe_inputs = inputs.copy()
# Eliminar camps sensibles
sensitive_fields = ['email', 'phone', 'ssn', 'credit_card']
for field in sensitive_fields:
if field in safe_inputs:
safe_inputs[field] = '***REDACTED***'
# Hash d'identificadors si cal mantenir-los
if 'user_id' in safe_inputs:
safe_inputs['user_id'] = hashlib.sha256(
str(safe_inputs['user_id']).encode()
).hexdigest()[:16]
return safe_inputs
# Usar abans de guardar
safe_inputs = anonymize_inputs(raw_inputs)
log_prediction(safe_inputs, prediction, model_version, latency)
Resum: estratègia de logging
Per començar (projectes petits):
- ✅ Logs JSON en fitxers (
predictions.jsonl) - ✅ Guardar: timestamp, inputs, prediction, model_version
- ✅ Analitzar amb scripts Python/pandas periòdicament
Per escalar (projectes mitjans):
- ✅ SQLite per emmagatzematge més eficient
- ✅ Índexs per timestamps per queries ràpides
- ✅ Scripts automatitzats (cron) per analitzar diàriament
Per producció (projectes grans):
- ✅ PostgreSQL o base de dades distribuïda
- ✅ Anonymització automàtica de dades sensibles
- ✅ Backups automàtics i retenció de dades
- ✅ Monitoratge en temps real amb alertes
Amb prediccions guardades, podem començar a detectar drift i monitoritzar el model!
Columnes de Predicció: Per Què i Com
Ara que sabem què guardar i on guardar-ho, entenguem per què cada columna és important i com s’utilitza en monitoratge i debugging.
Columnes i els Seus Casos d’Ús
Columnes Essencials:
- Timestamp: Anàlisi temporal i finestres de comparació (última setmana vs. anterior)
- Features: Detectar covariate shift (canvis en distribució d’entrades) i reproducibilitat
- Prediction: Detectar concept drift indirecte (canvis en distribució de sortides)
- Request ID: Debugging i traceability (correlacionar errors amb prediccions específiques)
Columnes Recomanades:
- Model Version: Comparar rendiment entre versions, rollback decisions, A/B testing
- Probability: Calibration monitoring i early warning de drift (canvis en confidence)
- Latency: Performance monitoring i SLA compliance
Columnes Opcionals:
- User ID: Personalització i bias detection (requereix anonymització per GDPR)
Casos d’Ús i Columnes Necessàries:
| Cas d’Ús | Columnes Clau |
|---|---|
| Detectar Covariate Shift | Timestamp + Features |
| Detectar Concept Drift | Timestamp + Prediction + Probability |
| Debugging | Request ID + Features + Model Version |
| A/B Testing | Model Version + Prediction + Timestamp |
| Calibration Monitoring | Probability + Ground Truth (quan disponible) |
Què monitoritzar?
1. Mètriques del model (Model metrics)
Si tenim accés a les etiquetes reals (encara que sigui amb retard), podem calcular les mètriques tradicionals: accuracy, precision, recall, F1 per classificació; MSE, MAE, R² per regressió.
2. Distribució de les prediccions
Fins i tot sense etiquetes, podem monitoritzar la distribució de les prediccions:
- Per classificació: Proporció de cada classe predita
- Per regressió: Mitjana, mediana, rang de les prediccions
Si la distribució de prediccions canvia dràsticament, pot ser senyal de drift.
3. Distribució de les features
Monitoritzar les features d’entrada ens permet detectar covariate shift. Si la mitjana d’una feature actual està a més de N desviacions estàndard de la referència, cal investigar.
4. Mètriques operacionals
A més del model, hem de monitoritzar el sistema:
- Latència: Temps de resposta de l’API (p50, p95, p99)
- Throughput: Nombre de peticions per segon
- Errors: Taxa d’errors (5xx, timeouts)
- Recursos: Ús de CPU, memòria, disc
Arquitectura de monitoratge simple
Per al nostre context (scripts Python, sense dependències complexes), podem implementar un sistema de monitoratge basat en:
- Logging estructurat: Registrar tot en fitxers de log amb format consistent
- Scripts d’anàlisi: Scripts que processen els logs periòdicament
- Visualització simple: Gràfics amb matplotlib o similar
Un script d’anàlisi periòdic (cron job diari) pot llegir els logs JSON, calcular estadístiques (latència mitjana, p95, taxa d’errors), i generar alertes si es superen llindars.
Observabilitat (Observability)
El monitoratge ens diu què passa (mètriques, alertes), però l’observabilitat ens permet entendre per què passa.
Els tres pilars de l’observabilitat
- Mètriques (Metrics): Valors numèrics agregats (latència mitjana, taxa d’errors)
- Logs: Registres detallats d’esdeveniments individuals
- Traces: Seguiment del camí d’una petició a través del sistema
Per al nostre context simplificat, ens centrarem en logs ben estructurats que ens permetin fer anàlisi posterior.
Logs estructurats
En lloc de logs de text lliure, utilitzar format JSON facilita l’anàlisi posterior. Cada línia de log hauria de contenir: timestamp, event type, dades rellevants (inputs anonimitzats, prediction, latency, model_version), i informació de context (request_id).
{"timestamp": "2024-01-15T10:30:45", "event": "prediction", "request_id": "abc123", "prediction": 0.85, "latency_ms": 45.2, "model_version": "1.2.0"}
Establint alertes
Les alertes ens notifiquen quan alguna cosa requereix atenció. La clau és trobar l’equilibri: prou sensibles per detectar problemes, però no tant que generin fatiga d’alertes.
Tipus d’alertes
-
Alertes de llindar (Threshold alerts): Quan una mètrica supera un valor fix
- Latència > 500ms
- Taxa d’errors > 1%
- PSI > 0.2
-
Alertes d’anomalia: Quan una mètrica es desvia significativament del seu comportament normal
- Nombre de peticions 50% inferior a la mitjana de la mateixa hora
-
Alertes de tendència: Quan una mètrica mostra una tendència preocupant
- Latència augmentant progressivament durant 3 dies
Implementació d’alertes
Les alertes es basen en comparar mètriques contra llindars predefinits:
| Mètrica | Llindar típic | Severitat |
|---|---|---|
| Latència p95 | > 500ms | warning |
| Taxa d’errors | > 1% | critical |
| PSI (drift) | > 0.2 | warning |
Quan es supera un llindar, es registra l’alerta a un fitxer o s’envia per email/Slack.
Resum
En aquest capítol hem après:
- El drift (canvi en la distribució de dades) és inevitable en producció i pot degradar el rendiment del model
- Hi ha tres tipus principals: covariate shift (canvi en features), label shift (canvi en distribució d’etiquetes), i concept drift (canvi en la relació entre features i etiquetes)
- Podem detectar drift amb tests estadístics com Kolmogorov-Smirnov, chi-quadrat, o el Population Stability Index (PSI)
- Un sistema de monitoratge complet vigila mètriques del model, distribució de prediccions i features, i mètriques operacionals
- L’observabilitat (especialment logs estructurats) ens permet entendre per què passen els problemes
- Les alertes ens notifiquen quan cal actuar, però cal calibrar-les per evitar fatiga
Al proper capítol veurem què fer quan detectem que el model necessita ser actualitzat: l’aprenentatge continu i les estratègies per testar models en producció.