Módulo / 10. MLOps
0%
Módulo 10 · Avanzado

MLOps y producción

Un modelo en un notebook no genera valor. Este módulo cubre el ciclo de vida profesional: empaquetar, servir, versionar, monitorear y mantener modelos en producción sin que se degraden en silencio.

8 lecciones 12 h estimadas Código listo para desplegar
0 de 8 lecciones completadas
Lección 10.1

El ciclo de vida de un modelo en producción

16 minMLOpsMapa del sistema

Un modelo entrenado no es un producto. Es un artefacto que debe integrarse en un sistema, recibir datos, responder en un tiempo razonable, monitorearse y actualizarse cuando el mundo cambia. MLOps es la disciplina que hace que eso sea repetible.

Al terminar sabrás

Describir las etapas del ciclo de vida de un sistema de ML.
Distinguir el modelo del sistema que lo rodea.
Identificar los puntos donde fallan la mayoría de los proyectos.
Elegir un nivel de madurez adecuado al contexto.

El ciclo completo

Datosingesta y calidad Entrenamientoexperimentos Empaquetadoartefacto DespliegueAPI / batch Monitoreodrift y métricas Decisiones: reentrenar, ajustar, retirarel ciclo se cierra con evidencia
El modelo es una pieza. El sistema incluye datos, pipeline, artefacto, servicio, monitoreo y personas.

El modelo es la parte pequeña

En un sistema real, el código del modelo suele ser una fracción mínima del total. El resto es infraestructura de datos, validación, serving, logging, dashboards y procesos. La deuda técnica de ML viene de las fronteras entre esos componentes:

  • Cambios en la fuente de datos que rompen el esquema.
  • Preprocesado duplicado entre entrenamiento y serving que se desincroniza.
  • Dependencias no fijadas que cambian el comportamiento al reinstalar.
  • Métricas que no se registran y decisiones que no se pueden auditar.
  • Modelos que se degradan sin que nadie lo note.
1

Un fallo silencioso típico

El modelo se entrenó con la columna ingresos en euros. Un cambio en el ERP hace que ahora llegue en céntimos. La API sigue respondiendo 200 y el esquema sigue siendo numérico, pero todas las predicciones son absurdas. Nadie lo detecta hasta que un usuario se queja semanas después.

Prevención: validar rangos y distribuciones de entrada, no solo tipos; comparar estadísticas de producción con las de entrenamiento; alertar cuando la media de una feature se desvía más de un umbral.

Niveles de madurez

NivelCaracterísticasCuándo es razonable
ManualNotebooks, scripts, despliegue a manoPrototipo, validación de idea
ReproduciblePipeline versionado, entorno fijo, artefacto guardadoPrimer modelo en producción
AutomatizadoCI/CD, tests, reentrenamiento programadoProducto con usuarios reales
MonitoreadoDrift, métricas de negocio, alertas, auditoríaSistemas críticos o regulados
No sobredimensiones MLOps Un equipo de dos personas con un modelo semanal no necesita Kubernetes, feature store y orquestación compleja. Empieza con un pipeline reproducible y un endpoint simple; añade complejidad cuando el dolor sea real.
Ejercicio 10.1 · Mapa del sistema

Elige un modelo que hayas entrenado en este curso y dibuja el sistema completo: fuente de datos, pipeline, artefacto, forma de serving, consumidores, métricas y responsable de cada parte. Marca los tres puntos más frágiles.

Orientación: los puntos frágiles suelen ser la calidad de la fuente, la coherencia del preprocesado y la ausencia de monitoreo. Para cada uno, define una prueba o alerta concreta y un responsable.

Lección 10.2

Serialización y pipelines reproducibles

20 minjoblibPipeline

Guardar el modelo no basta. Debes guardar la misma transformación que se aplicó a los datos, las versiones de las librerías y la configuración. Un modelo sin su pipeline es un artefacto incompleto.

Qué guardar

Modelo

Pesos y estructura

En Scikit-learn, el objeto completo; en PyTorch, state_dict más la definición de la arquitectura. No dependas de pickles de clases locales.

Preprocesado

Transformaciones

Escaladores, imputadores, encoders y vectorizadores ajustados. Si no viajan con el modelo, el serving reproduce otro pipeline.

Metadatos

Contexto

Versión, fecha, métricas, datos de entrenamiento, hiperparámetros y hash del artefacto. Sin esto no puedes auditar.

Entorno

Dependencias

requirements.txt con versiones fijas, imagen Docker o lockfile. Un cambio de versión puede alterar resultados.

El pipeline como unidad

Predicción reproducible $$\hat y = f_{\theta}\left(T_{\phi}(\mathbf{x})\right), \qquad \text{artefacto}=(f_\theta, T_\phi, \text{metadatos}, \text{entorno})$$ $T_\phi$ son las transformaciones ajustadas con entrenamiento. Guardar solo $f_\theta$ rompe la reproducibilidad si $T_\phi$ se recalcula en serving.
1

El escalador que se perdió

Entrenaste con features estandarizadas (media 0, desviación 1). En producción, el servicio recibe valores crudos y los pasa directamente al modelo. La predicción no da error, pero está fuera de distribución. Si la media de entrenamiento era 50 y la desviación 10, un valor de 60 debería entrar como 1.0; entra como 60.

Solución: guardar el pipeline completo con joblib o usar un artefacto que incluya el preprocesado. Probar el artefacto con un ejemplo conocido antes de desplegarlo.

Pythonserializar.py
import json
import joblib
import sklearn
from datetime import datetime, timezone

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier

pipeline = Pipeline([
    ("imputar", SimpleImputer(strategy="median")),
    ("escalar", StandardScaler()),
    ("modelo", RandomForestClassifier(
        n_estimators=300, max_depth=12, random_state=42, n_jobs=-1
    ))
])

pipeline.fit(X_train, y_train)

# Guardar pipeline completo, no solo el estimador final
joblib.dump(pipeline, "modelo_v1.joblib", compress=3)

metadatos = {
    "nombre": "churn-classifier",
    "version": "1.0.0",
    "fecha": datetime.now(timezone.utc).isoformat(),
    "sklearn": sklearn.__version__,
    "features": list(X_train.columns),
    "metrica_validacion": {"f1": 0.71, "roc_auc": 0.83},
    "semilla": 42
}
with open("modelo_v1.json", "w", encoding="utf-8") as f:
    json.dump(metadatos, f, indent=2, ensure_ascii=False)

# Verificación: cargar y comparar con el original
cargado = joblib.load("modelo_v1.joblib")
assert (cargado.predict(X_test) == pipeline.predict(X_test)).all()
print("artefacto verificado")

Buenas prácticas de serialización

  • Evita pickle para modelos de terceros no confiables: puede ejecutar código al cargar. Usa formatos seguros (ONNX, SavedModel) cuando compartas entre equipos.
  • Fija versiones: un modelo guardado con una versión de Scikit-learn puede no cargar igual en otra.
  • Incluye un test de humo: un ejemplo de entrada y su salida esperada. Si el artefacto no reproduce esa salida, no se despliega.
  • Registra el hash: permite verificar que el artefacto desplegado es el que se evaluó.
Nunca cargues un pickle de origen desconocido La deserialización de pickle puede ejecutar código arbitrario. Si recibes un modelo de un tercero, verifica su procedencia o usa un formato de solo datos como ONNX. La conveniencia no justifica un riesgo de ejecución remota.
Ejercicio 10.2 · Artefacto completo

Empaqueta un modelo de clasificación con su pipeline, metadatos y un test de humo. Escribe un script que cargue el artefacto, valide que reproduce una predicción conocida y falle con un mensaje claro si no.

Orientación: guarda el pipeline con joblib, un JSON con versión y features, y un archivo con la entrada/salida de referencia. El script de verificación debe comprobar forma, tipo y valor con tolerancia. Este test se ejecuta en CI antes de publicar la imagen.

Lección 10.3

API de inferencia con FastAPI

22 minServicioValidación

Una API de inferencia convierte un modelo en un servicio. Debe validar la entrada, responder en un tiempo predecible, manejar errores sin caerse y registrar lo suficiente para diagnosticar problemas.

Contrato de la API

ElementoQué definirEjemplo
EndpointRuta y métodoPOST /predict
EntradaEsquema, tipos, rangosJSON con 8 features numéricas
SalidaClase, probabilidad, versión{"churn": true, "prob": 0.82, "model": "1.0.0"}
ErroresCódigos y mensajes422 para entrada inválida, 503 si el modelo no cargó
SaludEndpoint de liveness/readinessGET /health
Pythonmain.py
from contextlib import asynccontextmanager
from typing import Literal

import joblib
import numpy as np
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field, field_validator

MODELO = None
VERSION = "1.0.0"

@asynccontextmanager
async def lifespan(app: FastAPI):
    global MODELO
    MODELO = joblib.load("modelo_v1.joblib")
    yield
    MODELO = None

app = FastAPI(title="Churn API", version=VERSION, lifespan=lifespan)

class Cliente(BaseModel):
    antiguedad_meses: int = Field(ge=0, le=600)
    gasto_mensual: float = Field(ge=0, le=100000)
    num_productos: int = Field(ge=1, le=20)
    reclamos_ultimo_ano: int = Field(ge=0, le=100)
    tipo_contrato: Literal["mensual", "anual", "bienal"]

    @field_validator("gasto_mensual")
    @classmethod
    def gasto_razonable(cls, v: float) -> float:
        if v > 50000:
            raise ValueError("gasto fuera del rango soportado por el modelo")
        return v

class Prediccion(BaseModel):
    churn: bool
    probabilidad: float
    modelo_version: str

def transformar(cliente: Cliente) -> np.ndarray:
    contrato = {"mensual": 0, "anual": 1, "bienal": 2}[cliente.tipo_contrato]
    return np.array([[
        cliente.antiguedad_meses,
        cliente.gasto_mensual,
        cliente.num_productos,
        cliente.reclamos_ultimo_ano,
        contrato
    ]], dtype=float)

@app.get("/health")
def health():
    return {"status": "ok" if MODELO is not None else "unavailable"}

@app.post("/predict", response_model=Prediccion)
def predict(cliente: Cliente) -> Prediccion:
    if MODELO is None:
        raise HTTPException(status_code=503, detail="modelo no disponible")
    X = transformar(cliente)
    prob = float(MODELO.predict_proba(X)[0, 1])
    return Prediccion(
        churn=prob >= 0.5,
        probabilidad=round(prob, 4),
        modelo_version=VERSION
    )
Validar no es opcional Pydantic valida tipos y rangos. Añade validaciones semánticas: categorías permitidas, coherencia entre campos y valores que el modelo no vio en entrenamiento. Una entrada inválida debe devolver 422, no una predicción silenciosa.

Patrones de serving

  • Online: petición individual, baja latencia, respuesta inmediata. Es lo que hace esta API.
  • Batch: se procesan lotes periódicamente; más eficiente para grandes volúmenes.
  • Streaming: el modelo consume eventos continuos y emite predicciones.
  • Edge: el modelo se ejecuta en el dispositivo, sin conexión.
Carga del modelo al inicio Cargar el modelo en cada petición multiplica la latencia y el consumo. Cárgalo una vez en el arranque (lifespan) y comparte una instancia de solo lectura. Si el modelo es pesado, usa varios workers con cuidado: cada proceso carga su propia copia en memoria.
Ejercicio 10.3 · Diseñar el contrato

Diseña el contrato de una API que recibe datos de un sensor y predice si una máquina fallará en las próximas 24 horas. Define esquema de entrada, salida, errores y validaciones. ¿Qué harías si faltan lecturas?

Orientación: entrada con timestamp, features numéricas y ventana temporal; salida con probabilidad, versión y hora; validar rangos físicos y número de lecturas; si faltan datos, devolver 422 con detalle o aplicar una política de imputación documentada. No inventes lecturas en silencio.

Lección 10.4

Docker y entornos reproducibles

20 minContenedoresImagen

«En mi máquina funciona» es el síntoma de un entorno no reproducible. Docker empaqueta código, dependencias y configuración en una imagen que se ejecuta igual en tu portátil, en CI y en el servidor.

Imagen, contenedor y capas

  • Imagen: plantilla inmutable con sistema base, dependencias y código.
  • Contenedor: instancia en ejecución de una imagen.
  • Capas: cada instrucción del Dockerfile crea una capa. El orden afecta el caché: pon lo que cambia menos arriba.
DockerfileDockerfile
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=1

WORKDIR /app

# 1) Dependencias primero: se cachean si no cambian
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 2) Código y artefacto después
COPY src/ ./src/
COPY artifacts/modelo_v1.joblib ./artifacts/

# 3) Usuario sin privilegios
RUN useradd --create-home appuser && chown -R appuser:appuser /app
USER appuser

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
Bashcomandos.sh
# Construir la imagen
docker build -t churn-api:1.0.0 .

# Ejecutar el contenedor
docker run --rm -p 8000:8000 churn-api:1.0.0

# Probar el endpoint
curl -X POST http://localhost:8000/predict \
  -H "Content-Type: application/json" \
  -d '{"antiguedad_meses": 12, "gasto_mensual": 45.5, "num_productos": 2, "reclamos_ultimo_ano": 1, "tipo_contrato": "mensual"}'

# Ver logs y tamaño
docker logs 
docker images churn-api

Errores frecuentes en Docker

ErrorConsecuenciaCorrección
Copiar todo el proyecto antes de instalarCaché inútil, builds lentosCopiar requirements primero
Usar latest en la imagen baseBuilds no reproduciblesFijar versión o digest
Ejecutar como rootMayor impacto de una vulnerabilidadCrear usuario sin privilegios
Incluir datos y secretos en la imagenFuga irreversibleVariables de entorno y volúmenes
Imagen de varios GBDespliegues lentosBase slim, multi-stage build, limpiar caché
Multi-stage build Para reducir tamaño, compila dependencias en una etapa y copia solo los artefactos necesarios a la imagen final. Es especialmente útil con extensiones nativas o modelos grandes. La imagen final no necesita compiladores ni cachés de pip.

Reproducibilidad más allá de Docker

Una imagen fija el entorno, pero también debes fijar los datos y el azar. Registra el hash del dataset, las semillas y la versión del código. Sin eso, dos ejecuciones con la misma imagen pueden producir modelos distintos.

Ejercicio 10.4 · Dockerizar un modelo

Escribe un Dockerfile para una API que sirve un modelo de Scikit-learn. Incluye healthcheck, usuario no root y dependencias fijas. Construye la imagen, ejecútala y verifica que responde. ¿Qué tamaño tiene y cómo lo reducirías?

Orientación: base python:3.11-slim, copiar requirements antes del código, instalar sin caché, copiar el artefacto, usuario no privilegiado y healthcheck. Para reducir tamaño: multi-stage, eliminar tests y notebooks de la imagen, y usar un modelo comprimido o cuantizado si aplica.

Lección 10.5

CI/CD, versionado de datos y modelos

22 minAutomatizaciónTrazabilidad

La integración continua verifica que el código sigue funcionando; el despliegue continuo lo publica. En ML hay una tercera pieza: los datos y el modelo también necesitan versiones, pruebas y trazabilidad.

Qué debe probar un pipeline de ML

Datos

Calidad y esquema

Columnas esperadas, tipos, rangos, nulos, duplicados y distribución. Un test barato detecta la mayoría de los fallos.

Código

Unidades e integración

Funciones de preprocesado, contrato de la API, serialización y carga del artefacto. pytest en cada commit.

Modelo

Umbral de rendimiento

El modelo nuevo no se publica si su métrica de validación cae por debajo de un mínimo o empeora respecto al anterior.

Servicio

Humo y latencia

La imagen arranca, /health responde y una predicción de referencia tarda menos que el presupuesto.

Versionar datos y modelos

Git versiona código, no datasets grandes. Para datos se usan DVC, LakeFS o almacenamiento con hashes; para modelos, un registro (MLflow, W&B, un bucket con metadatos). Lo importante es poder responder: ¿con qué datos, código e hiperparámetros se produjo este artefacto?

1

Una regresión que pasó los tests

Un nuevo modelo tiene F1 0.70 en validación, frente a 0.72 del anterior. El equipo decide publicarlo porque «la diferencia es pequeña». En producción, el recall de la clase crítica cae de 0.65 a 0.48 porque el nuevo modelo se centró en la clase mayoritaria.

Lección: el test de publicación debe incluir métricas por clase y comparación con el modelo en producción, no solo un promedio. La puerta de calidad debe reflejar el coste real.

YAMLci.yml
name: ml-pipeline

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install -r requirements.txt
      - name: Tests unitarios
        run: pytest -q
      - name: Validación de datos
        run: python scripts/validate_data.py --data data/train.csv
      - name: Test de humo del artefacto
        run: python scripts/smoke_test.py --model artifacts/modelo_v1.joblib
      - name: Construir imagen
        run: docker build -t churn-api:${{ github.sha }} .
      - name: Escanear imagen
        run: trivy image --exit-code 1 --severity HIGH,CRITICAL churn-api:${{ github.sha }}

Estrategias de despliegue

  • Recreate: se reemplaza la versión anterior. Simple, con downtime.
  • Rolling: se actualizan instancias gradualmente. Sin downtime, pero conviven versiones.
  • Blue-green: dos entornos idénticos; se cambia el tráfico cuando el nuevo está validado.
  • Canary: se envía un porcentaje pequeño de tráfico a la nueva versión y se compara con la anterior.
  • Shadow: la nueva versión recibe tráfico duplicado sin afectar a usuarios; se comparan predicciones.
Rollback preparado Todo despliegue debe poder revertirse en minutos. Conserva la imagen y el artefacto anteriores, documenta el procedimiento y prueba el rollback al menos una vez. Un rollback no probado no es un rollback.
No versiones secretos en Git Claves de API, contraseñas de bases de datos y credenciales de nube van en un gestor de secretos o variables de entorno cifradas. Si se filtran en un commit, considéralas comprometidas y rótalas; borrar el archivo no basta.
Ejercicio 10.5 · Puerta de calidad

Define los criterios que debe cumplir un modelo para pasar de staging a producción en un sistema de aprobación de crédito. Incluye métricas globales, por subgrupo, latencia y requisitos de auditoría.

Orientación: AUC y PR globales, recall y precisión por subgrupo, calibración, latencia p95, tasa de abstención, reproducibilidad del artefacto y documentación de limitaciones. Además, revisión humana y registro de la versión que tomó cada decisión.

Lección 10.6

Monitoreo, data drift y degradación

22 minDriftAlertas

Un modelo en producción no es estático. Las entradas cambian, el comportamiento de los usuarios cambia y la relación entre ambos puede cambiar. El monitoreo existe para detectar esa degradación antes de que afecte a las decisiones.

Tres tipos de cambio

TipoQué cambiaEjemploDetección
Data drift (covariate shift)$P(X)$Los usuarios nuevos tienen otra distribución de gastoComparar estadísticas de features
Concept drift$P(Y\mid X)$Un cambio de política altera qué clientes abandonanRendimiento con etiquetas tardías
Label drift$P(Y)$Sube la tasa base de fraudeMonitorear prevalencia
Detección de drift por feature $$\text{PSI}=\sum_{b=1}^{B}(p_b-q_b)\ln\frac{p_b}{q_b}, \qquad \text{KS}=\sup_x|F_{\text{prod}}(x)-F_{\text{train}}(x)|$$ PSI compara proporciones por bins; valores < 0.1 suelen considerarse estables, 0.1–0.25 moderados y > 0.25 altos. KS mide la máxima diferencia entre distribuciones acumuladas. Los umbrales dependen del dominio.
1

Drift sin caída inmediata de métricas

Una feature «edad» tenía media 35 y ahora tiene media 52 porque la app cambió de público. El modelo sigue prediciendo, pero muchas combinaciones de edad y otras variables quedan fuera de la región donde fue entrenado. Las predicciones pueden ser sistemáticamente peores sin que la API falle.

Acción: alertar por PSI/KS, revisar la distribución conjunta, y si el cambio es permanente, recolectar datos nuevos y reentrenar con validación temporal.

Qué monitorear

Técnico

Salud del servicio

Latencia p50/p95/p99, errores 5xx, tasa de timeouts, uso de memoria y CPU. Detecta fallos, no degradación silenciosa.

Datos

Entradas

Nulos, rangos, categorías nuevas, distribución por feature, PSI/KS. Un esquema válido puede ocultar valores absurdos.

Modelo

Predicciones

Distribución de scores, tasa de positivos, calibración. Un cambio brusco en la tasa de alertas es señal de alarma.

Negocio

Impacto

Conversión, fraude detectado, coste por error, satisfacción. Es la métrica que importa, aunque llega con retraso.

Etiquetas tardías

En muchos problemas la etiqueta real llega semanas después (impago, reingreso, fallo). No puedes esperar para monitorear. Alternativas: usar proxies, muestras etiquetadas manualmente, o comparar la distribución de scores con la esperada. Documenta el retraso y no confundas ausencia de queja con buen rendimiento.

Pythondrift.py
import numpy as np
from scipy.stats import ks_2samp

def psi(referencia, produccion, bins=10):
    """Population Stability Index para una feature numérica."""
    cortes = np.quantile(referencia, np.linspace(0, 1, bins + 1))
    cortes[0], cortes[-1] = -np.inf, np.inf
    p, _ = np.histogram(referencia, bins=cortes)
    q, _ = np.histogram(produccion, bins=cortes)
    p = np.clip(p / max(1, p.sum()), 1e-6, None)
    q = np.clip(q / max(1, q.sum()), 1e-6, None)
    return float(np.sum((p - q) * np.log(p / q)))

for columna in features:
    valor_psi = psi(train[columna].dropna(), prod[columna].dropna())
    ks, p_valor = ks_2samp(train[columna].dropna(), prod[columna].dropna())
    estado = "ALTO" if valor_psi > 0.25 else "moderado" if valor_psi > 0.1 else "estable"
    print(f"{columna:>20s} PSI={valor_psi:.3f} KS={ks:.3f} p={p_valor:.4f} -> {estado}")

# Distribución de scores: comparar con referencia
print("tasa de positivos train:", (score_train >= 0.5).mean())
print("tasa de positivos prod :", (score_prod >= 0.5).mean())
Alertas accionables Una alerta que nadie sabe qué hacer es ruido. Cada alerta debe tener dueño, umbral justificado y procedimiento: qué revisar, cómo confirmar y cuándo reentrenar. Si no puedes actuar, no la configures.
Ejercicio 10.6 · Plan de monitoreo

Diseña el monitoreo de un modelo de predicción de demanda diaria. Define qué métricas técnicas, de datos, de modelo y de negocio registrarías, con qué frecuencia y con qué umbral de alerta. ¿Cómo detectarías un cambio de tendencia sin etiquetas inmediatas?

Orientación: latencia y errores cada minuto; PSI/KS por feature a diario; distribución de predicciones y tasa de valores extremos; error contra ventas reales cuando llegan. Para detectar tendencia sin etiquetas, monitorea residuos proxies, comparación con un modelo naive y desviaciones sostenidas de la distribución de scores.

Lección 10.7

Gobernanza, privacidad y auditoría

18 minRiesgoCumplimiento

Cuando un modelo influye en crédito, empleo, salud o seguridad, la pregunta no es solo si funciona, sino si podemos explicar, auditar y limitar su uso. La gobernanza es el conjunto de decisiones y controles que hacen eso posible.

Preguntas de gobernanza

  • Propósito: ¿para qué está autorizado el modelo y para qué no?
  • Datos: ¿qué datos se usaron, con qué base legal y durante cuánto tiempo se conservan?
  • Responsabilidad: ¿quién responde cuando el modelo se equivoca?
  • Explicabilidad: ¿puede una persona afectada recibir una razón comprensible?
  • Supervisión: ¿hay revisión humana en decisiones de alto impacto?
  • Auditoría: ¿se conservan versiones, entradas y salidas para reconstruir decisiones?

Privacidad en la práctica

RiesgoEjemploMitigación
ReidentificaciónCombinar edad, código postal y comprasGeneralización, k-anonimato, ruido diferencial
MemorizaciónUn modelo reproduce datos de entrenamientoRegularización, deduplicación, auditoría de extracción
Fuga por logsDatos personales en logs de la APIMinimización, redacción, retención limitada
Acceso excesivoTodo el equipo puede leer el datasetRoles, cifrado, registro de accesos
Minimización de datos No recojas un dato «por si acaso». Cada campo aumenta el riesgo y las obligaciones. Si no se usa en el modelo ni en la auditoría, no debería estar en el dataset. Esto también mejora la calidad: menos columnas, menos ruido.

Explicabilidad: qué puedes prometer

La explicabilidad no es un único concepto. Puedes ofrecer:

  • Explicaciones globales: qué features importan en promedio (importancia, SHAP agregado).
  • Explicaciones locales: por qué esta predicción concreta (SHAP, LIME, contrafactuales).
  • Transparencia del proceso: qué datos, versión y reglas se aplicaron, aunque el modelo sea una caja negra.

Ninguna técnica prueba causalidad. Una explicación SHAP describe la contribución al score del modelo, no el efecto causal de la variable en el mundo. Sé explícito sobre esa diferencia.

1

Un rechazo explicable

Un modelo de crédito rechaza una solicitud. Una explicación útil no es «el modelo dio 0.31». Es: «su ratio de endeudamiento y el historial de pagos reciente son los factores que más redujeron su puntuación; puede revisar la información si cree que hay un error». Eso es accionable, verificable y respetuoso.

Requisito técnico: registrar la versión del modelo, las features de entrada y las contribuciones en el momento de la decisión. Sin ese registro, la explicación posterior es una reconstrucción incierta.

Auditoría mínima

  1. Identificador único de la decisión.
  2. Timestamp y versión del modelo.
  3. Entradas relevantes (con la debida protección de datos).
  4. Salida y umbral aplicado.
  5. Regla o intervención humana, si la hubo.
  6. Política de retención y acceso.
Documentación del modelo Un «model card» resume propósito, datos, métricas por subgrupo, limitaciones y usos prohibidos. No es burocracia: es lo que permite que otra persona evalúe el sistema sin leer todo el código. Inclúyelo como parte del artefacto.
Ejercicio 10.7 · Auditoría de un caso

Un modelo de selección de currículos prioriza candidatos. Enumera los riesgos de gobernanza, qué datos podrían ser problemáticos y qué controles establecerías antes de usarlo. ¿Qué explicarías a un candidato rechazado?

Orientación: riesgo de sesgo por género, origen o institución; datos históricos que reproducen discriminación; falta de explicabilidad; uso indebido del score como decisión automática. Controles: auditoría por subgrupo, revisión humana, exclusión de variables protegidas y proxies, documentación y posibilidad de apelación. Al candidato: factores objetivos y vía de revisión, sin revelar información de terceros.

Lección 10.8

Checklist de producción y cierre

18 minChecklistCierre del módulo

Este es el cierre operativo del curso. Antes de decir que un modelo está «listo para producción», recorre esta lista. No es una formalidad: cada punto corresponde a un fallo que ocurre con frecuencia.

Antes de desplegar

□
Problema y métrica definidos. La métrica principal está alineada con el coste real y existe una baseline.
□
Datos versionados y documentados. Se conoce la fuente, la fecha, la licencia y el hash del dataset de entrenamiento.
□
Pipeline reproducible. Preprocesado y modelo viajan juntos; las versiones están fijadas; un test de humo reproduce una predicción conocida.
□
Evaluación honesta. Test independiente, sin fuga, con métricas por subgrupo y comparación con la versión anterior.
□
Contrato de entrada validado. Tipos, rangos y categorías; errores claros en lugar de predicciones silenciosas.
□
Latencia y capacidad medidas. En el hardware real, con el preprocesado incluido, bajo carga razonable.
□
Seguridad y privacidad revisadas. Sin secretos en la imagen, usuario no root, datos minimizados y acceso restringido.
□
Rollback probado. Existe una versión anterior funcional y un procedimiento documentado para volver.

Después de desplegar

□
Monitoreo técnico activo. Latencia, errores y saturación con alertas que alguien atiende.
□
Monitoreo de datos activo. Nulos, rangos, categorías nuevas y drift por feature.
□
Monitoreo de modelo y negocio. Distribución de scores, tasa de positivos y métricas de impacto cuando llegan las etiquetas.
□
Registro de decisiones. Versión, entrada, salida y revisión humana cuando aplica.
□
Plan de reentrenamiento. Disparadores claros: drift sostenido, caída de métrica, cambio de política o nuevos datos.
□
Documentación viva. Model card, limitaciones conocidas y contactos de responsabilidad.
El modelo no es el sistema Puedes tener un F1 excelente y un sistema frágil. La calidad de un producto de ML se mide por la combinación de modelo, datos, servicio, monitoreo y personas. Un modelo mediocre con buen monitoreo suele ser más útil que uno brillante sin observabilidad.

Errores que deberías evitar

  • Desplegar sin un test de humo del artefacto.
  • Confiar en que el preprocesado de producción coincide con el de entrenamiento.
  • Monitorear solo latencia y errores HTTP.
  • No versionar datos ni semillas.
  • Ignorar la deriva porque «el modelo funcionaba en el test».
  • Automatizar decisiones de alto impacto sin revisión humana.
Cierre del módulo Has recorrido el camino desde un notebook hasta un servicio observable. La idea central: la reproducibilidad y el monitoreo no son extras, son parte del modelo. Si no puedes reconstruir cómo se generó una predicción y detectar cuándo deja de ser válida, no tienes un sistema de ML: tienes una demostración.
Ejercicio 10.8 · Auditoría final

Toma un modelo de los módulos anteriores y audítalo con esta checklist. Marca cada punto como cumplido, parcial o ausente. Elige los tres ausentes con mayor riesgo y propón una acción concreta con responsable y fecha.

Orientación: los ausentes más comunes son versionado de datos, test de humo, monitoreo de drift y plan de rollback. Prioriza por impacto y probabilidad: un modelo de alto impacto sin rollback ni monitoreo es el riesgo más grave. La acción debe ser específica y verificable, no «mejorar el monitoreo».

Curso de Machine Learning · teoría, matemáticas y práctica en Python Progreso local · 0% completado · Hecho para estudiar en cualquier lugar