Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Drifting i monitoratge

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.

Producció

Features X'
distribució diferent

Model

Predicció Y
potencialment dolenta

Entrenament

Features X

Model

Predicció Y

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)

No

Dades històriques
Referència

Comparar

Dades recents
Última setmana

Drift
detectat?

Alerta

Tot correcte

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:

  1. Shift additiu (covariate drift numèric)

    • Exemple: Augmentar l’edat de tots els registres en 5 anys
    • Simula: Envelliment de la població, canvis generacionals
  2. Shift multiplicatiu (canvis d’escala)

    • Exemple: Multiplicar els preus per 1.3
    • Simula: Inflació, canvis en unitats de mesura
  3. Canvis en distribucions categòriques

    • Exemple: Canviar 30% dels registres de “urbà” a “rural”
    • Simula: Canvis demogràfics, preferències d’usuaris
  4. 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ó:

  1. Preparar dades de referència: Usar el training set o un batch inicial conegut
  2. Crear escenaris de drift: Modificar una còpia de les dades de diferents formes
  3. Executar detecció: Aplicar els tests estadístics (KS, PSI, chi-square) a cada escenari
  4. 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 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:

IntensitatExemple de modificacióObjectiu del test
Cap driftDades originalsVerificar que NO genera falsos positius
Shift lleuCanvis petits (age + 2)Verificar tolerància a variació normal
Shift moderatCanvis mitjans (age + 5, income × 1.15)Ajustar llindars d’alerta
Shift fortCanvis 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’ÚsColumnes Clau
Detectar Covariate ShiftTimestamp + Features
Detectar Concept DriftTimestamp + Prediction + Probability
DebuggingRequest ID + Features + Model Version
A/B TestingModel Version + Prediction + Timestamp
Calibration MonitoringProbability + 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:

  1. Logging estructurat: Registrar tot en fitxers de log amb format consistent
  2. Scripts d’anàlisi: Scripts que processen els logs periòdicament
  3. Visualització simple: Gràfics amb matplotlib o similar

Alertes

Anàlisi

Producció

API FastAPI

Fitxers de log

Script d'anàlisi
cron job diari

Estadístiques

Detecció de drift

Gràfics

Llindars
superats?

Email/Slack

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

  1. Mètriques (Metrics): Valors numèrics agregats (latència mitjana, taxa d’errors)
  2. Logs: Registres detallats d’esdeveniments individuals
  3. 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

  1. Alertes de llindar (Threshold alerts): Quan una mètrica supera un valor fix

    • Latència > 500ms
    • Taxa d’errors > 1%
    • PSI > 0.2
  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
  3. 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ètricaLlindar típicSeveritat
Latència p95> 500mswarning
Taxa d’errors> 1%critical
PSI (drift)> 0.2warning

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ó.