Data drift y concept drift en producción: Evidently AI o NannyML según el caso
Detectar que un modelo se degrada en producción ya no depende solo de esperar a que baje una métrica de negocio; el ángulo que falta en la mayoría del contenido sobre este tema es elegir la herramienta según qué señal tienes disponible, no repetir el mismo ejemplo de DataDriftPreset. Y hay un problema más urgente todavía: el código de Evidently AI que circulaba en artículos de 2025 ya no funciona tal cual. La librería rehízo su API a fondo, y cualquier ejemplo que siga usando evidently.report.Report con metrics=[DataDriftPreset()] se rompe contra las versiones actuales del paquete.
Data drift y concept drift no son lo mismo
Data drift es un cambio en la distribución estadística de las variables de entrada de un modelo respecto a los datos con los que se entrenó, sin que necesariamente cambie la relación entre esas entradas y lo que el modelo predice. Concept drift es distinto: la relación entre las entradas y la salida cambia, aunque la distribución de las entradas se mantenga igual. El ejemplo de manual es un detector de fraude: el volumen y la forma de las transacciones pueden no cambiar (sin data drift), pero si los estafadores cambian de táctica, la relación entre el patrón de la transacción y si es fraude sí cambia (concept drift puro). En producción ambos tipos suelen coincidir, y distinguirlos importa porque piden mitigaciones distintas: el primero se corrige muchas veces con reentrenamiento sobre datos recientes, el segundo puede necesitar rediseñar qué señales usa el modelo.
Los criterios que deciden qué herramienta usar
Antes de mirar tablas de funcionalidades, conviene fijar qué preguntas determinan la elección real:
- ¿Tienes etiquetas reales (ground truth) llegando en producción, y con qué retraso? Si las tienes a tiempo, puedes medir rendimiento directamente. Si no, necesitas una técnica de estimación.
- ¿El riesgo es univariante o multivariante? Un cambio columna a columna es fácil de ver comparando histogramas; un cambio en cómo se correlacionan dos variables entre sí puede no mover ninguna distribución individual.
- ¿Quieres una librería que corres tú, o un dashboard hosteado con alertas gestionadas? Ambas opciones principales son open source, pero una tiene además una capa cloud de pago.
- ¿El problema es de clasificación o de regresión? Las técnicas de estimación de rendimiento sin etiquetas son distintas según el tipo de problema.
Evidently AI, Evidently Cloud y NannyML frente a frente
| Criterio | Evidently AI (librería OSS) | Evidently Cloud | NannyML |
|---|---|---|---|
| Detección de drift univariante | Sí, DataDriftPreset | Sí, sobre la misma librería | Sí, UnivariateDriftCalculator |
| Detección de drift multivariante | Limitada | Limitada | Sí, reconstrucción basada en PCA |
| Estimar rendimiento sin ground truth | No es su foco principal | No es su foco principal | Sí, CBPE para clasificación y DLE para regresión |
| Dashboard hosteado con alertas | No, solo HTML/JSON local | Sí | No, solo librería |
| Coste | Gratis, Apache 2.0 | De pago sobre la capa gratuita | Gratis, Apache 2.0 |
Evidently AI es un framework de código abierto con más de 40 millones de descargas que evalúa, prueba y monitoriza datos y sistemas de IA, según su página de introducción; la versión actual de la librería es la 0.7.21, publicada en marzo de 2026 según su ficha en PyPI. NannyML, por su parte, va en la versión 0.13.1 (julio de 2025) y se describe a sí misma como una librería para "estimar el rendimiento del modelo tras el despliegue sin acceso a las etiquetas, detectar data drift, y enlazar las alertas de drift con cambios reales en el rendimiento del modelo", según su ficha en PyPI.
El código de Evidently cambió de raíz: así se ve la API actual
Si tu referencia es un artículo de 2025 con from evidently.report import Report y from evidently.metric_preset import DataDriftPreset, olvídalo: ese módulo ya no existe con ese nombre. La documentación oficial actual importa desde evidently y evidently.presets, y además exige envolver cada DataFrame en un objeto Dataset con un esquema explícito antes de poder compararlos:
import pandas as pd
from evidently import Dataset, DataDefinition, Report
from evidently.presets import DataDriftPreset
# Esquema: qué columnas son numéricas y cuáles categóricas
schema = DataDefinition(
numerical_columns=["metros_cuadrados", "antiguedad_anos", "precio"],
categorical_columns=["num_habitaciones"],
)
referencia = Dataset.from_pandas(pd.DataFrame(datos_entrenamiento), data_definition=schema)
produccion = Dataset.from_pandas(pd.DataFrame(datos_produccion), data_definition=schema)
report = Report([DataDriftPreset()])
resultado = report.run(produccion, referencia)
resultado.save_html("data_drift_report.html")
El orden de los argumentos en run() también cambió: ya no son los parámetros nombrados reference_data=/current_data= del código de 2025, sino dos objetos Dataset posicionales. Para estimar rendimiento con etiquetas reales disponibles, la misma documentación confirma la existencia de presets adicionales como ClassificationPreset, ClassificationQuality y ClassificationQualityByLabel en su catálogo de métricas, siguiendo el mismo patrón de importación desde evidently.presets.
NannyML para lo que Evidently no resuelve bien
Cuando no tienes etiquetas reales a tiempo, o sospechas que el problema no está en los valores individuales de cada columna sino en cómo se relacionan entre sí, NannyML cubre dos huecos concretos que Evidently no ataca de frente: estima el rendimiento con CBPE (Confidence-Based Performance Estimation, clasificación) y DLE (Direct Loss Estimation, regresión) usando la confianza de las propias predicciones como proxy, y detecta drift multivariante mediante reconstrucción de datos basada en PCA, monitorizando el error de reconstrucción a lo largo del tiempo. La detección univariante, con la documentación oficial de quickstart como fuente, se ve así en su versión actual:
import nannyml as nml
columnas_a_monitorizar = ["metros_cuadrados", "antiguedad_anos", "num_habitaciones"]
calculador = nml.UnivariateDriftCalculator(
column_names=columnas_a_monitorizar,
chunk_size=5000,
)
calculador.fit(datos_referencia)
resultado_drift = calculador.calculate(datos_produccion)
ranking = nml.AlertCountRanker().rank(resultado_drift)
resultado_drift.filter(column_names=columnas_a_monitorizar).plot().show()
Nótese que esta API ya no usa timestamp_column_name ni chunk_period como parámetro obligatorio del calculador univariante; el troceo por chunk_size es el patrón vigente. La detección multivariante con reconstrucción PCA resuelve justo el caso donde la comparación columna a columna no basta: dos variables pueden mantener cada una su distribución individual intacta mientras su correlación cambia por completo, y ese es exactamente el tipo de deriva que un histograma comparado columna por columna no muestra.
Qué elegir según tu escenario
- Si tienes etiquetas reales llegando con poco retraso: Evidently AI con un preset de clasificación o regresión sobre el lote ya cerrado es la opción más directa.
- Si no tienes etiquetas y necesitas estimar el impacto en rendimiento: NannyML con CBPE (clasificación) o DLE (regresión) es la herramienta diseñada específicamente para ese hueco.
- Si solo necesitas vigilar que las variables de entrada no se muevan: Evidently AI con
DataDriftPresetes la opción más simple y con mejor documentación de visualización en HTML. - Si sospechas de un cambio en cómo se relacionan las variables entre sí, no solo en sus valores individuales: NannyML con detección multivariante basada en reconstrucción PCA es la única de las dos que ataca ese problema de frente.
- Si necesitas alertas gestionadas y que un equipo no técnico pueda revisar un dashboard sin tocar código: Evidently Cloud sobre la misma librería, asumiendo el coste adicional frente a la versión open source.