Facsímil 08 · Completo

La ciencia de los datos

Datos, decisión algorítmica, sesgos, pipelines y análisis aplicado como la materia prima que condiciona cualquier sistema de IA.

Contenido disponible
8 de 8 capítulos listos
Contenido completo, pendiente de revisión editorial final.
Estado editorial
Completo
Lectura web generada desde los capítulos Markdown originales.

Sobre esta edición

Esta página se genera desde capítulos Markdown propios del facsímil. Las fórmulas se renderizan con KaTeX, los mapas con Mermaid y las notas al pie se mantienen junto al texto para leer el facsímil como una pieza autónoma, no como una exportación del taller.

Capítulo 01

Facsímil 8 · La ciencia de los datos

Capítulo 01: Datos, datasets y linaje: la primera decisión de IA

Qué deberías poder hacer al terminar

Este facsímil cambia el foco. Hasta ahora hemos hablado de modelos, APIs, agentes, operación, evaluación, calibración e interpretabilidad. Pero todos esos sistemas tienen una pieza anterior que condiciona casi todo: qué datos entran, de dónde vienen, para qué pueden usarse y cómo sabemos que no nos estamos engañando.

La frase central del capítulo es esta:

Un dataset no es una carpeta con filas. Es una decisión técnica congelada.

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Distinguir dato, ejemplo, dataset y artefacto derivado.No llamas “datos” a cualquier texto metido en un prompt.
Diseñar un contrato de datos mínimo.Defines columnas, splits, licencias, sensibilidad, owner y checks.
Explicar linaje.Puedes responder qué fuente produjo cada fila y qué hash identifica el snapshot.
Detectar leakage básico.Sabes buscar duplicados o equivalencias entre train, validation y test.
Separar uso de entrenamiento, evaluación y consulta.No usas el mismo dato para todo si su licencia o finalidad no lo permite.
Conectar datos con RAG, fine-tuning y evals.Ves que documentos, chunks, embeddings, labels y trazas son artefactos de datos.
Ejecutar un gate de datos.Generas un reporte, una dataset card y una decisión técnica reproducible.

La ciencia de datos en IA no empieza entrenando. Empieza preguntando: ¿puedo usar este dato para esta decisión?

La escena: el modelo falla, pero el bug estaba en el dataset

Imagina un asistente académico que responde dudas sobre matrícula, becas, pagos y horarios. El equipo detecta errores en producción y lo primero que se propone es cambiar de modelo. Parece razonable: si la respuesta falla, el modelo será peor de lo esperado.

Pero al mirar los datos aparecen cosas menos vistosas:

HallazgoConsecuencia
Varias respuestas de evaluación también estaban en entrenamiento.La métrica era demasiado optimista.
Algunos documentos del corpus estaban obsoletos.El RAG citaba bien, pero citaba una fuente vieja.
Una licencia permitía consulta interna, no entrenamiento.El fine-tuning propuesto no era aceptable.
El campo producto cambió de nombre en producción.El modelo recibía una feature rota.
Las etiquetas se pusieron con criterios distintos según el equipo.La métrica mezclaba desacuerdos humanos con errores del modelo.

En ese punto, cambiar de modelo es secundario. El sistema no necesita más brillo; necesita DataOps.

Qué no es un dataset

Un dataset no es “unos CSV que encontré”, una carpeta de PDFs, una tabla de tickets o un export rápido de una herramienta interna. Eso puede ser una fuente de datos, pero todavía no es un dataset listo para ingeniería de IA.

Tampoco es un objeto neutral. La forma de recogerlo, filtrar filas, etiquetar casos, borrar columnas, crear splits y elegir qué queda fuera define qué aprenderá o evaluará el sistema.

Y no es intercambiable entre usos. Un dato puede servir para consultar en RAG, pero no para entrenar. Puede servir para evaluación interna, pero no para publicar resultados. Puede servir con metadatos, pero no si se separa de su fuente.

ConfusiónLectura de ingeniería
“Tengo datos, ya puedo entrenar”.Primero contrato, linaje, licencia, sensibilidad y splits.
“Es texto público, puedo usarlo para todo”.Hay que revisar licencia, finalidad, atribución y restricciones.
“Los embeddings no son texto”.Son datos derivados y deben protegerse como parte del corpus.
“La eval salió alta”.Si hay leakage, duplicados o etiquetas débiles, la métrica no vale lo que parece.
“Lo arreglamos limpiando después”.La limpieza sin contrato crea versiones imposibles de reproducir.

Datasheets for Datasets propuso documentar motivación, composición, recogida, preprocesamiento, usos y distribución de datasets para mejorar transparencia y responsabilidad técnica.1 Data Cards sigue esa línea con fichas de dataset orientadas a decisiones de uso y documentación práctica.2

Qué sí es un dataset para IA

En este libro llamaremos dataset a un conjunto de ejemplos con datos, metadatos, finalidad, propietario, versión, permisos, splits y checks verificables.

Ejemplo de fórmula: podemos escribirlo así para recordar qué piezas mínimas debe traer un dataset profesional. No es una definición universal de la literatura; es una notación de trabajo para este facsímil.

D=(X,Y,M,S,L,V,Q)D = (X, Y, M, S, L, V, Q)
SímboloSignificadoEjemplo
DDDataset.Casos de soporte académico.
XXEntradas o features.Texto del ticket, producto, canal, idioma.
YYEtiquetas o salidas esperadas.answer, ask_more, escalate.
MMMetadatos.Fuente, fecha, owner, licencia, sensibilidad.
SSSplits.train, validation, test.
LLLinaje.Hash del snapshot, documento origen, transformación.
VVVersión.support-cases@2026-06-06.
QQChecks de calidad.Schema, duplicados, missing, licencias, leakage.

Ejemplo de fórmula: cada fila también debería poder leerse como un objeto trazable. De nuevo, no pretende imponer un estándar único; sirve para que el alumno no olvide etiqueta, metadatos, split y linaje cuando mira una fila.

ei=(xi,yi,mi,si,li)e_i = (x_i, y_i, m_i, s_i, l_i)
SímboloSignificado
eie_iEjemplo individual.
xix_iEntrada del ejemplo.
yiy_iEtiqueta, referencia o salida esperada.
mim_iMetadatos del ejemplo.
sis_iSplit asignado.
lil_iLinaje del ejemplo.

La diferencia con “un CSV” es brutal: ahora el dataset tiene contrato. Puedes auditarlo, versionarlo, discutirlo y bloquear su uso si no cumple.

Cómo se estructura un dataset

Un dataset se estructura según la tarea. Esta frase parece obvia, pero evita muchos errores. No tiene la misma forma un dataset para clasificar tickets, un corpus RAG, un conjunto de preferencias, una tabla de features o una traza de agente.

La pregunta que conviene hacerse primero no es “qué formato uso”, sino cuál es la unidad de decisión. En clasificación puede ser una fila. En RAG puede ser un chunk con su documento origen. En preferencias puede ser una comparación entre dos respuestas. En agentes puede ser una trayectoria completa. Si no defines esa unidad, acabas mezclando cosas que parecen datos parecidos, pero que responden a decisiones distintas.

También hay una pregunta de tiempo: ¿este dato describe algo que ya estaba disponible cuando el sistema debía decidir, o se calculó después? Esta distinción marca la frontera entre un dataset honesto y un dataset que da ventaja irreal al modelo. En ingeniería de IA, el tiempo del dato importa tanto como el valor del dato.

Dataset tabular

Un dataset tabular suele tener una fila por ejemplo y columnas para entrada, etiqueta y metadatos:

case_id | split | product   | label
d001    | train | matricula | answer
ColumnaPor qué importa
case_idPermite rastrear una fila concreta.
splitEvita mezclar entrenamiento y evaluación.
source_idConecta el ejemplo con su fuente original.
labelDefine lo que aprende o mide el sistema.
licenseDecide si puede entrenarse, evaluarse o solo consultarse.
pii_riskDefine controles de tratamiento y revisión.

Este formato sirve para clasificación, regresión, scoring, routing, análisis por segmentos y evaluación con referencias.

La lectura importante es que una fila no debería ser solo “texto y etiqueta”. Si source_id falta, no sabes de dónde salió el caso. Si split falta, no sabes si el ejemplo mide o entrena. Si license falta, no sabes si el uso que quieres hacer es aceptable. Y si pii_risk falta, el sistema puede tratar todos los casos igual aunque unos necesiten más cuidado que otros.

En un proyecto real, muchas discusiones se resuelven mirando estas columnas. Producto pregunta si el asistente puede contestar consultas de becas; datos mira cuántos ejemplos de becas hay por split; legal o compliance mira permisos; ingeniería mira si el schema se mantiene estable. Esa es la diferencia entre un CSV suelto y un dataset gobernable.

Dataset JSONL para LLMs

En LLMs se usa mucho JSONL porque cada línea puede representar una conversación, una instrucción, una preferencia o una traza:

{"prompt":"Resume","response":"Falta dato","split":"train"}
{"prompt":"Decide","response":{"action":"ask_more"},"split":"test"}

Lo importante no es que sea JSON. Lo importante es que cada línea sea independiente, versionable y validable. Si una línea trae messages, tools, expected_output, rubric_id o trace_id, el contrato debe declararlo.

JSONL se usa mucho porque encaja bien con pipelines: puedes leer línea a línea, validar ejemplos de forma aislada, partir en splits y detectar qué registro falló sin cargar un archivo gigante completo. Para un alumno de ingeniería, esta ventaja es muy concreta: si la línea 842 rompe el contrato, no tienes que interpretar una conversación entera o un export opaco; puedes señalar el ejemplo exacto.

Hay otra consecuencia: el orden de campos no es el contrato. El contrato vive en lo que esperas de cada campo. prompt puede ser texto plano, pero response puede ser texto, JSON estructurado o una lista de mensajes. Si mañana cambias de prompt/response a messages, no has cambiado solo nombres: has cambiado la interfaz de datos que alimenta al sistema.

Dataset de RAG

Un corpus RAG no es solo texto. Cada chunk debería traer metadatos:

{
  "document_id": "doc-pay-001",
  "chunk_id": "doc-pay-001#001",
  "source_uri": "intranet://academico/pagos/justificantes",
  "version": "2026-05-02",
  "text": "El justificante de pago se revisa...",
  "license": "internal_retrieval_allowed",
  "expires_at": "2026-12-31"
}
CampoPregunta que responde
document_id¿Qué documento produjo este chunk?
chunk_id¿Qué fragmento exacto se recuperó?
source_uri¿Dónde está la fuente original?
version¿Qué versión estaba vigente?
expires_at¿Cuándo caduca esta evidencia?
license¿Puede recuperarse, indexarse o mostrarse?

Si un RAG falla, muchas veces el problema no es el modelo. Puede ser un chunk sin fecha, una fuente obsoleta, un embedding generado con otro modelo, metadatos incompletos o un índice que no refleja el snapshot esperado.

Piensa en una consulta académica sobre pagos. Si el retriever encuentra un fragmento correcto pero de una normativa antigua, el modelo puede sonar seguro y aun así guiar mal. Por eso version y expires_at no son decoración: permiten decidir si una evidencia sigue viva. En RAG, recuperar “algo parecido” no basta; hay que recuperar algo pertinente, vigente y permitido.

Además, el chunk es un dato derivado. Se ha creado al partir un documento, quizá después de limpiar HTML, pasar OCR, eliminar cabeceras y generar embeddings. Cada paso puede cambiar el resultado. Si no guardas el document_id, la versión del chunking y el modelo de embedding, reconstruir un fallo se vuelve una conversación de memoria en vez de una investigación técnica.

Dataset de preferencias

Un dataset de preferencias enseña comparaciones:

{
  "prompt": "Responde una consulta sin evidencia",
  "chosen": "No tengo evidencia suficiente...",
  "rejected": "La anulacion siempre se puede hacer...",
  "preference_policy": "abstencion_con_evidencia"
}

Aquí el dato no dice solo “esta respuesta es buena”. Dice: “entre estas dos respuestas, bajo esta política, preferimos esta”. Eso exige documentar quién etiquetó, con qué rúbrica, en qué fecha y para qué entrenamiento o evaluación se puede usar.

La parte delicada es que una preferencia siempre depende de criterio. En un asistente académico quizá preferimos una respuesta que pregunta por documentación antes que otra que inventa una solución. En un asistente de programación quizá preferimos una respuesta que añade test y explica el riesgo. La preferencia no flota en el aire: necesita una política escrita.

Si no guardas preference_policy, un equipo puede interpretar que chosen significa “más amable”, otro que significa “más corta” y otro que significa “más correcta”. El dataset parecerá grande, pero estará enseñando señales mezcladas. Para post-entrenamiento y evaluación comparativa, esa ambigüedad es veneno lento: no rompe el script, pero degrada la decisión.

Dataset de trazas

En agentes, un dataset útil puede ser una traza:

{
  "trace_id": "tr_001",
  "goal": "resolver ticket",
  "state": "falta evidencia",
  "action": "retrieve_documents",
  "observation": "2 chunks recuperados",
  "outcome": "ask_more"
}

Este formato sirve para evaluar trayectorias, herramientas, costes, pasos innecesarios, criterios de parada y handoffs. Si solo guardamos la respuesta final, perdemos el dato que explica cómo llegó el sistema hasta allí.

La traza cambia la pregunta. Ya no miras solo si la respuesta final fue aceptable; miras si el sistema eligió bien los pasos. ¿Consultó una herramienta cuando hacía falta? ¿Pidió aclaración cuando la evidencia era insuficiente? ¿Repitió una llamada sin ganar información? ¿Terminó por el motivo correcto? Esa información es oro para ingeniería porque permite mejorar el sistema sin tocar necesariamente el modelo.

También convierte observabilidad en dataset. Las trazas que vimos en facsímiles anteriores no sirven solo para depurar una incidencia puntual. Bien muestreadas y revisadas, pueden transformarse en evals, casos de regresión, datasets de herramientas o ejemplos para entrenar políticas de orquestación.

Dataset de features

En ML clásico y sistemas híbridos aparece otra estructura: una entidad con features calculadas en un tiempo concreto.

entity_id | event_time | wait_days | label
s001      | 2026-05-01 | 12        | urgent

Aquí hay una trampa crítica: las features deben existir en el momento de la predicción. Si calculas una feature usando información posterior al evento, el modelo aprende con ventaja irreal. Este error se llama leakage temporal y suele producir métricas preciosas en notebook y decepción en producción.

El campo event_time es el ancla. Si quieres predecir el 1 de mayo si un caso será urgente, no puedes usar una variable calculada el 5 de mayo. Parece una obviedad, pero ocurre mucho cuando se agregan tablas históricas sin respetar la fecha de disponibilidad de cada columna.

Por eso un feature store no es simplemente “una base de datos con variables”. Su valor está en mantener la misma definición de feature para entrenamiento e inferencia, controlar frescura, guardar versiones y evitar que el notebook use una realidad distinta a la que verá el servicio en producción.

Taxonomía práctica de datasets en IA

Tipo de datasetUnidad mínimaUso típicoRiesgo principal
Tabular supervisadoFila con features y etiqueta.Clasificación, regresión, routing.Leakage, desbalance, etiqueta ruidosa.
Corpus RAGDocumento o chunk con metadatos.Recuperación y citas.Fuente obsoleta, chunk sin linaje.
InstruccionesEntrada y salida esperada.SFT, evaluación, formato.Enseñar estilo sin cubrir casos reales.
PreferenciasPrompt, respuesta elegida y rechazada.Preferencias, ranking, post-entrenamiento.Rúbrica ambigua o etiqueta inconsistente.
TrazasEstado, acción, observación y resultado.Agentes y EvalOps.Guardar solo el final y perder diagnóstico.
FeaturesEntidad, tiempo y variables calculadas.Modelos online/offline.Desalineación entre entrenamiento e inferencia.
MultimodalTexto, imagen/audio/video y metadatos.Visión, documentos, OCR, audio.Calidad de OCR, resolución, permisos.
Producción muestreadaRun real revisada.Drift, regresiones, mejora continua.Sesgo de muestreo y falta de owner.

Esta tabla no pretende encerrar todos los casos. Sirve para que el alumno aprenda a hacer una separación mental: qué unidad estoy midiendo, qué uso tendrá y cuál es el riesgo dominante. Si el dataset es RAG, el riesgo dominante suele estar en la fuente y el linaje. Si es preferencias, en la rúbrica. Si es features, en el tiempo y la consistencia entre entrenamiento e inferencia.

Una buena práctica es nombrar el dataset por su uso, no solo por su origen. tickets_soporte.csv dice poco. support_cases_eval_v2026_06 ya indica una finalidad. support_cases_sft_v2026_06 indica otra. Puede venir de la misma fuente, pero no tiene el mismo contrato ni debería tener los mismos permisos.

Hugging Face Datasets popularizó una interfaz donde un dataset puede cargarse como DatasetDict, con splits como train, validation y test, y operaciones reproducibles de carga, transformación y procesamiento.3 No hace falta usar esa librería para aprender la idea: un dataset moderno debe declarar estructura, particiones y transformaciones de forma explícita.

Fecha de corte del estado del arte

Fecha de corte: 6 de junio de 2026.
Fuentes consultadas: Datasheets for Datasets, Data Cards, Model Cards, Hidden Technical Debt in Machine Learning Systems, Software Engineering for Machine Learning, TFX, ML Test Score, ODCS, TensorFlow Data Validation, ML Metadata, OpenLineage, DataHub, Great Expectations, Feast, Evidently, DVC, lakeFS, Delta Lake, Apache Iceberg y Hugging Face Datasets.

Lo estable es la disciplina: datos versionados, schema verificable, linaje, documentación, validación, separación de splits, evaluación por segmentos y monitorización de cambios. Lo coyuntural son herramientas, paneles, proveedores y formatos exactos.

Las fuentes de este bloque no dicen todas lo mismo, y eso es bueno. Unas hablan de documentación, otras de pipelines, otras de contratos, otras de linaje y otras de monitorización. Juntas dibujan una idea muy importante: en IA, la calidad del sistema no se puede separar de la vida del dato. El dato nace, cambia, se transforma, se versiona, se consume y se degrada.

Sculley et al. explicaron que los sistemas de ML acumulan deuda técnica especial: dependencias de datos, realimentaciones escondidas, configuraciones frágiles y cambios no locales.4 Amershi et al. mostraron desde Microsoft que construir ML exige prácticas de ingeniería diferentes al software clásico, especialmente alrededor de datos, experimentos y evolución del sistema.5

TFX formalizó una plataforma de ML a escala de producción donde ingestión, validación, transformación, entrenamiento, evaluación y serving forman un pipeline reproducible.6 El ML Test Score propuso una rúbrica para madurez de producción que incluye tests de datos, validación, monitorización y gestión de cambios.7

En herramientas actuales, ODCS define una estructura abierta para contratos de datos con secciones de fundamentos, schema, referencias, calidad, soporte, equipo, roles y acuerdos de servicio.8 TensorFlow Data Validation analiza datos, genera estadísticas, infiere schema y detecta anomalías contra expectativas.9 ML Metadata registra artefactos, ejecuciones y contextos para recuperar linaje en workflows de ML.10

OpenLineage aporta un estándar abierto para capturar metadatos de linaje en ejecuciones de jobs.11 DataHub se presenta como catálogo de datos para metadatos, búsqueda, linaje, perfilado, gobernanza y contratos.12 Great Expectations organiza calidad de datos mediante expectations reutilizables.13

Feast es un feature store que separa offline store para generar datos de entrenamiento y online store para servir features de baja latencia.14 Evidently documenta métricas de drift para comparar distribuciones y detectar cambios en datos o modelos.15 DVC, lakeFS, Delta Lake y Apache Iceberg tratan el problema de reproducibilidad y versionado desde ángulos distintos: proyectos ML versionados, data lakes con semántica tipo Git, time travel, schema enforcement, snapshots y evolución de schema.16171819

La lección práctica para este facsímil: los datos no son un paso previo; son parte del sistema.

Arquitectura de datos para IA

Una arquitectura mínima de datos para IA tiene varias capas. No todas hacen falta en un proyecto pequeño, pero todas deben existir como pregunta mental:

CapaQué guardaPregunta que responde
FuenteTabla, documento, log, traza, imagen o evento original.¿De dónde salió este dato?
IngestiónCopia controlada del dato.¿Cuándo entró y bajo qué contrato?
ValidaciónEstadísticas, schema, expectations y anomalías.¿Cumple lo prometido?
TransformaciónLimpieza, chunking, OCR, features, embeddings.¿Qué se cambió y con qué versión?
VersionadoSnapshot, hash, commit, tabla Delta/Iceberg, DVC/lakeFS.¿Puedo reconstruir el mismo dataset?
CatálogoOwner, descripción, sensibilidad, contrato, documentación.¿Quién responde por esto y para qué sirve?
LinajeJobs, inputs, outputs, columnas y artefactos derivados.¿Qué rompemos si cambia esta fuente?
ConsumoEntrenamiento, RAG, eval, dashboard, agente, producto.¿Qué sistema usa este dato?
MonitorizaciónDrift, frescura, calidad, cobertura, feedback.¿Producción sigue pareciéndose a lo validado?

La arquitectura correcta depende del tamaño. Para un proyecto didáctico, un CSV, un contrato JSON y un script bastan. Para una organización, quizá necesitas catálogo, feature store, lineage estándar, lakehouse y gates en CI. Lo importante es no saltarse la pregunta: qué evidencia tengo de que este dato sigue siendo el dato que creo que es.

Una forma sencilla de leer esta arquitectura es seguir una fila. Primero existe en una fuente: un ticket, un documento, una traza. Después entra en una zona controlada mediante ingestión. Luego se valida: tipos, nulos, valores permitidos, licencias. Más tarde se transforma: quizá se limpia, se trocea, se convierte en embedding o se convierte en feature. Finalmente se consume: entrena, evalúa, alimenta un RAG o aparece en un dashboard.

Si cada paso deja evidencia, puedes investigar un fallo con calma. Si no la deja, dependes de recordar quién exportó qué archivo, con qué filtro y en qué día. Eso no escala, y además impide que un alumno aprenda ingeniería reproducible. La meta no es montar una plataforma enorme desde el primer día; la meta es que incluso el proyecto pequeño tenga una línea clara entre fuente, transformación, versión y decisión.

Ciclo de vida de datos para IA Diagrama en blanco y negro que muestra fuentes, ingestión, validación, transformación, versionado, consumo y monitorización. Ciclo de vida: el dato viaja, cambia y deja evidencia Fuente tickets documentos logs trazas owner · permiso Ingestión snapshot_id created_at source_uri no se ingiere sin contrato Validación schema missing licencia split leakage gate: pass/review/block Transformación limpiar chunking features embeddings versiona cada receta Versionado dataset_hash contract_hash table_snapshot reproducir o revertir Consumo train RAG eval agentes cada uso tiene permiso Catálogo dataset card owner sensibilidad contrato descubrible y revisable Monitorización frescura drift calidad cobertura producción cambia Si cambia el dato, cambia el sistema aunque no cambie el modelo. IA para gente curiosa / Facsímil 08 / Capítulo 01 / 686f6c61
El dato no se queda quieto: se ingiere, valida, transforma, versiona, consume y monitoriza. Cada paso debe dejar evidencia.

Anatomía de un contrato de datos para IA

Contrato de datos para IA Diagrama en blanco, negro y gris que conecta fuentes, contrato, validación, splits, artefactos derivados, linaje, gates y decisión de uso. Un dataset usable tiene contrato, linaje y gate La pregunta no es “cuántas filas tengo”, sino si puedo usar esas filas para esta decisión concreta. 1 · Fuentes Origen documentos tickets logs trazas Cada fuente necesita owner, fecha y permiso. 2 · Contrato Especificación required_columns allowed_labels allowed_licenses min_rows_per_split El contrato convierte opiniones en checks. 3 · Validación Checks schema · missing case_id único licencia compatible PII permitida leakage entre splits Si falla aquí, no entrenes todavía. 4 · Splits Separación train validation test holdout futuro La evaluación solo vale si no vio la respuesta. Artefactos derivados chunks embeddings features labels generadas No son inocuos: heredan permiso y linaje. Linaje dataset_hash contract_hash source_id transform_version Sin hashes, no hay repetición. Gate schema_ok license_ok split_ok lineage_ok Salida: pass · review · block Decisión entrenar evaluar indexar bloquear uso El uso permitido sale del contrato. data_ok = schema_ok AND lineage_ok AND license_ok AND split_ok AND quality_ok La evaluación, el RAG y el fine-tuning heredan la salud del dataset. Si el dato no tiene contrato, el sistema tampoco. IA para gente curiosa / Facsímil 08 / Capítulo 01 / 686f6c61
El contrato de datos convierte una colección de filas en un artefacto que puede usarse, bloquearse, versionarse y auditarse.

Las fórmulas que sí conviene saber

Ejemplo de fórmula: la primera fórmula útil no es estadística. Es de ingeniería y resume una política de release de datos. Podríamos añadir más condiciones en otro proyecto, pero si una de estas falla, el dataset no debería avanzar sin revisión.

data_ok=schema_oklineage_oklicense_oksplit_okquality_okdata\_ok = schema\_ok \land lineage\_ok \land license\_ok \land split\_ok \land quality\_ok
TérminoQué exige
schema_okColumnas, tipos y valores permitidos coinciden con el contrato.
lineage_okCada fila tiene fuente, fecha, owner y hash reproducible.
license_okEl uso previsto respeta licencia y consentimiento declarados.
split_okTrain, validation y test están separados sin fuga obvia.
quality_okNo hay missing, duplicados, etiquetas imposibles o señales rotas por encima del umbral.

La tasa de valores faltantes por columna puede escribirse como:

miss(c)=i=1n1[xi,c=]nmiss(c) = \frac{ \sum_{i=1}^{n} \mathbb{1}[x_{i,c}=\varnothing] }{n}
SímboloSignificado
miss(c)miss(c)Proporción de filas donde falta la columna cc.
nnNúmero de filas del dataset.
xi,cx_{i,c}Valor de la columna cc en la fila ii.
1\mathbb{1}Indicador: vale 1 si la condición se cumple, 0 si no.

Para leakage simple entre train y test podemos mirar huellas de texto:

leak(Dtrain,Dtest)=F(Dtrain)F(Dtest)F(Dtest)leak(D_{train}, D_{test}) = \frac{ |F(D_{train}) \cap F(D_{test})| }{ |F(D_{test})| }
SímboloSignificado
F(D)F(D)Conjunto de huellas normalizadas de ejemplos en un dataset.
DtrainD_{train}Split de entrenamiento.
DtestD_{test}Split de prueba.
leakleakProporción de ejemplos de test que aparecen también en train.

Esto no detecta todos los problemas. Un duplicado semántico puede no tener el mismo texto. Pero ya evita una trampa básica: evaluar con respuestas que el sistema pudo ver durante ajuste.

Para revisar balance de etiquetas podemos usar proporciones:

p(y=k)=nknp(y=k)= \frac{n_k}{n}
SímboloSignificado
p(y=k)p(y=k)Proporción de ejemplos con etiqueta kk.
nkn_kNúmero de ejemplos de esa etiqueta.
nnNúmero total de ejemplos.

Si una clase tiene muy pocos ejemplos, el modelo puede aprender a ignorarla y aun así sacar una métrica global aceptable. Por eso conviene mirar distribución de labels, productos, canales e idiomas.

La entropía resume cuán repartida está una distribución:

H(Y)=kp(y=k)logp(y=k)H(Y)= -\sum_k p(y=k)\log p(y=k)
SímboloSignificado
H(Y)H(Y)Entropía de la distribución de etiquetas.
p(y=k)p(y=k)Proporción de la etiqueta kk.

Una entropía baja no es necesariamente mala. Puede significar que el mundo real está desbalanceado. Lo importante es no confundir “realista” con “suficiente para entrenar o evaluar bien”.

Para drift entre una muestra de referencia PP y una muestra actual QQ, una medida sencilla es distancia total variation:

DTV(P,Q)=12iPiQiD_{TV}(P,Q)= \frac{1}{2} \sum_i |P_i-Q_i|
SímboloSignificado
PiP_iProporción de la categoría ii en la referencia.
QiQ_iProporción de la categoría ii en la muestra actual.
DTVD_{TV}Distancia entre distribuciones categóricas.

También se usa PSI (Population Stability Index) en entornos de scoring:

PSI=i(QiPi)logQiPiPSI = \sum_i (Q_i-P_i) \log \frac{Q_i}{P_i}
SímboloSignificado
PSIPSIÍndice de estabilidad poblacional.
PiP_iProporción esperada o de referencia.
QiQ_iProporción observada o actual.

No lo uses como oráculo. Úsalo como señal: si sube, mira la distribución, el tamaño muestral, la fecha, el origen y si la evaluación sigue representando producción.

Para etiquetas humanas, si dos personas anotan los mismos casos, conviene medir acuerdo. Una versión clásica es kappa de Cohen:

κ=pope1pe\kappa = \frac{p_o-p_e}{1-p_e}
SímboloSignificado
pop_oAcuerdo observado.
pep_eAcuerdo esperado por azar según las distribuciones de anotación.
κ\kappaAcuerdo corregido por azar.

Si las personas no se ponen de acuerdo, quizá el problema no es el modelo. Quizá la etiqueta está mal definida.

Los siete contratos que debería tener un dataset

Un contrato de datos no tiene que ser enorme para ser útil. Debe responder siete preguntas:

ContratoPreguntaEjemplo
Schema¿Qué columnas existen y qué valores son válidos?label solo puede ser answer, ask_more, escalate.
Linaje¿De dónde viene cada fila?source_id, created_at, owner, dataset_hash.
Uso permitido¿Para qué puede usarse?Entrenar, evaluar, consultar, indexar o solo revisar.
Sensibilidad¿Qué cuidado exige?Riesgo de PII bajo, medio o alto.
Splits¿Qué se usa para entrenar y qué para medir?train, validation, test.
Calidad mínima¿Qué bloquea uso?Missing, duplicado, licencia incompatible, etiqueta no permitida.
Decisión¿Qué hacemos con el resultado?pass, review, block.

Estos contratos no son burocracia. Son una forma de convertir intuiciones en reglas que se puedan revisar. Si alguien dice “este dataset es bueno”, podemos preguntar: ¿bueno para qué uso?, ¿con qué permisos?, ¿para qué población?, ¿con qué fecha de corte?, ¿con qué separación entre entrenamiento y evaluación? Un contrato no elimina la discusión, pero la vuelve concreta.

También evita que el dato cambie silenciosamente. Si un productor añade una columna, cambia el significado de label o deja de enviar source_id, el consumidor no debería enterarse semanas después por una caída de calidad. El contrato permite detectar el cambio en el momento en que entra al pipeline.

Esta idea conecta con model cards. Una model card documenta un modelo; una dataset card documenta el material que lo alimenta o lo evalúa.20 Las dos cosas se necesitan: un modelo sin datos documentados es difícil de interpretar; un dataset sin uso previsto puede acabar aplicado donde no toca.

Herramientas: qué problema resuelve cada una

No hay una herramienta única para “datos de IA”. Hay piezas distintas:

Herramienta o estándarResuelveSirve cuandoNo sustituye
ODCSContrato de datos legible y extensible.Varios equipos producen y consumen datos.La validación ejecutable si no conectas checks.
TensorFlow Data ValidationEstadísticas, schema y anomalías.Quieres perfilar y validar datasets de ML.Decidir si la licencia o finalidad son correctas.
ML MetadataLinaje de artefactos, ejecuciones y contextos.Tienes pipelines ML reproducibles.Un catálogo de negocio completo.
OpenLineageEstándar de eventos de linaje de jobs.Necesitas linaje entre orquestadores y sistemas.Documentación semántica de cada campo.
DataHubCatálogo, metadatos, linaje y gobernanza.Una organización necesita descubrir y gobernar datos.Checks específicos de entrenamiento si no los defines.
Great ExpectationsExpectations y suites de calidad.Quieres tests de datos repetibles.Versionado de snapshots o linaje completo.
FeastFeature store online/offline.Necesitas features consistentes en train e inferencia.Limpieza de datos fuente o evaluación de modelo.
EvidentlyDrift y monitorización de datos/modelos.Comparas referencia contra producción.Arreglar por sí solo una distribución que cambió.
DVCVersionado de datos y pipelines con Git.Equipos pequeños o medianos quieren reproducibilidad ML.Catálogo empresarial o tabla transaccional.
lakeFSVersionado tipo Git sobre data lake.Necesitas ramas, commits y rollbacks de datos a escala.Validación semántica de columnas.
Delta LakeTablas con transacciones, schema enforcement y time travel.Lakehouse con necesidad de historial y rollback.Contrato de uso por dominio.
Apache IcebergTablas con snapshots y evolución de schema/partición.Data lake analítico con motores múltiples.Evaluación de calidad del dataset.
Hugging Face DatasetsCarga, splits y procesamiento reproducible.Datasets de NLP, multimodalidad y benchmarks.Gobernanza interna, licencias y owner.

Una forma práctica de ordenar estas herramientas es por pregunta. Si preguntas “¿qué columnas prometo?”, estás cerca de contratos. Si preguntas “¿cumple lo prometido?”, estás cerca de validación. Si preguntas “¿de dónde viene este resultado?”, estás cerca de linaje. Si preguntas “¿qué versión exacta usé?”, estás cerca de versionado. Y si preguntas “¿ha cambiado producción?”, estás cerca de monitorización.

En un proyecto pequeño no necesitas instalar todo. Puedes empezar con un contrato JSON, scripts de validación, hashes y una dataset card. En un proyecto de empresa, esas mismas ideas pueden acabar repartidas entre DataHub, OpenLineage, Great Expectations, Feast, DVC, lakeFS o tablas lakehouse. La escala cambia; la lógica no.

La lectura correcta para ingeniería no es “elige la herramienta de moda”. Es:

  1. ¿Dónde vive la verdad del dataset?
  2. ¿Cómo versiono el snapshot?
  3. ¿Cómo valido schema y calidad?
  4. ¿Cómo registro linaje?
  5. ¿Cómo documento finalidad y límites?
  6. ¿Cómo detecto que producción cambió?

Si no puedes responder esas seis preguntas, el stack todavía no está maduro aunque tenga nombres modernos. Y al revés: si puedes responderlas con herramientas simples, ya tienes una base didáctica y profesional bastante sana.

Cómo los datos alteran algoritmos

Un dataset no solo alimenta modelos; cambia el comportamiento de los algoritmos.

Algoritmo o sistemaQué dato lo condicionaQué pasa si el dato está mal
Árbol de decisiónFeatures categóricas, umbrales, missing.Puede elegir un split cómodo pero espurio.
Regresión logísticaEscala, colinealidad, balance de clases.Pesos inestables o clase minoritaria ignorada.
k-meansEscalado y distancia.Una variable con rango grande domina los clusters.
EmbeddingsCorpus, idioma, longitud y objetivo de entrenamiento.Vecinos semánticos pobres o sesgo de dominio.
RAGChunking, metadatos, vigencia, índice.Recupera texto irrelevante o caducado.
Fine-tuningPares entrada-salida y etiquetas.Aprende formato superficial o errores de anotación.
Preferenciaschosen, rejected, rúbrica.Optimiza gustos mal definidos.
Evaluador LLMCasos, criterios y ejemplos calibrados.Premia estilo en vez de verdad operativa.
AgenteTrazas, tools, outcomes y costes.Aprende trayectorias largas o acciones no útiles.

La parte incómoda es que muchos algoritmos parecen matemáticamente limpios cuando se explican en abstracto, pero se vuelven frágiles al tocar datos reales. Un k-means no “sabe” que una variable está en euros y otra en días; solo ve magnitudes. Una regresión no “sabe” que una clase minoritaria es crítica para negocio; solo optimiza sobre lo que le das. Un retriever no “sabe” que un documento caducó si no lo marcas.

Esto no resta importancia a los algoritmos. Al contrario: para usarlos bien hay que respetar sus supuestos. Si el algoritmo usa distancia, revisa escalado. Si usa etiquetas, revisa criterios de anotación. Si usa ranking, revisa qué documentos pueden aparecer arriba. Si usa trazas, revisa si esas trazas representan la operación real o solo casos cómodos.

Un ejemplo sencillo: si un dataset de soporte tiene casi todo answer y muy pocos ask_more, un clasificador puede responder siempre y sacar buen accuracy. Pero producto necesita saber cuándo preguntar. En ese caso, el problema no es solo el algoritmo: el dataset no representa suficientemente la decisión que queremos automatizar.

Otro ejemplo: en RAG, dos chunks pueden tener texto parecido, pero uno está vigente y otro caducado. Si no guardas version y expires_at, el retriever puede hacer lo que le pediste técnicamente y aun así devolver evidencia mala.

La ingeniería de datos para IA consiste justo en esto: mirar dónde se rompen los supuestos antes de culpar al modelo. A veces el modelo falla; muchas otras, el dataset no estaba contando el mundo que creíamos.

Datasets en LLMs: no solo entrenamiento

En sistemas con LLMs, la palabra datos aparece en muchas capas:

CapaArtefacto de datosPregunta de ingeniería
Pre-entrenamientoCorpus masivo.¿Qué mezcla de idioma, dominio y calidad aprende el modelo base?
SFT o ajustePares entrada-salida.¿Enseñan formato y comportamiento estable?
PreferenciasComparaciones o rankings.¿Qué criterio humano o automático se está optimizando?
RAGDocumentos, chunks y metadatos.¿La fuente está vigente, citada y recuperable?
EmbeddingsVectores derivados de texto o imagen.¿Se protegen como parte del corpus?
EvalsCasos, referencias y rúbricas.¿Separan baseline y candidate con evidencia?
ObservabilidadTraces, errores y feedback.¿Se pueden convertir en regresiones o mejoras del dataset?

Esta tabla ayuda a desmontar una confusión habitual: “datos de LLM” no significa solo corpus de entrenamiento. Un documento de ayuda puede no tocar jamás los pesos del modelo y aun así condicionar una respuesta mediante RAG. Una traza de producción puede no entrenar nada hoy, pero convertirse mañana en un caso de evaluación. Una conversación puede servir para mejorar formato, pero no para actualizar conocimiento vivo.

La clave: un dato cambia de papel según su uso. Un documento puede ser fuente RAG, caso de evaluación, ejemplo de fine-tuning o evidencia de una incidencia. Cada uso necesita permiso y contrato.

Por eso el contrato debe hablar de usos, no solo de columnas. La misma fila puede estar permitida para evaluación interna, prohibida para entrenamiento, permitida para recuperación sin mostrar texto literal, o reservada para análisis manual. Sin esa distinción, el dataset se vuelve una bolsa de material disponible y el equipo acaba tomando decisiones por costumbre.

Manos a la obra

El kit del capítulo está en:

kit/

Construye una auditoría pequeña pero completa sobre un dataset sintético de soporte académico. No entrena ningún modelo porque esa no es la decisión de este capítulo. La decisión es anterior: este dataset puede entrar en una cadena de IA o debe quedarse en revisión.

El kit cubre cuatro formas de datos:

FormaArchivoPara qué sirve
Dataset tabulardata/support_cases.csvClasificación, splits, etiquetas, licencias y linaje por fila.
Corpus RAGdata/rag_documents.jsonlChunks con versión, caducidad, fuente y permiso de recuperación.
Preferenciasdata/preference_pairs.jsonlPares chosen/rejected con política de preferencia.
Muestra actualdata/production_sample.csvComparar producción contra el dataset de referencia y detectar drift.

La idea es que el alumno no solo lea nombres de archivos. Debe entender qué papel juega cada uno. support_cases.csv representa el dataset que queremos aprobar. rag_documents.jsonl enseña cómo debería documentarse un corpus recuperable. preference_pairs.jsonl enseña que una preferencia necesita política. production_sample.csv introduce la vida real: aunque el dataset base pase, producción puede moverse.

Cuando termines el laboratorio, deberías poder llevarte el patrón a otro proyecto. Cambiarás columnas, dominios y umbrales, pero mantendrás la secuencia: contrato, auditoría, manifest, card, decisión y revisión de drift.

Estructura

kit/
  README.md
  data/support_cases.csv
  data/rag_documents.jsonl
  data/preference_pairs.jsonl
  data/production_sample.csv
  contracts/data_contract.json
  contracts/odcs_like_contract.yaml
  ops/data/audit_dataset_contract.py
  ops/data/compare_drift.py
  output/data_quality_report.json
  output/lineage_manifest.json
  output/data_release_gate.json
  output/leakage_report.json
  output/dataset_card.md
  output/data_release_decision.md
  output/drift_report.json
  output/drift_decision.md

La estructura separa datos, contratos, código y salidas. Esta separación importa. Si mezclas todo en una carpeta, es fácil editar una salida a mano, confundir un reporte viejo con uno nuevo o no saber si el contrato usado coincide con el dataset. En cambio, cuando cada cosa tiene su sitio, el proyecto enseña una disciplina simple: entrada, regla, ejecución y evidencia.

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/data/audit_dataset_contract.py --write
python3 ops/data/compare_drift.py --write
cat output/data_release_decision.md
cat output/drift_decision.md

No hay dependencias externas. Es deliberado: el alumno debe poder abrir el código y ver cada comprobación.

En una organización usarías librerías y servicios más completos, pero aquí interesa ver la mecánica sin capas intermedias. El script lee el contrato, carga el dataset, calcula checks, decide el gate y escribe artefactos. Ese recorrido es exactamente el mismo que luego haría un pipeline más grande con Airflow, Dagster, dbt, Great Expectations o una plataforma interna.

Qué audita el primer script

PiezaQué producePor qué importa
SchemaComprueba columnas obligatorias y columnas extra.Si cambia la forma, puede romper entrenamiento, eval o RAG.
UnicidadVerifica que case_id no se repite.Una fila duplicada puede inflar métricas o sesgar conteos.
SplitsComprueba valores permitidos y mínimos por split.Una evaluación sin test suficiente no permite decidir.
EtiquetasVerifica catálogo y cantidad mínima total.Una clase sin ejemplos es una promesa falsa.
MissingCalcula tasa de valores faltantes.Los huecos no son inocentes: pueden ocultar un pipeline roto.
LicenciasComprueba si cada split permite ese uso.Entrenar, evaluar e indexar no son el mismo permiso.
SensibilidadBloquea valores de riesgo no permitidos.El contrato debe saber qué dato necesita más cuidado.
LinajeRevisa fuente, fecha, owner, licencia y consentimiento.Sin linaje no puedes explicar ni reconstruir la decisión.
LeakageBusca duplicados de texto entre splits.Evita medir con ejemplos que ya estaban cerca del entrenamiento.
ManifestGenera hashes del dataset y del contrato.Permite saber exactamente qué snapshot se aprobó.
Dataset cardDocumenta finalidad, distribución y resultado.Sustituye memoria oral por evidencia revisable.
GateEscribe pass, review o block.Convierte calidad de datos en decisión operativa.

El punto más importante es que el gate no dice “el dataset es perfecto”. Dice algo más humilde y útil: “con las reglas actuales, este snapshot cumple lo suficiente para el uso declarado”. Si el uso cambia, el contrato debe cambiar. Si el contrato cambia, el gate debe volver a ejecutarse.

También conviene mirar los checks que pasan, no solo los que fallan. Un reporte con todo en verde enseña qué condiciones está garantizando: no hay IDs repetidos, los splits existen, las licencias encajan, el linaje está completo. Esa evidencia permite defender una decisión técnica sin depender de impresiones.

Qué audita el segundo script

El segundo script compara support_cases.csv contra production_sample.csv en columnas categóricas:

ColumnaQué miraCómo se lee
productSi cambió la mezcla de temas.Si aparecen muchas consultas nuevas, la eval puede no representar producción.
labelSi cambió la distribución de acciones esperadas.Si suben casos de ask_more, una política de respuesta directa puede quedarse corta.
channelSi cambió el canal de entrada.Un canal nuevo trae estilo, longitud y ruido distintos.
pii_riskSi cambió la sensibilidad.La operación necesita otro control antes de reutilizar trazas.

Calcula tres señales:

SeñalQué mideLectura práctica
total_variationDiferencia total entre dos distribuciones categóricas.Buena para entender cuánto se ha movido la mezcla.
jensen_shannonSeparación suavizada entre distribuciones.Útil porque es simétrica y estable para comparar perfiles.
psiEstabilidad poblacional.Señal habitual en scoring y monitorización, pero siempre requiere mirar el dato.

El drift no significa automáticamente que haya que tirar el dataset. Significa que hay que mirar. Si producción cambia de titulos a pagos, quizá es una semana rara; quizá hubo una campaña; quizá el producto cambió; quizá la evaluación ya no cubre lo que importa. La métrica abre una revisión, no la sustituye.

En el ejemplo, psi salta especialmente porque una categoría que existía en la referencia deja de aparecer en la muestra actual. Eso no convierte el número en una verdad absoluta, pero sí en una buena alarma didáctica. El siguiente paso no es discutir el decimal: es abrir distribuciones, mirar fechas, revisar tamaño muestral y decidir si hace falta actualizar la eval.

Salida esperada de calidad

El reporte actual genera:

{
  "row_count": 18,
  "split_counts": {
    "train": 8,
    "validation": 4,
    "test": 6
  },
  "label_distribution": {
    "answer": 11,
    "ask_more": 4,
    "escalate": 3
  },
  "gate": "pass",
  "recommendation": "usar como dataset didactico"
}

La decisión importante es:

Estado: pass.

Este dataset puede usarse como material didactico.
Tiene contrato, schema esperado, splits definidos,
licencias compatibles, linaje por fila y hashes reproducibles.

Esta salida no autoriza a usar datos reales sin más. Autoriza este snapshot didáctico bajo este contrato didáctico. En un proyecto real, la decisión debería incluir quién aprueba, qué uso se permite, qué fecha de caducidad tiene el dataset y qué cambios obligan a repetir la auditoría.

Salida esperada de drift

La muestra de producción está preparada para que haya una señal de revisión:

{
  "gate": "review",
  "recommendation": "revisar drift antes de reutilizar la eval"
}

La lectura no es “todo está roto”. La lectura profesional es más precisa: producción cambió lo suficiente como para revisar si el test sigue representando la realidad.

Esta diferencia de lenguaje es importante. review no es fracaso; es una pausa técnica. Si el dataset de evaluación ya no representa los casos actuales, comparar modelos con ese test puede llevarte a elegir mal. El gate de drift protege la decisión, no solo el dataset.

Cómo lo adaptas a tu caso

Si tu proyecto es...Añade al contratoAñade al gate
RAG documentaldocument_version, chunk_id, retrieval_scope, expires_at, embedding_model.Fuente vigente, chunk con cita, embedding regenerado con versión esperada.
Fine-tuningtraining_allowed, label_source, reviewer_id, label_policy_version.Licencia compatible, etiqueta revisada, ejemplos por etiqueta y por segmento.
Evaluaciónexpected_output, rubric_id, criticality, baseline_version.Leakage, cobertura por caso crítico, acuerdo entre anotadores.
Agentestool_context, action_allowed, approval_required, trace_id, stop_reason.Trayectoria válida, coste máximo, herramienta permitida, salida verificable.
Multimodalmedia_type, resolution, ocr_quality, caption_source, asset_license.Resolución mínima, OCR revisado, permiso de uso y metadatos completos.
Feature storeentity_id, event_time, feature_view, freshness_slo.Sin leakage temporal, consistencia offline/online, frescura mínima.

Para adaptar el laboratorio, empieza por escribir una historia de uso: “quiero evaluar un asistente de soporte”, “quiero indexar documentación interna”, “quiero ajustar el formato de respuesta”, “quiero entrenar un clasificador”. Después traduce esa historia a columnas. Si una columna no ayuda a decidir, quizá sobra. Si una decisión no se puede tomar con las columnas actuales, falta contrato.

La mejor adaptación no es la más larga. Es la que deja claro qué está permitido, qué se mide, qué se bloquea y qué evidencia queda. Un contrato pequeño pero ejecutable gana a una política enorme que nadie puede comprobar.

Qué entregaría un alumno

  1. data_quality_report.json ejecutado sin editar a mano.
  2. lineage_manifest.json con hashes reproducibles.
  3. dataset_card.md revisada como ficha de uso.
  4. data_release_decision.md con una decisión clara.
  5. drift_report.json comparando referencia y muestra actual.
  6. Una propuesta de cambio al contrato para su propio caso.
  7. Una respuesta escrita a esta pregunta: “¿qué uso permitiría y qué uso no permitiría con estos datos?”.

El objetivo no es copiar este contrato. Es aprender la forma mental: antes de usar datos, escribe qué significa usarlos bien y haz que una máquina lo compruebe.

Cómo encaja todo

El mapa siguiente conecta este capítulo con lo que ya hemos trabajado. RAG necesita documentos y chunks; embeddings son datos derivados; observabilidad produce trazas; evals necesitan casos separados; interpretabilidad necesita linaje para explicar por qué un sistema decidió algo. Por eso este facsímil no va aparte: es el suelo sobre el que pisan los facsímiles anteriores.

También prepara los siguientes capítulos. Calidad de datos, splits, features, slices, drift y experimentos no son temas aislados. Son capas de una misma pregunta: qué evidencia tenemos de que el dato representa bien la decisión que queremos tomar.

graph TD
    subgraph "Este capítulo"
        SRC["Fuente y formato"]
        CONTRACT["Contrato de datos"]
        LIN["Linaje<br/>hashes · permisos"]
        SPLIT["Splits iniciales"]
        CHECK["Checks de calidad"]
        CARD["Dataset card"]
        DEC["Decisión de uso"]
    end
    subgraph "Mismo facsímil"
        C02["Calidad<br/>cap. 2"]
        C03["Splits<br/>cap. 3"]
        C04["Features y embeddings<br/>cap. 4"]
        C05["Slices<br/>cap. 5"]
        C06["DataOps<br/>cap. 6"]
        C07["Experimentos<br/>cap. 7"]
    end
    subgraph "Otros facsímiles"
        RAG["RAG<br/>fasc. 4"]
        EMB["Embeddings<br/>fasc. 4"]
        OBS["Observabilidad<br/>fasc. 6"]
        EVAL["Evals<br/>fasc. 7"]
        GOV["Gobernanza<br/>fasc. 9"]
    end

    RAG -->|"necesita documentos"| SRC
    EMB -->|"genera datos derivados"| LIN
    OBS -->|"aporta trazas"| SRC
    EVAL -->|"necesita casos separados"| SPLIT

    SRC -->|"se formaliza en"| CONTRACT
    CONTRACT -->|"exige"| LIN
    CONTRACT -->|"define"| SPLIT
    CONTRACT -->|"activa"| CHECK
    LIN -->|"documenta"| CARD
    CHECK -->|"alimenta"| CARD
    CARD -->|"permite"| DEC

    CONTRACT -->|"abre"| C02
    SPLIT -->|"prepara"| C03
    LIN -->|"protege"| C04
    CHECK -->|"se mira por"| C05
    CARD -->|"se opera en"| C06
    DEC -->|"da población a"| C07
    DEC -->|"deja evidencia"| GOV

    style SRC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CONTRACT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style LIN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SPLIT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CHECK fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CARD fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DEC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C02 stroke-dasharray: 5 5
    style C03 stroke-dasharray: 5 5
    style C04 stroke-dasharray: 5 5
    style C05 stroke-dasharray: 5 5
    style C06 stroke-dasharray: 5 5
    style C07 stroke-dasharray: 5 5
    style RAG stroke-dasharray: 5 5
    style EMB stroke-dasharray: 5 5
    style OBS stroke-dasharray: 5 5
    style EVAL stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
DatasetConjunto de ejemplos con datos, metadatos y finalidad de uso.
Fuente de datosLugar original del que sale el dato: tabla, documento, log, traza o evento.
DatasetDictEstructura que agrupa splits como train, validation y test.
JSONLFormato de una línea JSON por ejemplo, muy útil para LLMs, RAG y trazas.
LinajeRegistro de origen, transformación, versión, owner y hash.
Contrato de datosEspecificación verificable de columnas, permisos, splits y checks.
ODCSEstándar abierto para describir contratos de datos.
SplitPartición destinada a entrenar, validar, probar o evaluar.
LeakageFuga de información que contamina la evaluación.
Dataset cardFicha que documenta finalidad, composición, límites y usos previstos.
Dato derivadoChunk, embedding, feature, resumen, etiqueta o traza producida desde otro dato.
Feature storeSistema para mantener features consistentes entre entrenamiento e inferencia.
DriftCambio en una distribución respecto a una referencia.
PSIÍndice de estabilidad poblacional usado como señal de drift.
SensibilidadNivel de cuidado por privacidad, licencia, permisos o impacto.
SchemaForma esperada del dataset: columnas, tipos y valores válidos.
SnapshotCopia concreta y fechada del dataset.
Time travelCapacidad de consultar una versión anterior de un dato o tabla.
HashHuella criptográfica que identifica una versión exacta.
OwnerEquipo o persona responsable del contrato y sus cambios.
Gate de datosDecisión automatizada de pass, review o block sobre un dataset.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Entrenar antes de escribir contratoEl dataset parece obvio porque está delante.Escribir schema, uso permitido, splits y checks antes de tocar modelo.
Mezclar train y test sin darse cuentaDuplicados, textos parecidos o casos derivados cruzan particiones.Calcular huellas y revisar leakage básico.
Usar el mismo dato para RAG, fine-tuning y evalTodo vive en la misma carpeta y parece “texto útil”.Declarar finalidad y permiso por fila o documento.
Tratar embeddings como si no fueran datosAl ser vectores, parecen menos sensibles.Heredar permisos, linaje y protección del texto origen.
Creer que una licencia vale para todoConsulta, evaluación y entrenamiento son usos distintos.Registrar license y consent_scope por fila.
Guardar preferencias sin políticaUn chosen sin rúbrica parece verdad universal.Versionar preference_policy, anotador, fecha y criterio.
Documentar solo el modeloEs más visible presentar una model card.Añadir dataset card y manifest de linaje.
Limpiar sin versionarLa limpieza mejora algo, pero borra el camino.Guardar contrato, hashes y decisión de cada snapshot.
Ignorar producción después de aprobar la evalEl test aprobado da tranquilidad falsa durante meses.Comparar muestras nuevas contra referencia y revisar drift.
Confundir feature store con base de datos normalParece solo una tabla más.Verificar event_time, frescura, consistencia offline/online y leakage temporal.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Por qué un dataset no es simplemente una carpeta de filas?
  2. ¿Qué diferencia hay entre fuente de datos, dataset y dato derivado?
  3. ¿Qué campos mínimos incluirías en un contrato de datos?
  4. ¿Por qué una licencia puede permitir RAG pero no fine-tuning?
  5. ¿Qué es linaje y qué aporta un hash?
  6. ¿Cómo detectarías leakage básico entre train y test?
  7. ¿Por qué los embeddings deben tratarse como datos derivados?
  8. ¿Qué cambia entre un CSV, un JSONL, un DatasetDict y un corpus RAG?
  9. ¿Qué debería contener una dataset card?
  10. ¿Qué significa que un gate de datos devuelva pass, review o block?
  11. ¿Qué mide PSI y por qué no basta con mirar solo ese número?
  12. ¿Qué metadatos necesita un chunk RAG para ser confiable?
  13. ¿Qué información mínima debe traer un par de preferencias?
  14. ¿Qué problema resuelve un feature store y qué problema no resuelve?
  15. ¿Cómo conecta este capítulo con evaluación e interpretabilidad?

En resumen

IdeaQué te llevas
Los datos son parte del sistema.No son una entrada pasiva ni una fase previa menor.
Un dataset necesita contrato.Schema, linaje, uso permitido, sensibilidad, splits y checks.
La estructura depende de la tarea.Tabular, JSONL, RAG, preferencias, trazas y features no piden lo mismo.
La evaluación depende del dato.Si hay leakage o etiquetas débiles, la métrica miente.
RAG y embeddings también son DataOps.Chunks y vectores heredan permisos, versiones y linaje.
El drift cambia decisiones.Un test aprobado puede dejar de representar producción.
La documentación importa.Dataset card, manifest y decisión técnica evitan memoria oral.
La práctica empieza con un gate.Antes de entrenar, indexar o evaluar, audita el dataset.
Lo profesional es dejar evidencia.Contrato, hashes, reportes y decisión deben poder repetirse.

Para saber más

Baylor, D., Breck, E., Cheng, H.-T., Fiedel, N., Foo, C. Y., Haque, Z., Haykal, S., Ispir, M., Jain, V., Koc, L., Koo, C. Y., Lew, L., Mewald, C., Modi, A. N., Polyzotis, N., Ramesh, S., Roy, S., Whang, S. E., Wicke, M., Wilkiewicz, J., Zhang, X. y Zinkevich, M. (2017). TFX: A TensorFlow-Based Production-Scale Machine Learning Platform. KDD, 1387-1395. https://doi.org/10.1145/3097983.3098021

Bitol. (2026). Open Data Contract Standard. https://bitol-io.github.io/open-data-contract-standard/latest/

Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction. IEEE Big Data, 1123-1132. https://research.google/pubs/pub46555/

DataHub. (2026). DataHub Documentation. https://docs.datahub.com/

DVC. (2026). What is DVC? https://dvc.org/doc/user-guide/what-is-dvc

Evidently AI. (2026). Data Drift Documentation. https://docs.evidentlyai.com/metrics/explainer_drift

Feast. (2026). Feast Documentation. https://docs.feast.dev/

Gebru, T., Morgenstern, J., Vecchione, B., Vaughan, J. W., Wallach, H., Daumé III, H. y Crawford, K. (2021). Datasheets for Datasets. Communications of the ACM, 64(12), 86-92. https://doi.org/10.1145/3458723

Great Expectations. (2026). Expectations Overview. https://docs.greatexpectations.io/docs/cloud/expectations/expectations_overview/

Hugging Face. (2026). Datasets Documentation. https://huggingface.co/docs/datasets/

lakeFS. (2026). lakeFS Documentation. https://docs.lakefs.io/

Mitchell, M., Wu, S., Zaldivar, A., Barnes, P., Vasserman, L., Hutchinson, B., Spitzer, E., Raji, I. D. y Gebru, T. (2019). Model Cards for Model Reporting. FAT, 220-229. https://doi.org/10.1145/3287560.3287596

OpenLineage. (2026). OpenLineage Documentation. https://openlineage.io/docs/

Pushkarna, M., Zaldivar, A. y Kjartansson, O. (2022). Data Cards: Purposeful and Transparent Dataset Documentation for Responsible AI. arXiv. https://arxiv.org/abs/2204.01075

Sculley, D., Holt, G., Golovin, D., Davydov, E., Phillips, T., Ebner, D., Chaudhary, V., Young, M., Crespo, J.-F. y Dennison, D. (2015). Hidden Technical Debt in Machine Learning Systems. NeurIPS. https://papers.nips.cc/paper_files/paper/2015/hash/86df7dcfd896fcaf2674f757a2463eba-Abstract.html

TensorFlow. (2026). ML Metadata. https://tensorflow.github.io/tfx/guide/mlmd/

TensorFlow. (2026). TensorFlow Data Validation. https://www.tensorflow.org/tfx/data_validation/get_started/

Notas

  1. Gebru, T., Morgenstern, J., Vecchione, B., Vaughan, J. W., Wallach, H., Daumé III, H. y Crawford, K. (2021). Datasheets for Datasets. Communications of the ACM, 64(12), 86-92. https://doi.org/10.1145/3458723

  2. Pushkarna, M., Zaldivar, A. y Kjartansson, O. (2022). Data Cards: Purposeful and Transparent Dataset Documentation for Responsible AI. arXiv. https://arxiv.org/abs/2204.01075

  3. Hugging Face. (2026). Datasets Documentation. https://huggingface.co/docs/datasets/. Consultado el 6 de junio de 2026.

  4. Sculley, D. et al. (2015). Hidden Technical Debt in Machine Learning Systems. NeurIPS. https://papers.nips.cc/paper_files/paper/2015/hash/86df7dcfd896fcaf2674f757a2463eba-Abstract.html

  5. Amershi, S. et al. (2019). Software Engineering for Machine Learning: A Case Study. ICSE-SEIP, 291-300. https://doi.org/10.1109/ICSE-SEIP.2019.00042

  6. Baylor, D. et al. (2017). TFX: A TensorFlow-Based Production-Scale Machine Learning Platform. KDD, 1387-1395. https://doi.org/10.1145/3097983.3098021

  7. Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction. IEEE Big Data, 1123-1132. https://research.google/pubs/pub46555/

  8. Bitol. (2026). Open Data Contract Standard. https://bitol-io.github.io/open-data-contract-standard/latest/. Consultado el 6 de junio de 2026.

  9. TensorFlow. (2026). TensorFlow Data Validation. https://www.tensorflow.org/tfx/data_validation/get_started/. Consultado el 6 de junio de 2026.

  10. TensorFlow. (2026). ML Metadata. https://tensorflow.github.io/tfx/guide/mlmd/. Consultado el 6 de junio de 2026.

  11. OpenLineage. (2026). OpenLineage Documentation. https://openlineage.io/docs/. Consultado el 6 de junio de 2026.

  12. DataHub. (2026). DataHub Documentation. https://docs.datahub.com/. Consultado el 6 de junio de 2026.

  13. Great Expectations. (2026). Expectations Overview. https://docs.greatexpectations.io/docs/cloud/expectations/expectations_overview/. Consultado el 6 de junio de 2026.

  14. Feast. (2026). Feast Documentation. https://docs.feast.dev/. Consultado el 6 de junio de 2026.

  15. Evidently AI. (2026). Data Drift Documentation. https://docs.evidentlyai.com/metrics/explainer_drift. Consultado el 6 de junio de 2026.

  16. DVC. (2026). What is DVC?. https://dvc.org/doc/user-guide/what-is-dvc. Consultado el 6 de junio de 2026.

  17. lakeFS. (2026). lakeFS Documentation. https://docs.lakefs.io/. Consultado el 6 de junio de 2026.

  18. Delta Lake. (2026). Delta Lake Documentation. https://docs.delta.io/. Consultado el 6 de junio de 2026.

  19. Apache Iceberg. (2026). Apache Iceberg Documentation. https://iceberg.apache.org/docs/latest/evolution/. Consultado el 6 de junio de 2026.

  20. Mitchell, M. et al. (2019). Model Cards for Model Reporting. FAT, 220-229. https://doi.org/10.1145/3287560.3287596

Capítulo 02

Facsímil 8 · La ciencia de los datos

Capítulo 02: Calidad de datos: schema, duplicados, leakage y etiquetas

Qué deberías poder hacer al terminar

En el capítulo anterior construimos una idea base: un dataset serio no empieza en el modelo, empieza en el contrato. Ahora damos un paso más. Un contrato escrito no sirve de mucho si no se ejecuta. La calidad de datos aparece justo ahí: en convertir el contrato en comprobaciones que puedan aprobar, revisar o bloquear un dataset antes de que llegue al modelo, al RAG o a una evaluación.

Calidad no significa “datos bonitos”. Significa datos suficientemente correctos para la decisión que queremos tomar. Un dataset puede ser aceptable para un prototipo, insuficiente para una evaluación pública, útil para RAG interno y prohibido para entrenamiento. La calidad siempre se lee junto al uso.

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Distinguir schema, expectation y contrato.No confundes “la columna existe” con “el dato es válido”.
Detectar duplicados exactos y cercanos.Sabes mirar claves repetidas, textos normalizados y similitud.
Explicar leakage con ejemplos de datos.Puedes detectar cuándo test se contaminó con train o cuándo una feature mira el futuro.
Revisar etiquetas con criterio.No borras ejemplos difíciles; los llevas a una cola de revisión.
Calcular acuerdo entre anotadores.Entiendes pop_o, pep_e y κ\kappa.
Diseñar un gate de calidad.Produces un reporte con pass, review o block.
Conectar calidad con evaluación.Ves que una métrica puede caer por modelo o por dataset, y sabes separarlo.

La idea central es esta:

La calidad de datos no se inspecciona al final. Se prueba antes de decidir.

La escena: el modelo parece peor, pero el dataset cambió

Imagina que tenemos una eval de soporte académico. Durante semanas el asistente funciona razonablemente bien. Un día, tras cambiar algunos datos, la métrica baja. El primer impulso es pensar que el modelo ha empeorado o que el prompt ya no sirve.

Pero al mirar el dataset aparecen señales menos espectaculares y más importantes: una etiqueta nueva llamada resolve se coló en un catálogo donde solo existían answer, ask_more y escalate; un caso de train aparece casi igual en test; un campo source_id está vacío; una fila de validación lleva licencia de entrenamiento; y dos anotadores no se ponen de acuerdo en varios ejemplos.

Nada de eso requiere cambiar el modelo. Requiere parar la cadena y preguntar: ¿este dataset puede sostener la decisión que estamos tomando? Si no puede, la métrica deja de ser una medida limpia. Se convierte en una mezcla de comportamiento del modelo, fallos de contrato, errores de etiqueta y contaminación entre splits.

Qué no es calidad de datos

Calidad de datos no es “no tener nulos”. Los nulos importan, pero son solo una parte pequeña. Un dataset puede no tener ningún valor vacío y aun así estar mal: etiquetas inconsistentes, licencia incompatible, duplicados entre splits, texto caducado, clases desbalanceadas o columnas con significado ambiguo.

Tampoco es “pasar un script de limpieza”. Limpiar sin contrato puede empeorar el problema. Si borras todos los casos difíciles porque ensucian la métrica, quizá destruyes justo los ejemplos que el sistema necesita aprender o evaluar. Si deduplicas sin mirar splits, puedes eliminar evidencia legítima o dejar contaminación.

Y no es una puntuación universal. La misma tabla puede estar bien para explorar, mal para entrenar y completamente inaceptable para evaluar. Por eso la pregunta correcta no es “¿tiene calidad?”, sino “¿tiene calidad suficiente para este uso, con este contrato y esta fecha de corte?”.

MalentendidoLectura de ingeniería
“Si no hay nulos, está limpio”.Faltan catálogo, licencias, duplicados, leakage, etiquetas y linaje.
“Un duplicado siempre se borra”.Primero hay que saber si es repetición real, evento legítimo o contaminación.
“La etiqueta registrada es verdad”.La etiqueta es una decisión humana o automática que puede fallar.
“Si la métrica baja, el modelo empeoró”.Puede haber cambiado el dataset, el split o la distribución.
“Calidad es cosa de datos, no de ingeniería”.Un gate de calidad es parte del pipeline de software.

Qué sí es calidad de datos para IA

En este libro llamaremos calidad de datos al grado en que un dataset cumple las condiciones necesarias para una decisión de IA: entrenar, evaluar, indexar, recuperar, monitorizar o revisar.

Ejemplo de fórmula: una forma compacta de escribirlo es la siguiente. No es una ley académica cerrada; es una regla de lectura para recordar que la calidad depende del uso previsto.

quality(D,u)=schema(D)values(D)lineage(D)license(D,u)splits(D,u)labels(D,u)quality(D, u) = schema(D) \land values(D) \land lineage(D) \land license(D, u) \land splits(D, u) \land labels(D, u)
SímboloSignificadoEjemplo
DDDataset que queremos usar.Casos de soporte académico.
uuUso previsto.Evaluación interna, RAG o fine-tuning.
schema(D)schema(D)El dataset tiene la forma esperada.Están case_id, split, label, text.
values(D)values(D)Los valores respetan catálogos y tipos.label no contiene resolve si no está permitido.
lineage(D)lineage(D)Cada fila conserva origen y versión.source_id no está vacío.
license(D,u)license(D,u)El permiso encaja con el uso.support_eval_only no se usa para entrenamiento.
splits(D,u)splits(D,u)Las particiones no contaminan la decisión.test no repite casos de train.
labels(D,u)labels(D,u)Las etiquetas son coherentes con la política.Dos anotadores no discrepan masivamente.

Esta fórmula no pretende ser una verdad matemática absoluta. Es una forma de recordar que la calidad es una conjunción: si una pieza crítica falla, el dataset no debería avanzar como si nada.

Fecha de corte del estado del arte

Fecha de corte: 6 de junio de 2026.
Fuentes consultadas: TensorFlow Data Validation, Great Expectations, Pandera, Deequ, Cleanlab, Snorkel, scikit-learn y literatura clásica sobre acuerdo entre anotadores.

La idea estable es que la validación de datos debe ser declarativa, reproducible y cercana al pipeline. TensorFlow Data Validation perfila datasets, infiere schema y detecta anomalías contra expectativas.1 Su referencia de anomalías muestra que un sistema de validación no solo dice “hay error”, sino que clasifica problemas como tipo inválido, dominio inesperado, valor ausente o cambio de distribución.2

Great Expectations organiza la calidad como expectations: afirmaciones verificables sobre columnas, rangos, nulos, formatos o relaciones entre datos.3 Pandera lleva esa misma filosofía al mundo de DataFrames, con schemas programáticos para validar tipos y propiedades de columnas.4 Deequ propone “unit tests for data” sobre Spark, una frase muy útil porque acerca la calidad de datos a una práctica que cualquier ingeniero de software reconoce.5

Para etiquetas, confident learning propone estimar incertidumbre y errores de etiqueta en datasets, y Cleanlab lo popularizó como herramienta práctica.6 El trabajo sobre errores de etiqueta en test sets mostró algo incómodo: incluso benchmarks muy usados pueden contener errores de etiqueta suficientes para desestabilizar conclusiones.7

Snorkel es importante porque enseña otra vía: crear datos de entrenamiento con supervisión débil mediante funciones de etiquetado, y después combinar señales ruidosas de forma sistemática.8 La lección para este capítulo no es “usa una herramienta concreta”. Es más básica: si una etiqueta puede fallar, la etiqueta también necesita ingeniería.

Las tripas de la calidad: de schema a decisión

La calidad empieza con schema, pero no termina ahí. El schema responde a la forma: qué columnas existen, qué tipos tienen, qué valores son válidos. Después vienen reglas de contenido: nulos, catálogos, rangos, licencias, duplicados, distribución de clases, coherencia entre anotadores y leakage entre splits.

Una expectation sencilla puede escribirse como una función booleana:

Ej(D){0,1}E_j(D) \in \{0,1\}
SímboloSignificadoEjemplo
EjE_jExpectation o check número jj.label pertenece al catálogo permitido”.
DDDataset evaluado.quality_cases_dirty.csv.
00La regla falla.Aparece resolve aunque no está permitido.
11La regla pasa.Todas las etiquetas están en catálogo.

Ejemplo de fórmula: un gate del kit agrupa expectations y les asigna severidad. En otro equipo podrían cambiar los nombres o los umbrales, pero la idea operativa es la misma: no todo fallo pesa igual.

gate(D)=s,s{block,review,pass}gate(D)=s,\quad s\in\{\mathrm{block},\mathrm{review},\mathrm{pass}\}

La tabla concreta cuándo devuelve cada estado:

ResultadoQué significaQué haría un equipo
blockHay fallos que impiden usar el dataset.No entrenar, no evaluar, no indexar ese snapshot.
reviewNo hay bloqueo técnico, pero hay dudas que requieren criterio.Abrir cola de revisión y documentar decisión.
passCumple el contrato actual para el uso declarado.Usarlo y guardar reporte/versionado.

La parte importante es la palabra “actual”. Un pass no significa que el dataset sea perfecto para siempre. Significa que, bajo este contrato y este uso, no hemos encontrado fallos que impidan avanzar.

Missing y valores fuera de catálogo

El missing se calcula como proporción de celdas vacías sobre las celdas obligatorias:

miss(D)=i=1ncC1[xi,c=]nCmiss(D) = \frac{ \sum_{i=1}^{n} \sum_{c \in C} \mathbb{1}[x_{i,c}=\varnothing] }{ n \cdot |C| }
SímboloSignificadoEjemplo
nnNúmero de filas.19 casos.
CCColumnas obligatorias.case_id, source_id, label, text, etc.
xi,cx_{i,c}Valor de la columna cc en la fila ii.source_id de q007.
1\mathbb{1}Indicador: 1 si falta, 0 si no.Vale 1 si source_id está vacío.
miss(D)miss(D)Tasa total de missing.0.003096 en el kit.

Un missing bajo puede seguir siendo grave. Si falta una columna secundaria quizá es revisable; si falta source_id, perdemos linaje. Por eso la tasa agregada no basta: hay que mirar qué columna falta y para qué uso era necesaria.

Los valores fuera de catálogo son otra familia de errores. Si label solo permite answer, ask_more y escalate, una etiqueta resolve no es una variación inocente: rompe la semántica del dataset. Quizá representa una nueva clase legítima, pero entonces el contrato debe cambiar y la evaluación debe rehacerse.

Duplicados exactos y duplicados cercanos

Un duplicado exacto puede detectarse normalizando texto:

dupexact(a,b)=1[norm(texta)=norm(textb)]dup_{exact}(a,b) = \mathbb{1}[norm(text_a)=norm(text_b)]
SímboloSignificadoEjemplo
a,ba,bDos ejemplos comparados.q001 y q017.
normnormNormalización de texto.Minúsculas, quitar signos, compactar espacios.
dupexactdup_{exact}Indicador de duplicado textual exacto.1 si el texto normalizado coincide.

Pero muchos duplicados no son idénticos. Cambian una palabra o añaden un adjetivo. Para enseñar la idea sin dependencias externas, el kit usa Jaccard sobre conjuntos de tokens:

J(A,B)=ABABJ(A,B)= \frac{|A \cap B|}{|A \cup B|}
SímboloSignificadoEjemplo
AATokens del primer texto.consulta, documentacion, beca.
BBTokens del segundo texto.consulta, documentacion, beca, necesaria.
$A \cap B$
$A \cup B$
J(A,B)J(A,B)Similitud de Jaccard.0.833333 en un par del kit.

Jaccard no entiende semántica profunda. No sabe que “matrícula” y “inscripción” pueden estar relacionadas. Pero es suficiente para enseñar una idea crítica: si un caso muy parecido aparece en train y test, la evaluación deja de ser limpia.

Leakage entre splits

Leakage no es solo duplicado textual. Es cualquier información que permite al sistema obtener ventaja en evaluación porque ya vio directa o indirectamente la respuesta.

Una tasa básica puede escribirse así:

leak(Dtrain,Dtest)={eDtest:sim(e,Dtrain)τ}Dtestleak(D_{train}, D_{test}) = \frac{ |\{e \in D_{test}: sim(e,D_{train}) \ge \tau\}| }{ |D_{test}| }
SímboloSignificadoEjemplo
DtrainD_{train}Split de entrenamiento.8 filas en el kit.
DtestD_{test}Split de prueba.7 filas en el kit.
eeEjemplo de test.q017 o q019.
simsimFunción de similitud.Coincidencia exacta o Jaccard.
τ\tauUmbral de similitud.0.82 para duplicado cercano.

En el próximo capítulo entraremos más a fondo en splits y leakage. Aquí basta con una regla operativa: si algo de test está demasiado cerca de train, no uses ese test para decidir si el sistema generaliza.

Distribución de etiquetas

Una etiqueta no es solo un texto. Es una decisión que influye en el aprendizaje o en la evaluación. Por eso conviene mirar proporciones:

p(y=k)=nknp(y=k)= \frac{n_k}{n}
SímboloSignificadoEjemplo
yyEtiqueta.answer, ask_more, escalate.
kkClase concreta.ask_more.
nkn_kNúmero de ejemplos de esa clase.4 casos.
nnNúmero total de ejemplos.19 casos.

Si casi todo es answer, el sistema puede aprender a contestar siempre. Si casi no hay escalate, puede parecer correcto hasta que aparece un caso crítico. En clasificación y evaluación, mirar la distribución por split es obligatorio.

Para comparar la distribución global con la de cada split podemos usar distancia total variation:

DTV(P,Q)=12iPiQiD_{TV}(P,Q)= \frac{1}{2} \sum_i |P_i-Q_i|
SímboloSignificadoEjemplo
PiP_iProporción global de la clase ii.Proporción global de answer.
QiQ_iProporción de la clase ii en un split.Proporción de answer en test.
DTVD_{TV}Distancia entre distribuciones.0.172932 para test en el kit.

scikit-learn permite hacer splits estratificados con train_test_split(..., stratify=y) cuando esa estrategia encaja con el problema.9 Estratificar no arregla etiquetas malas, pero ayuda a que cada partición conserve una mezcla parecida de clases.

Calidad de etiquetas y acuerdo entre anotadores

Las etiquetas son datos, no dogmas. En el kit aparecen tres señales de revisión: desacuerdo entre anotadores, diferencia con una referencia didáctica y baja confianza de un modelo auxiliar. En un proyecto real no siempre tendrás expected_label, pero sí puedes tener doble anotación, reglas de revisión, muestras auditadas o modelos que prioricen casos dudosos.

El acuerdo observado se calcula así:

po=i=1n1[ai=bi]np_o = \frac{ \sum_{i=1}^{n} \mathbb{1}[a_i=b_i] }{ n }
SímboloSignificadoEjemplo
aia_iEtiqueta del anotador A para el ejemplo ii.answer.
bib_iEtiqueta del anotador B para el ejemplo ii.ask_more.
pop_oProporción de acuerdo observado.0.789474 en el kit.

Pero parte del acuerdo puede ocurrir por azar, especialmente si una clase domina. Kappa de Cohen corrige ese efecto:10

κ=pope1pe\kappa = \frac{p_o-p_e}{1-p_e}
SímboloSignificadoEjemplo
pop_oAcuerdo observado.0.789474.
pep_eAcuerdo esperado por azar según distribuciones marginales.0.518006.
κ\kappaAcuerdo corregido por azar.0.563218.

En el kit, κ\kappa queda por debajo del umbral 0.6, así que no bloquea por sí solo, pero exige revisión. Esta distinción importa: una etiqueta dudosa no siempre se borra; se revisa con política.

Anatomía de un gate de calidad

Gate de calidad de datos Diagrama en blanco y negro que muestra schema, valores, duplicados, leakage, etiquetas, acuerdo, severidad y decision final. Gate de calidad: no limpia por intuición, decide con evidencia Cada check tiene severidad. Un fallo bloqueante detiene el dataset; un fallo revisable abre cola de trabajo. Dataset + contrato quality_cases_dirty.csv quality_contract.json uso declarado catálogos umbrales Schema columnas obligatorias tipos y campos vacíos missing · extra columns Valores catálogos permitidos licencia por split label · product · pii Duplicados case_id repetido texto exacto normalización textual Leakage train cerca de test Jaccard alto eval contaminada Etiquetas catálogo confianza baja cola de revisión Acuerdo anotador A vs B kappa revisable fallo bloqueante schema roto licencia incompatible leakage entre splits salida: block fallo revisable kappa bajo etiqueta dudosa distribución rara salida: review evidencia quality_report.json label_queue.csv clean_actions.md reproducible Una métrica sin calidad de datos es una decisión con suelo blando. IA para gente curiosa / Facsímil 08 / Capítulo 02 / 686f6c61
Un gate de calidad separa fallos bloqueantes, revisiones necesarias y evidencia generada. No sustituye el criterio humano: lo organiza.

Severidad: cuándo bloquear, cuándo revisar y cuándo aceptar deuda

Un gate útil no trata todos los fallos igual. Si una etiqueta dudosa y una licencia incompatible aparecen en la misma lista sin severidad, el equipo pierde criterio. La severidad existe para responder a una pregunta muy concreta: ¿qué daño produce avanzar con este fallo?

En ingeniería de IA conviene separar tres niveles. Un fallo bloqueante invalida el uso automático del dataset. Un fallo revisable no permite publicar una decisión todavía, pero sí permite abrir trabajo humano. Una deuda aceptada es un problema conocido que no afecta al uso actual o que tiene un plan explícito de corrección.

NivelPregunta de decisiónEjemploAcción
block¿Puede invalidar entrenamiento, evaluación, permiso o seguridad del uso?Leakage entre train y test; licencia incompatible; etiqueta fuera de catálogo.Detener uso automatizado.
review¿Necesita criterio humano antes de confiar en la decisión?Kappa bajo; baja confianza de etiqueta; distribución rara.Abrir cola de revisión.
accepted_debt¿Se puede vivir con esto durante una ventana concreta?Missing en un campo no usado por este modelo.Documentar owner, fecha y plan.

Esta tabla evita dos extremos. El primero es bloquearlo todo y convertir calidad en un cuello de botella imposible. El segundo es dejar pasar todo porque “ya lo arreglaremos”. La severidad obliga a escribir el riesgo y la acción. Si no puedes explicar por qué algo es block o review, quizá la regla todavía no está bien formulada.

La matriz también debe depender del uso. Un source_id vacío puede ser revisable para exploración local, pero bloqueante para evaluación trazable. Una etiqueta dudosa puede ser tolerable en entrenamiento con millones de ejemplos, pero bloqueante en un test pequeño que decide entre dos modelos. La severidad no vive aislada: vive con el contrato.

SLI, SLO y presupuesto de error de datos

En operación ya vimos que un SLI es un indicador medible, un SLO es un objetivo y el presupuesto de error dice cuánto margen queda antes de actuar. Esa idea encaja muy bien con calidad de datos.

Un SLI de datos mide una propiedad concreta del dataset. Un SLO de datos fija el umbral aceptable. Un presupuesto de error de datos define qué ocurre cuando nos acercamos al límite o lo superamos. No es una frase de marketing: es una herramienta para que el equipo sepa cuándo parar.

SLI de datosQué mideSLO posibleAcción si falla
critical_missing_rateMissing en columnas críticas.<= 0.5%Bloquear snapshot si afecta linaje o etiqueta.
cross_split_duplicatesDuplicados entre splits.0Bloquear evaluación.
invalid_catalog_valuesValores fuera de catálogo.0Bloquear hasta migrar contrato o datos.
license_mismatchesUso incompatible con licencia.0Bloquear uso automatizado.
annotator_kappaAcuerdo corregido por azar.>= 0.6Abrir revisión de política de anotación.
label_review_queue_sizeCasos pendientes de revisar.<= 2No cerrar release si supera el umbral.

En el kit, estos objetivos aparecen en:

kit/contracts/quality_slos.json

El presupuesto de error evita discusiones vagas. Por ejemplo: si el SLO exige cero duplicados entre train y test, un solo duplicado consume todo el presupuesto y bloquea. Si el SLO permite hasta dos casos en cola de revisión, un tercero no significa que el dataset sea inútil, pero sí que la release no debería cerrarse sin mirar esos casos.

Ciclo de vida de una incidencia de datos

Detectar un fallo es el principio, no el final. Una incidencia de datos debería tener un ciclo de vida tan claro como una incidencia de software:

  1. Detectar: el gate marca un check fallido.
  2. Clasificar: se decide severidad, owner y uso afectado.
  3. Diagnosticar: se busca causa raíz.
  4. Corregir: se cambia dato, contrato, pipeline o política.
  5. Reejecutar: se vuelve a correr el gate.
  6. Versionar: se guarda snapshot, reporte y decisión.
  7. Aprender: se añade un check para que no vuelva a pasar igual.

La causa raíz importa porque no todos los fallos se arreglan tocando el CSV. Si aparece una etiqueta resolve, puede ser un error de anotación, pero también una señal de que el dominio necesita una nueva clase. Si aparece admisiones en product, puede ser un campo mal escrito, o puede ser que el producto haya crecido y el contrato esté viejo. Si baja kappa, quizá los anotadores fallaron, pero quizá la política era ambigua.

SíntomaCausa raíz posibleArreglo pobreArreglo de ingeniería
Etiqueta nuevaCatálogo real cambió.Reemplazarla por la clase más parecida.Versionar contrato y migrar evaluación.
Duplicado entre splitsSplit creado después de deduplicar mal.Borrar una fila sin registro.Rehacer split desde snapshot limpio.
Kappa bajoPolítica de anotación ambigua.Pedir “más cuidado”.Añadir casos frontera y regla de desempate.
Licencia incompatibleExport mezcló permisos.Ignorar en prototipo.Separar usos permitidos por split.
Missing en linajePipeline perdió metadatos.Rellenar a mano.Corregir ingestión y reejecutar.

Esta forma de pensar es muy de ingeniería: no arreglar solo el síntoma, sino el mecanismo que permitió que apareciera.

Schema evolution: cuando el dataset cambia sin pedir permiso

Los datasets vivos cambian. Aparecen columnas, se renombran campos, se añaden etiquetas, se deprecan productos y cambian tipos. Ese cambio no es malo. Lo peligroso es que ocurra sin versión, sin migración y sin compatibilidad.

Schema evolution significa gestionar cambios de forma controlada. En un dataset de IA, no basta con que el código lea la nueva columna. Hay que saber si el significado cambió. Una columna label puede mantener el mismo nombre y cambiar por completo si el equipo añade una política nueva. Un valor resolve puede ser un error hoy y una clase legítima mañana.

CambioRiesgoEstrategia
Nueva columna opcionalLos consumidores antiguos la ignoran.Añadirla como optional y documentar fecha.
Columna obligatoria nuevaPipelines antiguos fallan.Crear versión v2 del contrato y periodo de convivencia.
Nuevo valor de catálogoMétricas antiguas no comparan igual.Versionar label set y rehacer splits/evals.
Cambio de tipoValidación y transformación pueden romper.Migración explícita con tests de datos.
Cambio de significadoEl peor caso: parece compatible, pero no lo es.Nota de contrato, ejemplos y revisión humana.

Una regla útil: si un cambio altera una decisión, no es un detalle técnico. Es una nueva versión del contrato.

Política de anotación: la etiqueta también necesita contrato

Una etiqueta como answer parece sencilla hasta que aparecen casos frontera. ¿Qué hacemos si falta un dato menor? ¿Y si el usuario mezcla beca y matrícula? ¿Y si el asistente podría responder, pero con riesgo de orientar mal? Sin política, cada anotador inventa su criterio.

El kit incluye una política mínima en:

kit/contracts/annotation_policy.md

Una política de anotación profesional debería incluir:

PiezaPor qué importa
Definición de cada etiquetaEvita que dos personas usen palabras iguales con criterios distintos.
Ejemplos positivosMuestran cuándo sí aplica la etiqueta.
Ejemplos negativosMuestran cuándo no aplica aunque se parezca.
Casos fronteraReducen desacuerdo donde el dominio es ambiguo.
Regla de desempatePermite cerrar conflictos sin improvisar.
Versión de políticaHace trazable qué criterio produjo cada etiqueta.

Esto conecta directamente con kappa. Si el acuerdo es bajo, no siempre significa que los anotadores sean malos. Puede significar que la política no explica los casos difíciles. En ese caso, el siguiente paso no es reetiquetar a ciegas: es mejorar la política y después revisar.

Calidad por segmentos

Una media global puede esconder un problema local. El dataset puede tener buen missing global, pero fallar en becas; buen kappa global, pero mucho desacuerdo en chat; buen reparto de etiquetas, pero ningún caso crítico en test.

Por eso la calidad debería mirarse por segmentos:

SegmentoPregunta
product¿Todos los temas tienen cobertura y etiquetas coherentes?
channel¿Chat, email y portal tienen estilos comparables?
split¿Train, validation y test mantienen distribuciones razonables?
pii_risk¿Los casos sensibles tienen controles suficientes?
language¿La calidad se mantiene si hay varios idiomas?
criticality¿Los casos de alto impacto están representados y revisados?

Esta idea preparará el capítulo de slices. La intuición es sencilla: un dataset no se rompe siempre “en general”. Muchas veces se rompe en un rincón. La ingeniería consiste en encontrar ese rincón antes de que lo encuentre producción.

Leakage temporal

Hasta ahora hemos hablado de leakage entre splits. Hay otro tipo especialmente traicionero: leakage temporal. Ocurre cuando el dataset usa información que no existía en el momento en que el sistema habría tenido que decidir.

Ejemplos:

CasoLeakage temporal
Predicción de urgenciaUsar days_to_resolution, que solo se conoce después de cerrar el caso.
RAG académicoEvaluar con un documento actualizado después de la consulta original.
Feature de pagosUsar un estado de pago corregido días después del evento.
Etiqueta de soporteEtiquetar con información de resolución posterior y usarla como entrada.

La regla de oro es: para cada feature o documento, pregunta “¿esto estaba disponible en ese momento?”. Si la respuesta es no, quizá sirve para análisis histórico, pero no para entrenar o evaluar una decisión que pretende simular producción.

Esto en un proyecto real

En un equipo de IA, la calidad de datos debería estar cerca de CI. Igual que un cambio de código no debería desplegarse si rompe tests, un snapshot de datos no debería llegar a entrenamiento o evaluación si rompe checks críticos.

La práctica madura tiene cuatro capas:

CapaPreguntaArtefacto
Contrato¿Qué prometen los datos?JSON, YAML, ODCS, schema programático.
Validación¿Cumplen lo prometido?Reporte de checks y anomalías.
Revisión¿Qué casos requieren criterio?Cola de etiquetas, duplicados, incidencias.
Decisión¿Qué hacemos con el snapshot?pass, review, block y plan de limpieza.

La parte difícil no es escribir if row["label"] not in allowed_labels. Eso lo puede hacer cualquiera. La parte difícil es decidir qué fallos bloquean, cuáles abren revisión y cuáles se aceptan temporalmente con una nota. Ahí aparece la ingeniería: convertir incertidumbre en reglas operativas que un equipo pueda sostener.

En CI/CD, el patrón mínimo sería:

python3 ops/data_quality_gate.py --write
python3 ops/ci_assert_gate.py

Si release_gate.json contiene block, el segundo comando termina con error y el pipeline se detiene. Si el equipo permite releases en review para entornos manuales, podría ejecutarlo con:

python3 ops/ci_assert_gate.py --allow-review

La clave es que el pipeline no decide por intuición. Lee un artefacto. Ese artefacto queda guardado y puede revisarse después.

Por qué debería importarte

Si no revisas calidad, puedes entrenar con etiquetas rotas, evaluar con leakage, elegir un modelo por una métrica falsa o indexar documentos que no debían usarse. Todo eso produce sistemas que parecen funcionar hasta que llegan a producción o hasta que alguien intenta explicar una decisión.

Además, la calidad de datos es una de las formas más baratas de mejorar IA. Cambiar de modelo puede costar dinero, latencia y complejidad. Corregir una etiqueta mal puesta, separar bien splits o bloquear una licencia incompatible puede mejorar la decisión sin tocar arquitectura.

La calidad no compite con el modelado. Lo hace posible.

Manos a la obra

El kit del capítulo está en:

kit/

La práctica trabaja con un dataset deliberadamente problemático. Esto es intencional: si el gate devolviera pass a la primera, aprenderíamos menos. Aquí queremos ver cómo se organiza una revisión real.

Estructura

kit/
  README.md
  data/quality_cases_dirty.csv
  contracts/quality_contract.json
  contracts/quality_slos.json
  contracts/annotation_policy.md
  ops/data_quality_gate.py
  ops/ci_assert_gate.py
  output/quality_report.json
  output/release_gate.json
  output/duplicate_candidates.csv
  output/label_review_queue.csv
  output/clean_actions.md

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/data_quality_gate.py --write
python3 ops/ci_assert_gate.py
cat output/clean_actions.md

No necesita dependencias externas. La idea es que puedas abrir el script, seguir cada check y modificarlo para tu proyecto.

En este dataset, ci_assert_gate.py debe fallar porque el gate es block. Eso no es un error del kit: es el comportamiento esperado. Si un pipeline siguiera adelante con este snapshot, estaría ignorando su propio contrato.

Qué detecta

El gate busca problemas de distinta naturaleza:

FamiliaEjemplo en el kitSeveridad
ID duplicadoq004 aparece dos veces.block
Valor fuera de catálogoProducto admisiones.block
Etiqueta inválidaresolve.block
PII fuera de contratohigh.block
Licencia incompatibleFila de validation con licencia de entrenamiento.block
Duplicado exacto entre splitsq001 y q017.block
Duplicado cercano entre splitsq007 y q019 con Jaccard 0.833333.block
Etiqueta dudosaq006, q008, q011, q015.review
Acuerdo bajoκ=0.563218\kappa=0.563218.review

La lectura correcta no es “el dataset es un desastre”. La lectura correcta es: el gate ha convertido una intuición difusa en una lista priorizada. Primero se corrigen bloqueos. Después se revisan etiquetas. Luego se reejecuta.

Además, ahora el kit trae dos contratos complementarios. quality_slos.json traduce salud del dataset a SLI/SLO y presupuesto de error. annotation_policy.md explica cómo deberían decidirse answer, ask_more y escalate. Si la cola de revisión crece, no basta con corregir filas: hay que mirar si la política está incompleta.

Salida esperada

El release_gate.json debería resumir algo así:

{
  "gate": "block",
  "blocking_failures": [
    "case_id_unique",
    "product_values",
    "label_values",
    "pii_risk_values",
    "license_compatibility",
    "exact_cross_split_duplicates",
    "near_cross_split_duplicates"
  ],
  "review_failures": [
    "label_review_queue",
    "annotator_agreement"
  ]
}

Y clean_actions.md debería empezar con una decisión clara: no usar este snapshot de forma automatizada hasta corregir fallos de contrato, leakage y etiquetas.

Cómo lo adaptas a tu caso

Si tu dataset es...Añade checks
RAG documentalDocumento vigente, chunk_id único, fuente recuperable, permiso de indexación.
Fine-tuningLicencia de entrenamiento, formato de mensajes, revisión de salidas esperadas.
EvaluaciónSeparación estricta de splits, casos críticos, rúbrica, acuerdo de anotadores.
AgentesHerramienta permitida, estado inicial, acción final, coste máximo, criterio de parada.
Featuresevent_time, frescura, rango, consistencia offline/online, leakage temporal.

El patrón es siempre el mismo: escribe el contrato, codifica checks, decide severidades, genera evidencia y reejecuta tras cada cambio.

Si quieres llevarlo a un repositorio real, añade el comando del gate a CI y guarda output/ como artefacto de ejecución. Así una persona revisora no solo ve que el pipeline falló; ve por qué falló y qué casos debe revisar.

Qué entregaría un alumno

  1. quality_report.json generado.
  2. release_gate.json con decisión.
  3. duplicate_candidates.csv revisado.
  4. label_review_queue.csv con acciones propuestas.
  5. clean_actions.md ampliado con decisiones justificadas.
  6. Una modificación al contrato para un caso propio.
  7. Una propuesta de SLI/SLO de datos.
  8. Una versión de política de anotación con casos frontera.
  9. Una explicación corta de por qué un fallo es block y otro es review.

Cómo encaja todo

El capítulo anterior nos dio contrato y linaje. Este capítulo ejecuta ese contrato. El siguiente capítulo se centrará en splits y leakage con más profundidad. Más adelante veremos features, slices, drift y análisis aplicado. La calidad de datos es el puente entre “tengo datos” y “puedo tomar una decisión con ellos”.

graph TD
    subgraph "Este capítulo"
        CONTRACT["Contrato heredado"]
        SCHEMA["Schema y valores"]
        DUP["Duplicados"]
        LEAK["Leakage"]
        LABEL["Etiquetas y acuerdo"]
        GATE["Gate de calidad"]
        EVID["Evidencia"]
    end
    subgraph "Mismo facsímil"
        C01["Datos y linaje<br/>cap. 1"]
        C03["Splits<br/>cap. 3"]
        C04["Features<br/>cap. 4"]
        C05["Slices<br/>cap. 5"]
        C06["DataOps<br/>cap. 6"]
    end
    subgraph "Otros facsímiles"
        EVAL["Evals<br/>fasc. 7"]
        OBS["Observabilidad<br/>fasc. 6"]
        GOV["Gobernanza<br/>fasc. 9"]
    end

    C01 -->|"declara"| CONTRACT
    EVAL -->|"necesita etiquetas"| LABEL
    OBS -->|"aporta casos"| LABEL

    CONTRACT -->|"se ejecuta como"| SCHEMA
    SCHEMA -->|"detecta"| DUP
    DUP -->|"alerta de"| LEAK
    LABEL -->|"se mide con"| GATE
    SCHEMA -->|"alimenta"| GATE
    LEAK -->|"bloquea"| GATE
    GATE -->|"produce"| EVID

    LEAK -->|"se profundiza en"| C03
    SCHEMA -->|"condiciona"| C04
    LABEL -->|"se analiza por"| C05
    EVID -->|"se opera en"| C06
    GATE -->|"deja control para"| GOV

    style CONTRACT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SCHEMA fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DUP fill:#F5F5F5,stroke:#000000,stroke-width:2
    style LEAK fill:#F5F5F5,stroke:#000000,stroke-width:2
    style LABEL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style GATE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EVID fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C01 stroke-dasharray: 5 5
    style C03 stroke-dasharray: 5 5
    style C04 stroke-dasharray: 5 5
    style C05 stroke-dasharray: 5 5
    style C06 stroke-dasharray: 5 5
    style EVAL stroke-dasharray: 5 5
    style OBS stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
Calidad de datosGrado en que un dataset cumple el contrato necesario para una decisión concreta.
SchemaForma esperada de los datos: columnas, tipos, catálogos y reglas.
ExpectationRegla verificable sobre el dataset.
GateDecisión automatizada de pass, review o block.
Duplicado exactoRegistro que repite clave o texto normalizado.
Duplicado cercanoRegistro muy parecido según una medida de similitud.
JaccardSimilitud entre conjuntos basada en intersección y unión.
LeakageInformación que contamina entrenamiento, evaluación o tiempo de decisión.
EtiquetaClase o salida esperada asociada a un ejemplo.
Ruido de etiquetaSospecha de que la etiqueta registrada no sigue la política.
KappaAcuerdo entre dos anotadores corregido por azar.
Cola de revisiónLista priorizada de casos que necesitan criterio humano.
SLI de datosIndicador medible de salud del dataset.
SLO de datosObjetivo mínimo aceptable para un indicador de datos.
Presupuesto de error de datosMargen de fallos tolerables antes de bloquear o revisar.
Schema evolutionGestión versionada de cambios en columnas, tipos y catálogos.
Leakage temporalUso de información que no existía en el momento de decisión.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Mirar solo nulosEs el check más fácil de programar.Separar schema, catálogo, licencias, duplicados, leakage y etiquetas.
Borrar duplicados sin mirar splitsParece una limpieza obvia.Revisar si el duplicado contamina evaluación o representa un evento legítimo.
Tratar una etiqueta como verdadLa columna label da falsa seguridad.Medir acuerdo, revisar baja confianza y documentar política de anotación.
Mezclar fallos bloqueantes y revisablesTodo se mete en una lista única.Asignar severidad: block para lo que invalida uso, review para lo que pide criterio.
Celebrar un pass sin contextoSuena a certificado universal.Leerlo siempre junto a contrato, uso, fecha y versión del dataset.
Cambiar schema sin versiónEl código sigue funcionando y parece compatible.Versionar contrato si cambia una decisión o significado.
Mirar calidad solo globalLas medias esconden problemas locales.Revisar por producto, canal, split, sensibilidad e idioma.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Por qué calidad de datos no significa solo “sin nulos”?
  2. ¿Qué diferencia hay entre schema y expectation?
  3. ¿Por qué un valor fuera de catálogo puede bloquear un dataset?
  4. ¿Qué diferencia hay entre duplicado exacto y duplicado cercano?
  5. ¿Cómo se calcula Jaccard y qué limitación tiene?
  6. ¿Por qué un duplicado entre train y test puede contaminar una evaluación?
  7. ¿Qué significa que una etiqueta vaya a cola de revisión?
  8. ¿Por qué kappa corrige el acuerdo observado?
  9. ¿Qué diferencia hay entre block, review y pass?
  10. ¿Qué archivo del kit usarías para justificar una decisión ante otra persona?
  11. ¿Qué SLI y SLO definirías para duplicados entre splits?
  12. ¿Cuándo un cambio de schema exige nueva versión del contrato?
  13. ¿Qué problema resuelve una política de anotación?
  14. ¿Qué es leakage temporal y por qué no lo detecta siempre un deduplicador?
  15. ¿Cómo conectarías el gate de datos a CI/CD?

En resumen

IdeaQué te llevas
Calidad es calidad para un uso.No existe un dataset bueno en abstracto.
El schema es el principio.La forma importa, pero no basta.
Los duplicados pueden contaminar.Especialmente si cruzan splits.
Leakage rompe la evaluación.El test deja de medir generalización.
Las etiquetas son datos revisables.Necesitan política, acuerdo y cola de revisión.
Un gate organiza la decisión.block, review y pass separan tipos de acción.
La práctica debe dejar evidencia.Reporte, cola, duplicados y plan de limpieza.
Los SLOs hacen operativa la calidad.Un indicador sin objetivo no guía una decisión.
El schema evoluciona.Los cambios de significado necesitan versión y migración.
La calidad se mira por segmentos.El fallo puede vivir en un producto, canal o split concreto.
CI/CD también sirve para datos.El pipeline puede bloquear snapshots con evidencia reproducible.

Para saber más

AWS Labs. (2026). Deequ: Unit Tests for Data. https://github.com/awslabs/deequ

Cohen, J. (1960). A Coefficient of Agreement for Nominal Scales. Educational and Psychological Measurement, 20(1), 37-46. https://doi.org/10.1177/001316446002000104

Great Expectations. (2026). Expectations Overview. https://docs.greatexpectations.io/docs/cloud/expectations/expectations_overview/

Northcutt, C. G., Athalye, A. y Mueller, J. (2021). Pervasive Label Errors in Test Sets Destabilize Machine Learning Benchmarks. NeurIPS Datasets and Benchmarks. https://arxiv.org/abs/2103.14749

Northcutt, C. G., Jiang, L. y Chuang, I. L. (2021). Confident Learning: Estimating Uncertainty in Dataset Labels. Journal of Artificial Intelligence Research, 70, 1373-1411. https://doi.org/10.1613/jair.1.12125

Pandera. (2026). Pandera Documentation. https://pandera.readthedocs.io/en/stable/

Ratner, A., Bach, S. H., Ehrenberg, H., Fries, J., Wu, S. y Ré, C. (2017). Snorkel: Rapid Training Data Creation with Weak Supervision. PVLDB, 11(3), 269-282. https://doi.org/10.14778/3157794.3157797

scikit-learn. (2026). train_test_split. https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

TensorFlow. (2026). TensorFlow Data Validation. https://www.tensorflow.org/tfx/data_validation/get_started/

TensorFlow. (2026). TensorFlow Data Validation Anomalies Reference. https://www.tensorflow.org/tfx/data_validation/anomalies

Notas

  1. TensorFlow. (2026). TensorFlow Data Validation. https://www.tensorflow.org/tfx/data_validation/get_started/. Consultado el 6 de junio de 2026.

  2. TensorFlow. (2026). TensorFlow Data Validation Anomalies Reference. https://www.tensorflow.org/tfx/data_validation/anomalies. Consultado el 6 de junio de 2026.

  3. Great Expectations. (2026). Expectations Overview. https://docs.greatexpectations.io/docs/cloud/expectations/expectations_overview/. Consultado el 6 de junio de 2026.

  4. Pandera. (2026). Pandera Documentation. https://pandera.readthedocs.io/en/stable/. Consultado el 6 de junio de 2026.

  5. AWS Labs. (2026). Deequ: Unit Tests for Data. https://github.com/awslabs/deequ. Consultado el 6 de junio de 2026.

  6. Northcutt, C. G., Jiang, L. y Chuang, I. L. (2021). Confident Learning: Estimating Uncertainty in Dataset Labels. Journal of Artificial Intelligence Research, 70, 1373-1411. https://doi.org/10.1613/jair.1.12125

  7. Northcutt, C. G., Athalye, A. y Mueller, J. (2021). Pervasive Label Errors in Test Sets Destabilize Machine Learning Benchmarks. NeurIPS Datasets and Benchmarks. https://arxiv.org/abs/2103.14749

  8. Ratner, A., Bach, S. H., Ehrenberg, H., Fries, J., Wu, S. y Ré, C. (2017). Snorkel: Rapid Training Data Creation with Weak Supervision. PVLDB, 11(3), 269-282. https://doi.org/10.14778/3157794.3157797

  9. scikit-learn. (2026). train_test_split. https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html. Consultado el 6 de junio de 2026.

  10. Cohen, J. (1960). A Coefficient of Agreement for Nominal Scales. Educational and Psychological Measurement, 20(1), 37-46. https://doi.org/10.1177/001316446002000104

Capítulo 03

Facsímil 8 · La ciencia de los datos

Capítulo 03: Splits, muestreo y leakage: medir sin engañarse

Qué deberías poder hacer al terminar

El capítulo anterior nos enseñó a bloquear un dataset con fallos de calidad. Pero un dataset puede pasar schema, licencias, etiquetas y duplicados básicos, y aun así medir mal. La razón suele estar en cómo lo partimos.

Un split no es un porcentaje. Es una promesa de evaluación. Cuando decimos train, validation y test, no estamos repartiendo filas al azar como quien reparte cartas. Estamos diciendo qué puede ver el sistema, qué usamos para ajustar decisiones y qué reservamos para comprobar si generaliza.

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Explicar para qué sirve cada split.No usas test para elegir prompt, modelo o umbral.
Elegir estrategia de muestreo según la pregunta.No haces random split si hay tiempo, grupos o fuentes repetidas.
Detectar leakage por entidad, fuente, texto y tiempo.Sabes buscar estudiantes, documentos o textos que cruzan splits.
Medir distribución de etiquetas por split.No celebras un split si test pierde clases críticas.
Comparar estrategias de partición.Puedes justificar random, estratificado, por grupo, temporal o híbrido.
Construir un manifiesto de split.Dejas asignaciones y hallazgos versionados.

La frase central del capítulo:

Un split mide una pregunta. Si partes mal, la respuesta parece científica y no lo es.

La escena: una métrica que sube demasiado

Imagina que evaluamos un asistente académico. Hacemos un train/test split aleatorio y obtenemos una métrica preciosa. El sistema responde muy bien sobre matrículas, becas y pagos. Todo parece listo para enseñar.

Luego alguien mira los casos. Un estudiante aparece en train y test. Un documento fuente está repetido en ambos. Una consulta de test es casi igual a una de train. Además, algunos ejemplos de train tienen fecha posterior a ejemplos de test. La métrica no está midiendo generalización: está midiendo familiaridad.

Este es uno de los errores más caros porque no rompe el código. Al contrario: el código funciona, el reporte se ve profesional y la gráfica sube. Justo por eso hay que tratar los splits como ingeniería, no como una llamada rápida a una función.

Qué no es un split

Un split no es “60/20/20 y ya”. Esos números dicen cuántas filas hay, no si la partición responde bien a la pregunta. Si hay varios tickets de la misma persona, un random split puede poner unos en train y otros en test. Si hay documentos con versiones parecidas, puede partir la misma evidencia en dos. Si hay tiempo, puede entrenar con eventos posteriores y evaluar con eventos anteriores.

Tampoco es una garantía automática de independencia. Dos filas distintas pueden compartir entidad, fuente, plantilla, texto, anotador o evento. Para un modelo o un retriever, esa cercanía puede ser suficiente para inflar resultados.

Y test no es un lugar donde mirar muchas veces. Si usamos test para decidir prompts, elegir modelo, ajustar umbrales, cambiar chunking o seleccionar features, test deja de ser una medida final. Se convierte en otra validación, aunque sigamos llamándolo test.

Qué sí es un split de evaluación

Un split es una partición diseñada para responder a una pregunta de generalización:

D=DtrainDvalDtestD = D_{train} \cup D_{val} \cup D_{test}

con:

DtrainDvalDtest=D_{train} \cap D_{val} \cap D_{test} = \varnothing
SímboloSignificadoEjemplo
DDDataset completo.24 casos de soporte.
DtrainD_{train}Datos que el sistema puede usar para aprender.Casos anteriores usados para ajustar.
DvalD_{val}Datos para elegir decisiones durante desarrollo.Elegir prompt, umbral o estrategia.
DtestD_{test}Datos reservados para medir al final.Casos no usados para ajustar nada.
\varnothingIntersección vacía.Ninguna fila debería estar en dos splits.

La intersección vacía de filas es necesaria, pero no suficiente. También necesitamos evitar solapamiento de entidades, fuentes o información temporal cuando esas dimensiones afecten a la pregunta.

Fecha de corte del estado del arte

Fecha de corte: 6 de junio de 2026.
Fuentes consultadas: documentación oficial de scikit-learn sobre train_test_split, GroupKFold, StratifiedGroupKFold y TimeSeriesSplit; literatura sobre leakage en data mining y reproducibilidad de evaluación con machine learning; y el paper original de Retrieval-Augmented Generation para situar por qué, en RAG, documentos y consultas también forman parte de la evaluación.

train_test_split permite partir arrays o matrices en subconjuntos aleatorios de entrenamiento y test, con opciones como test_size, train_size, random_state, shuffle y stratify.1 Esa función es útil, pero no decide por nosotros si un random split es correcto.

GroupKFold mantiene grupos no solapados entre folds, y StratifiedGroupKFold intenta preservar proporciones de clases sin partir grupos.23 TimeSeriesSplit trabaja con particiones ordenadas en el tiempo, donde cada train es anterior al test correspondiente.4

Kaufman, Rosset, Perlich y Stitelman definieron leakage como la introducción de información sobre el objetivo que no debería estar disponible legítimamente para el modelo, y lo trataron como un error recurrente en proyectos reales y competiciones.5 Kapoor y Narayanan revisaron leakage como una fuente importante de problemas de reproducibilidad en ciencia basada en machine learning.6

Lewis y colaboradores formalizaron RAG como una combinación de modelo paramétrico y memoria no paramétrica recuperada desde documentos.7 Esa idea cambia la conversación sobre splits: no basta con partir preguntas, también hay que controlar documentos, versiones, chunks e índices de recuperación.

La lección estable es esta: las funciones de partición ayudan, pero la garantía viene de entender la estructura del dato.

Estrategias de muestreo

Antes de elegir una estrategia, debemos escribir la pregunta de evaluación. ¿Queremos saber si el sistema generaliza a nuevos casos de las mismas personas? ¿A nuevas personas? ¿A documentos futuros? ¿A otro periodo? ¿A clases raras? Cada pregunta pide un split distinto.

EstrategiaQué preservaQué puede romper
Random por filaProporciones aproximadas si hay suficientes datos.Grupos, fuentes, tiempo y textos cercanos.
Estratificado por etiquetaDistribución de clases.Entidades repetidas o tiempo.
Por grupoEntidades no solapadas.Distribución de etiquetas o cronología.
TemporalSimulación de futuro.Grupos repetidos o clases raras.
Temporal por grupoTiempo y entidad a la vez.Puede dejar alguna distribución en revisión.

No hay estrategia universal. Si todos los casos de una misma persona se parecen, necesitas grupo. Si el producto cambia con el tiempo, necesitas tiempo. Si hay clases muy raras, necesitas mirar cobertura por etiqueta. Si hay documentos comunes, quizá necesitas agrupar por fuente.

Las fórmulas que sí conviene saber

Para medir si los splits conservan etiquetas, podemos comparar proporciones:

ps(y=k)=ns,knsp_s(y=k)= \frac{n_{s,k}}{n_s}
SímboloSignificadoEjemplo
ssSplit.train, validation, test.
kkEtiqueta concreta.escalate.
ns,kn_{s,k}Ejemplos de la etiqueta kk en el split ss.Casos escalate en test.
nsn_sTotal de ejemplos del split ss.5 casos de test.

Para comparar la distribución de un split con la global usamos distancia total variation:

DTV(P,Q)=12iPiQiD_{TV}(P,Q)= \frac{1}{2} \sum_i |P_i-Q_i|
SímboloSignificado
PiP_iProporción global de la clase ii.
QiQ_iProporción de la clase ii en el split.
DTVD_{TV}Distancia entre ambas distribuciones.

Para textos cercanos usamos Jaccard, igual que en el capítulo anterior:

J(A,B)=ABABJ(A,B)= \frac{|A \cap B|}{|A \cup B|}
SímboloSignificado
AATokens del primer texto.
BBTokens del segundo texto.
$A \cap B
$A \cup B

Y para leakage temporal podemos mirar si train contiene filas posteriores al primer test:

future_train={eDtrain:t(e)>min(t(Dtest))}future\_train = \{e \in D_{train}: t(e) > \min(t(D_{test}))\}
SímboloSignificado
eeEjemplo individual.
t(e)t(e)Fecha del ejemplo.
DtrainD_{train}Split de entrenamiento.
DtestD_{test}Split de prueba.

Si ese conjunto no está vacío en una evaluación temporal, tenemos una señal clara de que la partición no simula futuro.

Tipos de leakage que debe mirar un ingeniero

Leakage no siempre se ve como una fila duplicada. Muchas veces aparece como una relación escondida.

TipoCómo apareceQué check ayuda
Por filaMismo case_id o mismo texto.Duplicado exacto.
Por entidadMisma persona, cliente, documento o dispositivo en train y test.Group split.
Por fuenteMismo source_id o versión documental.Agrupar por fuente.
Por texto cercanoPreguntas casi iguales en splits distintos.Jaccard, embeddings o revisión.
TemporalTrain ve eventos posteriores a test.Split temporal.
De preprocesamientoEscalado, imputación o selección de features hecha con todo el dataset.Fit solo con train.
De decisiónTest se usa para elegir prompt, modelo o umbral.Separar validation y test real.

El leakage de preprocesamiento merece una frase aparte. Si calculas la media de una columna con todo el dataset y luego escalas train y test, test ya influyó en train. La solución es sencilla conceptualmente: fit de transformaciones solo en train; transform en validation y test.

El split como contrato de evaluación

En ingeniería conviene dejar de hablar del split como una operación suelta y empezar a tratarlo como un contrato. Un contrato de split responde a preguntas que deberían quedar por escrito:

PreguntaRespuesta que debe quedar versionada
¿Qué decisión medimos?Clasificador, RAG, prompt, modelo, retriever, umbral o pipeline completo.
¿Qué estrategia se eligió?Random, estratificada, por grupo, temporal, temporal por grupo o una combinación propia.
¿Qué claves protegen la independencia?case_id, student_id, source_id, created_at, label, text.
¿Qué puede hacerse con cada split?Train entrena, validation decide, test mide, holdout confirma.
¿Qué está prohibido después de mirar test?Elegir modelo, reescribir prompt, ajustar umbral, cambiar chunking o modificar el retriever.
¿Qué hashes demuestran reproducibilidad?Hash del dataset, hash de la política y asignaciones por split.

El artefacto que recoge todo eso es el manifiesto de split. En el kit se genera como output/split_manifest.json. Un manifiesto mínimo debería contener:

{
  "policy_id": "support-split-policy-v1",
  "dataset": {
    "sha256": "..."
  },
  "split_contract": {
    "selected_strategy": "time_group_holdout",
    "gate": "review",
    "keys": {
      "group": "student_id",
      "source": "source_id",
      "time": "created_at"
    }
  }
}

El hash no es decoración. Si cambias una fila, una etiqueta o una fecha, el hash del dataset cambia. Si cambias una regla de la política, el hash de la política cambia. Eso permite reconstruir qué se midió, con qué reglas y por qué la métrica era defendible en ese momento.

En un equipo real, el manifiesto evita discusiones imposibles semanas después. Si alguien pregunta “¿por qué aquella métrica bajó al repetir el experimento?”, no deberíamos responder mirando una gráfica suelta. Deberíamos poder abrir el manifiesto, comprobar el hash del dataset, ver qué política estaba activa, saber qué estrategia asignó cada case_id y revisar si test se usó solo para medir o también para decidir. Esa diferencia parece administrativa, pero es ingeniería: sin trazabilidad, una métrica deja de ser una medida y se convierte en una anécdota difícil de reproducir.

El manifiesto también ayuda a integrar evaluación en CI/CD. Puedes bloquear una ejecución si cambia el hash del dataset sin regenerar el split, si falta una predicción para un caso de test, si validation o test se usan para hacer fit de un transformador, o si una política nueva modifica los umbrales sin actualizar la decisión. En proyectos de IA, muchas regresiones no vienen de una línea de modelo, sino de una línea de datos que cambió sin que nadie la registrara.

Ejemplo de fórmula: para este facsímil podemos pensar el manifiesto de split así. No es una especificación estándar; es una forma compacta de recordar qué debe quedar versionado para que la evaluación sea reproducible.

M=(hD,hP,S,A,G)M = (h_D, h_P, S, A, G)
SímboloSignificado
MMManifiesto de split.
hDh_DHash del dataset.
hPh_PHash de la política de split.
SSEstrategia elegida.
AAAsignación de IDs a train, validation y test.
GGResultado del gate: pass, review o block.

La métrica sin manifiesto es débil. Puede estar bien, pero no sabemos repetirla ni auditarla.

Leakage de preprocesamiento

Una fuga clásica no aparece en el split, sino en el pipeline. Suele pasar cuando hacemos esto:

  1. Cargar todo el dataset.
  2. Normalizar, imputar, seleccionar variables o crear vocabulario.
  3. Partir en train, validation y test.
  4. Entrenar y medir.

El problema está en el paso 2. Si una transformación aprende algo del dataset completo, validation y test ya han participado en el entrenamiento, aunque el modelo principal no los haya visto.

La versión correcta es:

θT=fit(T,Dtrain)\theta_T = fit(T, D_{train}) Xs=transform(TθT,Xs),s{train,val,test}X'_s = transform(T_{\theta_T}, X_s), \quad s \in \{train, val, test\}
SímboloSignificado
TTTransformación: escalado, imputación, PCA, vectorizador, calibrador.
θT\theta_TParámetros aprendidos por la transformación.
DtrainD_{train}Datos usados para aprender esos parámetros.
XsX_sFeatures originales del split ss.
XsX'_sFeatures transformadas del split ss.

La regla práctica:

TransformaciónQué aprendeDónde se hace fitQué se aplica a validation/test
NormalizaciónMedia, desviación, mínimos o máximos.Solo train.transform con parámetros de train.
ImputaciónMedia, moda, percentil o modelo auxiliar.Solo train.Relleno con reglas aprendidas en train.
Selección de featuresVariables que parecen predictivas.Solo train, o dentro de cada fold.Mismas features elegidas.
PCAComponentes y proyección.Solo train.Misma proyección.
TF-IDFVocabulario e IDF.Solo train.Misma matriz de vocabulario.
OversamplingEjemplos sintéticos o pesos.Solo train.Nunca se sintetiza test.

La frase que debería quedar pegada a la pantalla: primero partes, luego aprendes transformaciones.

En el kit, esta idea se convierte en un script ejecutable: ops/preprocessing_fit_audit.py. El script no entrena un modelo grande; hace algo más pequeño y muy útil para aprender: compara el vocabulario que obtendrías si ajustas un vectorizador con solo train frente al vocabulario que obtendrías usando todo el dataset. Si el vocabulario global aprende palabras que solo aparecen en validation o test, acabas de demostrar una fuga de preprocesamiento con un ejemplo que cabe en una terminal.

Por ejemplo, con el split recomendado del kit, el vectorizador ajustado solo con train no conoce algunos términos que aparecen en test, como convocatoria, abonado, confirmacion o bloqueada. Eso es normal: test representa futuro o datos reservados. Si ajustas el vectorizador con todo el dataset antes de partir, esas palabras entran en el vocabulario desde el principio. El modelo todavía no ha visto la etiqueta de test, pero su representación ya fue preparada con información del test. En texto, ese detalle es importante porque vocabulario, IDF, normalizadores y reglas de tokenización forman parte de lo que el sistema aprende.

Puedes ejecutarlo así:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/split_audit.py --write
python3 ops/preprocessing_fit_audit.py --write
cat output/preprocessing_fit_decision.md

La salida no pretende decir “este vocabulario es malo”. Dice algo más concreto: si quieres medir honestamente, el fit del vectorizador debe ocurrir después del split y solo con train. Luego aplicas ese mismo vectorizador a validation y test. Ese patrón se traslada igual a StandardScaler, imputadores, PCA, selección de features, calibración, oversampling o cualquier transformación que aprenda parámetros.

RAG y LLM eval también tienen splits

En un clasificador tabular, solemos pensar en filas. En RAG y evaluación de LLMs hay más piezas:

ObjetoPor qué puede contaminar la evaluación
DocumentoEl mismo documento puede generar chunks, preguntas y respuestas en varios splits.
ChunkDos chunks hermanos pueden contener casi la misma evidencia.
Pregunta sintéticaSi se genera desde un documento, hereda su grupo.
Respuesta esperadaSi acaba en trazas de desarrollo, el test deja de ser final.
Prompt few-shotEjemplos demasiado parecidos al test facilitan la tarea artificialmente.
Índice de recuperaciónSi mezcla corpus de desarrollo y test, la medición no separa conocimiento.
Herramientas y trazasLogs de ejecución pueden contener soluciones, IDs o rutas documentales.

Para RAG, la regla no debería ser “parto preguntas”. Debería ser:

g(di)=g(dj)split(di)=split(dj)g(d_i) = g(d_j) \Rightarrow split(d_i) = split(d_j)
SímboloSignificado
di,djd_i, d_jDocumentos, chunks o preguntas derivadas.
g()g(\cdot)Grupo documental: document_id, source_id, versión o URL canónica.
split()split(\cdot)Partición asignada.

Si dos chunks vienen del mismo documento, no deberían terminar uno en train y otro en test salvo que la evaluación esté diseñada explícitamente para medir recuperación sobre documentos compartidos. Y si ese caso existe, debe declararse, porque ya no estamos midiendo generalización documental.

En evaluación de LLMs hay otra trampa: mirar fallos de test para mejorar el prompt. La primera vez puede ser análisis. La segunda empieza a parecer ajuste. Si cambiamos el prompt, el modelo, el formato de salida, el sistema de herramientas o la rúbrica porque vimos test, test ya no es final. Necesitamos validation o un nuevo holdout.

Un ejemplo operativo: supón que tienes 200 preguntas para evaluar un RAG de normativa universitaria. Si generas 100 preguntas desde un documento de becas y luego repartes esas preguntas al azar, algunas acabarán en train, otras en validation y otras en test. El modelo o el equipo no ven exactamente la misma pregunta, pero sí ven el mismo documento, los mismos términos y a veces la misma respuesta escrita de otra manera. Para medir generalización documental, eso no vale. El grupo no debería ser la pregunta: debería ser el documento, la versión del documento o la fuente canónica.

Otro caso frecuente: usas ejemplos few-shot en el prompt. Esos ejemplos también tienen que salir de train o validation, no del test. Si al mirar el test descubres que el modelo falla en “matrícula bloqueada” y copias un ejemplo parecido al prompt, has convertido el test en una herramienta de ajuste. La práctica correcta no es dejar de aprender del error; es mover esa decisión a validation y reservar un nuevo holdout si quieres comunicar una cifra final.

Validación cruzada avanzada

La validación cruzada no arregla por sí sola un split mal pensado. Solo repite una regla de partición varias veces. Si la regla parte grupos o mezcla futuro, el problema se repite en cada fold.

MétodoCuándo sirveRiesgo si se usa sin pensar
KFoldDatos independientes y suficientes.Parte entidades repetidas.
StratifiedKFoldClasificación con clases desbalanceadas.Conserva etiquetas, pero puede mezclar grupos.
GroupKFoldHay usuarios, estudiantes, clientes, pacientes, documentos o dispositivos.Puede dejar folds con etiquetas descompensadas.
StratifiedGroupKFoldNecesitas grupos no compartidos y proporciones de clases razonables.No siempre puede satisfacer ambas cosas si el dataset es pequeño.
TimeSeriesSplitEvaluación hacia futuro.No protege entidades repetidas por sí solo.
Validación cruzada anidadaSeparar selección de hiperparámetros y estimación final.Es más cara y exige disciplina con pipelines.

La validación cruzada anidada se usa cuando queremos seleccionar hiperparámetros sin engañar la estimación. La idea:

CVouterR^CV_{outer} \rightarrow \hat{R} CVinnerλCV_{inner} \rightarrow \lambda^*
SímboloSignificado
CVouterCV_{outer}Bucle externo que estima rendimiento.
CVinnerCV_{inner}Bucle interno que elige configuración dentro de cada train externo.
R^\hat{R}Estimación de rendimiento.
λ\lambda^*Hiperparámetros elegidos.

Si usas el mismo fold para elegir y medir, el resultado tiende a ser optimista. No porque nadie haya hecho nada extraño, sino porque el proceso de selección ya miró esa señal.

Negativos difíciles, ranking y recuperación

En RAG, ranking y clasificación semántica, los ejemplos negativos importan mucho. Un negativo fácil es un caso claramente distinto. Un negativo difícil es uno que se parece mucho al positivo pero requiere distinguir un detalle.

CasoPositivoNegativo difícil
Beca“requisitos de beca general”“requisitos de beca de movilidad”
Pago“justificante de pago pendiente”“pago duplicado reclamado”
Matrícula“plazo ordinario de matrícula”“ampliación de matrícula fuera de plazo”

Los negativos difíciles enseñan y evalúan mejor, pero también pueden contaminar si se generan mezclando splits. La regla operativa:

  1. Si generas negativos antes de partir, agrupa por entidad y fuente para que no crucen splits.
  2. Si generas negativos después de partir, hazlo dentro de cada split.
  3. Si usas embeddings para buscar negativos, no uses el índice de test para seleccionar ejemplos de train.
  4. Si ajustas un reranker, mide con consultas y documentos que no hayan participado en su selección.

Para un retriever, una evaluación mínima debería reportar:

MétricaQué pregunta responde
recall@k¿El documento correcto aparece entre los kk primeros?
MRR¿A qué altura aparece el primer resultado útil?
Precisión de contexto¿Cuánto contexto recuperado es realmente relevante?
Cobertura por fuente¿El sistema recupera bien todos los tipos de documento?
Latencia¿La recuperación cabe en el presupuesto operativo?

Este punto prepara el capítulo de embeddings y los capítulos de RAG: la evaluación de recuperación también empieza por un split honesto.

Tamaño mínimo, intervalos y slices

Un test pequeño puede ser honesto y aun así poco informativo. Si medimos accuracy con 20 ejemplos, pasar de 15 a 16 aciertos cambia la métrica de 75% a 80%. Eso no es una mejora estable; puede ser ruido muestral.

Una aproximación rápida para una proporción es:

SE(p^)=p^(1p^)nSE(\hat{p}) = \sqrt{\frac{\hat{p}(1-\hat{p})}{n}} IC95p^±1.96SE(p^)IC_{95} \approx \hat{p} \pm 1.96 \cdot SE(\hat{p})
SímboloSignificado
p^\hat{p}Métrica como proporción: accuracy, tasa de acierto, recall binario.
nnNúmero de ejemplos del test.
SESEError estándar aproximado.
IC95IC_{95}Intervalo de confianza aproximado al 95%.

Ejemplo: si p^=0.80\hat{p}=0.80 y n=25n=25, entonces:

SE0.80.225=0.08SE \approx \sqrt{\frac{0.8 \cdot 0.2}{25}} = 0.08

El intervalo aproximado sería 0.80±0.160.80 \pm 0.16. Es decir, el test dice algo, pero todavía no permite presumir precisión quirúrgica. Para métricas más complejas, bootstrap suele ser una opción práctica: remuestrear el test muchas veces y observar la distribución de la métrica.

Además de mirar la media global, hay que mirar slices. Un sistema puede tener buen resultado global y fallar justo en el segmento que importa.

SlicePor qué mirarlo
productMatrícula, becas, pagos, horarios o prácticas pueden tener dificultad distinta.
channelPortal, email y chat no generan el mismo lenguaje.
labelLas clases raras suelen desaparecer en tests pequeños.
source_idAlgunas fuentes documentales son más ambiguas.
FechaCambios de periodo pueden alterar vocabulario y reglas.
CriticidadNo todos los errores cuestan lo mismo.
Idioma o regiónSi existen, pueden cambiar distribución y estilo.

La pregunta técnica no es solo “¿cuánto acierta?”. También es: “¿dónde falla, con cuánta evidencia y qué decisión puedo tomar sin engañarme?”.

El segundo script práctico del kit trabaja justo esta parte: ops/evaluate_test_slices.py. Lee data/model_predictions.csv, toma del manifiesto los IDs asignados a test y evalúa solo esos casos. Esto es importante: no deja que se cuele una predicción de train o validation en la métrica final. Después calcula accuracy, intervalo aproximado, latencia y slices por product, channel y label.

Con el dataset pequeño del capítulo, el resultado esperado es deliberadamente incómodo: accuracy de 0.75 con solo 4 casos de test, un fallo en el caso s023 y una decisión review_test_too_small. Eso enseña una lección que muchos proyectos aprenden tarde: una métrica global puede sonar bien y seguir sin ser suficiente para tomar una decisión fuerte. Si el único caso escalate del test falla, la media global no cuenta toda la historia. Si cada producto tiene un único ejemplo, ningún slice tiene evidencia suficiente. El reporte no bloquea por capricho; te obliga a mirar la métrica con tamaño, contexto y coste del error.

Puedes ejecutarlo así:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/evaluate_test_slices.py --write
cat output/evaluation_slice_decision.md
python3 -m json.tool output/evaluation_slice_report.json

Este ejemplo sí se puede reutilizar. Cambias data/model_predictions.csv por las predicciones de tu modelo, mantienes case_id, predicted_label, confidence y latency_ms, y el script usa el manifiesto para decidir qué pertenece a test. Si tu proyecto mide otra cosa, cambias la función de métrica, pero mantienes el contrato: IDs versionados, split congelado, slices explícitos y decisión documentada.

Política de test y holdout final

La política sencilla:

SplitPermiso
TrainAprender.
ValidationElegir.
TestMedir una decisión cerrada.
Holdout finalConfirmar una conclusión importante.

Cuando test se usa para decidir, deja de ser test final. En un proyecto real eso no debería vivirse como culpa, sino como trazabilidad: se anota y se crea una nueva partición final si hace falta.

Un ejemplo concreto:

  1. Entrenas tres modelos con train.
  2. Eliges el mejor con validation.
  3. Mides una vez con test.
  4. Ves que falla en “becas”.
  5. Cambias el prompt, el chunking o el retriever.
  6. La siguiente medición ya no debería venderse como test puro.

La solución profesional es reservar un holdout final para decisiones importantes o crear una nueva versión de evaluación. No siempre hace falta en un ejercicio pequeño; sí hace falta cuando vas a comunicar rendimiento, comparar sistemas o tomar una decisión con impacto.

Anatomía de una partición que no se engaña

Anatomía de un split sin contaminación Diagrama en blanco y negro que muestra estrategias de split, checks de leakage y decisión final. Partir datos es diseñar una evaluación La estrategia elegida debe respetar la pregunta: filas, etiquetas, grupos, fuentes y tiempo. Dataset con estructura case_id student_id source_id created_at label sin estas columnas no sabemos qué leakage buscar Random rápido pero mezcla grupos Estratificado cuida etiquetas no cuida tiempo Por grupo no parte estudiantes puede romper fechas Temporal simula futuro puede partir grupos Temporal + grupo respeta fechas mantiene entidades puede quedar en review Checks de leakage grupo compartido source_id compartido texto exacto o cercano fit antes de partir chunks cruzados si falla, no midas todavía Checks de cobertura labels en test distancia TV segmentos críticos puede ser review Decisión pass review block hashes + IDs split_manifest.json El mejor split no es el más equilibrado: es el que responde honestamente a la pregunta. IA para gente curiosa / Facsímil 08 / Capítulo 03 / 686f6c61
Una partición seria combina estrategia, checks de leakage, cobertura y una decisión documentada.

Esto en un proyecto real

Un equipo profesional debería discutir el split antes de mirar resultados. Si elegimos estrategia después de ver métricas, ya estamos contaminando la decisión. La pregunta correcta es: “¿qué uso real queremos simular?”.

SituaciónSplit razonablePor qué
Tickets de los mismos clientesPor cliente o cuenta.Evita que el sistema vea estilos repetidos.
Documentación vivaTemporal por versión.Evalúa contra futuro documental.
Datasets médicos o académicos por personaPor sujeto o estudiante.Evita que la misma entidad cruce particiones.
Clases rarasEstratificado con revisión manual.Evita perder casos críticos en test.
Logs de productoTemporal.Simula despliegue hacia adelante.

La regla profesional: si una entidad puede generar varias filas parecidas, no partas por fila hasta demostrar que no contamina.

Por qué debería importarte

Una mala partición puede hacer que un modelo mediocre parezca excelente. También puede hacer que un modelo bueno parezca inestable si el test no cubre clases importantes. En ambos casos, la decisión técnica se apoya en una medición defectuosa.

Este capítulo importa porque casi todo lo que sigue depende de aquí: features, embeddings, slices, drift, análisis causal y gobernanza. Si test no es honesto, los capítulos posteriores están midiendo sobre una base torcida.

Manos a la obra

El kit del capítulo está en:

kit/

Compara cinco estrategias sobre el mismo dataset:

EstrategiaQué intentaResultado esperado en el kit
random_rowRepartir filas con orden pseudoaleatorio estable.block.
stratified_labelConservar proporción de etiquetas.block.
group_holdoutNo partir estudiantes.block.
time_cutoffRespetar cronología.block.
time_group_holdoutCombinar tiempo y grupos.review.

Estructura

kit/
  README.md
  data/model_predictions.csv
  data/support_split_cases.csv
  contracts/evaluation_use_policy.md
  contracts/preprocessing_policy.json
  contracts/rag_llm_eval_policy.json
  contracts/split_policy.json
  ops/evaluate_test_slices.py
  ops/preprocessing_fit_audit.py
  ops/split_audit.py
  output/evaluation_slice_decision.md
  output/evaluation_slice_report.json
  output/preprocessing_fit_decision.md
  output/preprocessing_fit_report.json
  output/split_manifest.json
  output/split_report.json
  output/strategy_comparison.csv
  output/leakage_findings.csv
  output/split_assignments.csv
  output/split_decision.md

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/split_audit.py --write
cat output/split_decision.md
python3 -m json.tool output/split_manifest.json
python3 ops/preprocessing_fit_audit.py --write
cat output/preprocessing_fit_decision.md
python3 ops/evaluate_test_slices.py --write
cat output/evaluation_slice_decision.md

Qué deberías ver

La estrategia recomendada debería ser time_group_holdout, pero con gate review. Esto es importante: la estrategia evita leakage fuerte por grupo, fuente, texto y tiempo, pero deja una revisión por distribución de etiquetas. No todo se arregla automáticamente.

{
  "chosen_strategy": "time_group_holdout",
  "recommendation": "revisar label_distribution_shift"
}

En output/split_manifest.json deberías ver cuatro cosas especialmente importantes:

CampoPor qué importa
dataset.sha256Si cambia el dataset, cambia la medición.
policy.sha256Si cambia la política, cambia el contrato.
split_contract.keysExplica qué claves protegen grupos, fuentes, tiempo y etiquetas.
assignments_by_splitPermite reconstruir qué casos estaban en train, validation y test.

Después, output/preprocessing_fit_decision.md debería bloquear el fit con todo el dataset. La lectura útil no es memorizar los términos concretos del ejemplo, sino entender el patrón: si una transformación aprende parámetros con validation o test, la evaluación queda preparada con información reservada.

Por último, output/evaluation_slice_decision.md debería dejar la evaluación en revisión por tamaño de test. Verás una accuracy global de 0.75, pero también un fallo en s023, slices con una sola muestra y un intervalo demasiado ancho para vender una conclusión fuerte. Eso es exactamente lo que queremos que aprenda un alumno: una evaluación seria no solo imprime una métrica, también dice cuánto puedes fiarte de ella.

Cómo lo adaptas a tu caso

Si tu problema tiene...Añade al contrato
Clientes repetidosgroup_field: customer_id.
Documentos versionadossource_group: document_id y version_date.
Tiempo críticoVentanas temporales y fecha mínima de test.
Clases rarasLabels obligatorias en validation y test.
TransformacionesRegla de fit solo con train.
RAGProhibir que chunks del mismo documento crucen splits.
Evaluaciones de LLMSeparar prompt, ejemplos few-shot, rúbrica y respuestas esperadas.
Ranking o retrieverGenerar negativos difíciles sin cruzar splits.
Métricas públicasHoldout final o nueva versión de evaluación.

Qué entregaría un alumno

  1. split_report.json generado.
  2. strategy_comparison.csv explicado.
  3. leakage_findings.csv revisado.
  4. split_manifest.json con hashes y asignaciones.
  5. split_decision.md con decisión propia.
  6. preprocessing_fit_report.json y decisión de preprocesado.
  7. evaluation_slice_report.json y lectura por slices.
  8. Una regla de preprocesado que demuestre fit solo con train.
  9. Una propuesta de split para un dataset real, justificando grupos, tiempo, RAG si aplica y cobertura.

Cómo encaja todo

Este capítulo conecta calidad de datos con evaluación. El capítulo 02 detectaba fallos dentro del dataset; este capítulo pregunta si la partición permite medir sin engañarse. El capítulo 04 usará estos splits para hablar de features y embeddings: ahí veremos que una transformación también puede introducir leakage si se ajusta con todo el dataset.

graph TD
    subgraph "Este capítulo"
        Q["Pregunta de evaluación"]
        CONTRACT["Contrato de split"]
        UNIT["Unidad y muestreo"]
        LEAK["Leakage"]
        FIT["Fit solo con train"]
        MANIFEST["Split manifest"]
        DEC["Decisión de split"]
        HOLD["Holdout final"]
    end
    subgraph "Mismo facsímil"
        C01["Datos y linaje<br/>cap. 1"]
        C02["Calidad<br/>cap. 2"]
        C04["Features<br/>cap. 4"]
        C05["Slices<br/>cap. 5"]
        C06["DataOps<br/>cap. 6"]
    end
    subgraph "Otros facsímiles"
        RAG["RAG<br/>fasc. 4"]
        EVAL["Evals<br/>fasc. 7"]
        GOV["Gobernanza<br/>fasc. 9"]
    end

    C01 -->|"declara campos"| CONTRACT
    C02 -->|"bloquea datos rotos"| CONTRACT
    EVAL -->|"necesita test honesto"| DEC

    Q -->|"se escribe en"| CONTRACT
    CONTRACT -->|"elige"| UNIT
    UNIT -->|"puede introducir"| LEAK
    LEAK -->|"obliga a"| FIT
    FIT -->|"se registra en"| MANIFEST
    UNIT -->|"se registra en"| MANIFEST
    MANIFEST -->|"sostiene"| DEC
    DEC -->|"reserva"| HOLD

    FIT -->|"protege"| C04
    UNIT -->|"se revisa por"| C05
    MANIFEST -->|"se monitoriza en"| C06
    MANIFEST -->|"prepara evaluación RAG"| RAG
    HOLD -->|"cierra afirmaciones"| EVAL
    MANIFEST -->|"documenta"| GOV

    style Q fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CONTRACT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style UNIT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style LEAK fill:#F5F5F5,stroke:#000000,stroke-width:2
    style FIT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style MANIFEST fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DEC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style HOLD fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C01 stroke-dasharray: 5 5
    style C02 stroke-dasharray: 5 5
    style C04 stroke-dasharray: 5 5
    style C05 stroke-dasharray: 5 5
    style C06 stroke-dasharray: 5 5
    style RAG stroke-dasharray: 5 5
    style EVAL stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
SplitPartición de un dataset con finalidad concreta.
TrainSplit que puede usarse para aprender o ajustar.
ValidationSplit para elegir decisiones durante desarrollo.
TestSplit reservado para medir al final.
HoldoutConjunto separado que no se usa durante ajuste.
EstratificaciónMantener proporciones de etiquetas o segmentos.
Split por grupoMantener todas las filas de una entidad juntas.
Split temporalRespetar orden cronológico.
LeakageInformación indebida que contamina la evaluación.
PurgaSeparar o retirar ejemplos demasiado cercanos.
Distancia TVMedida de diferencia entre distribuciones.
Manifiesto de splitDocumento técnico con hashes, estrategia, claves, permisos y asignaciones.
Leakage de preprocesamientoFuga causada por transformaciones ajustadas antes de partir o usando splits reservados.
RAG leakageFuga en documentos, chunks, preguntas, respuestas esperadas, prompts o índices.
Negativo difícilEjemplo muy parecido al positivo, pero con etiqueta o respuesta distinta.
Holdout finalPartición reservada para confirmar una conclusión después de cerrar decisiones.
SliceSubconjunto relevante del test: producto, canal, etiqueta, fuente, fecha o criticidad.
Error estándarEstimación de cuánto puede variar una métrica por tamaño de muestra.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Confundir porcentaje con validez60/20/20 parece profesional.Preguntar qué decisión simula cada split.
Estratificar y olvidarme de gruposLas clases quedan bonitas.Revisar student_id, cliente, fuente o documento.
Hacer split después de transformarEl pipeline parece más cómodo.Separar primero; ajustar transformaciones solo en train.
Mirar test demasiadas vecesEs tentador ajustar contra la métrica final.Usar validation para decisiones y test para cierre.
Ignorar el tiempoRandom parece estable.Usar split temporal si producción será futura.
Partir preguntas RAG sin agrupar documentosParece que cada pregunta es independiente.Agrupar por documento, versión, fuente o URL canónica.
Hacer negativos difíciles con todo el índiceSale una evaluación más dura, pero mezclada.Generarlos dentro de cada split o con grupos congelados.
No guardar manifiestoEl reporte parece suficiente.Versionar hashes, política, estrategia e IDs por split.
Celebrar una métrica con test pequeñoEl número tiene demasiada varianza.Acompañar con tamaño, intervalo y slices.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Por qué un split no es solo un porcentaje?
  2. ¿Qué diferencia hay entre train, validation y test?
  3. ¿Cuándo usarías split por grupo?
  4. ¿Cuándo usarías split temporal?
  5. ¿Por qué una estrategia estratificada puede seguir contaminada?
  6. ¿Qué mide Jaccard en el kit?
  7. ¿Qué significa future_train_vs_test?
  8. ¿Por qué time_group_holdout queda en review y no en pass?
  9. ¿Qué archivo del kit explica los hallazgos de leakage?
  10. ¿Cómo evitarías leakage de preprocesamiento?
  11. ¿Por qué un documento RAG puede contaminar varias preguntas?
  12. ¿Qué pasa si miras test para cambiar el prompt?
  13. ¿Qué diferencia hay entre validation, test y holdout final?
  14. ¿Qué debería guardar un split_manifest.json?
  15. ¿Cuándo usarías StratifiedGroupKFold en vez de KFold?
  16. ¿Por qué una métrica global puede esconder fallos por slice?
  17. ¿Qué te dice el error estándar cuando el test es pequeño?
  18. ¿Qué demuestra preprocessing_fit_audit.py?
  19. ¿Por qué evaluate_test_slices.py filtra por IDs del manifiesto?
  20. ¿Qué cambiarías en model_predictions.csv para usarlo con tu propio modelo?

En resumen

IdeaQué te llevas
Un split mide una pregunta.La estrategia depende del uso real.
Random no siempre es inocente.Puede mezclar grupos, fuentes y tiempo.
Estratificar no basta.Conserva labels, pero no protege entidades.
El tiempo cambia la evaluación.Entrenar con futuro infla resultados.
La mejor estrategia puede quedar en review.Evitar leakage no garantiza cobertura perfecta.
El split debe versionarse.Asignaciones, hallazgos y decisión son artefactos.
Preprocesar también aprende.Todo fit que aprende parámetros debe usar train.
RAG añade nuevas fronteras.Documentos, chunks, prompts y respuestas esperadas también se separan.
Test no decide.Si test decide, necesitas validation nueva o holdout final.
Los negativos difíciles se controlan.Son útiles, pero deben respetar grupos y particiones.
El tamaño importa.Un test pequeño necesita intervalo, cautela y lectura por slices.
Los ejemplos deben ejecutarse.El kit genera reportes de split, preprocesado y evaluación por slices.

Para saber más

Kapoor, S. y Narayanan, A. (2023). Leakage and the Reproducibility Crisis in Machine-Learning-Based Science. Patterns, 4(9), 100804. DOI

Kaufman, S., Rosset, S., Perlich, C. y Stitelman, O. (2012). Leakage in Data Mining: Formulation, Detection, and Avoidance. ACM Transactions on Knowledge Discovery from Data, 6(4), 1-21. DOI

Lewis, P., Perez, E., Piktus, A., Petroni, F., Karpukhin, V., Goyal, N., Küttler, H., Lewis, M., Yih, W., Rocktäschel, T., Riedel, S. y Kiela, D. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS 2020. Paper

scikit-learn. (2026). GroupKFold

scikit-learn. (2026). StratifiedGroupKFold

scikit-learn. (2026). TimeSeriesSplit

scikit-learn. (2026). train_test_split

Notas

  1. scikit-learn. (2026). train_test_split. Documentación oficial. Consultado el 6 de junio de 2026.

  2. scikit-learn. (2026). GroupKFold. Documentación oficial. Consultado el 6 de junio de 2026.

  3. scikit-learn. (2026). StratifiedGroupKFold. Documentación oficial. Consultado el 6 de junio de 2026.

  4. scikit-learn. (2026). TimeSeriesSplit. Documentación oficial. Consultado el 6 de junio de 2026.

  5. Kaufman, S., Rosset, S., Perlich, C. y Stitelman, O. (2012). Leakage in Data Mining: Formulation, Detection, and Avoidance. ACM Transactions on Knowledge Discovery from Data, 6(4), 1-21. DOI.

  6. Kapoor, S. y Narayanan, A. (2023). Leakage and the Reproducibility Crisis in Machine-Learning-Based Science. Patterns, 4(9), 100804. DOI.

  7. Lewis, P. et al. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS 2020. Paper.

Capítulo 04

Facsímil 8 · La ciencia de los datos

Capítulo 04: Features y representaciones: de tablas a embeddings

Qué deberías poder hacer al terminar

En el capítulo anterior congelamos una partición honesta. Ahora toca una pregunta igual de importante: ¿qué entra realmente al modelo? Un dataset no se convierte solo en inteligencia por estar en una tabla. Hay que transformar fechas, categorías, texto y metadatos en números que una función pueda operar.

Ese paso se llama representación. A veces es tan sencillo como convertir email en una columna binaria. A veces implica normalizar una fecha. A veces convierte un texto completo en un vector de cientos o miles de dimensiones. En todos los casos hay una decisión de ingeniería: qué información permitimos, qué información prohibimos, cuándo se ajusta la transformación y qué versión queda registrada.

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Distinguir dato crudo, feature y representación.No llamas “dato” a cualquier columna sin mirar cómo se transforma.
Diseñar un contrato de features.Declaras columnas permitidas, prohibidas, tipos y fit_scope.
Explicar one-hot, normalización, TF-IDF y embeddings.Puedes escribir sus fórmulas y decir qué aprende cada pieza.
Evitar leakage de representación.Ajustas vocabulario, escalas e IDF solo con train.
Leer una dimensión de embedding como coste y contrato.No tratas d=64, d=768 o d=3072 como decoración.
Evaluar una búsqueda vectorial mínima.Miras top-k, términos fuera de vocabulario, metadata y slices.

La frase central del capítulo:

Una feature no es una columna: es una promesa sobre cómo una columna se convierte en señal.

La escena: el modelo no sabe leer tu tabla

Imagina una tabla con casos de soporte académico. Tiene columnas como created_at, product, channel, student_id, source_id, label y text. Una persona puede leerla y entender bastante: esto va de becas, aquello de matrícula, esto llegó por email, aquello por portal.

El modelo, en cambio, no ve “becas” como idea ni “email” como canal humano. Ve números. Si le das texto, alguien debe tokenizarlo o vectorizarlo. Si le das fechas, alguien debe convertirlas en una escala útil. Si le das categorías, alguien debe decidir si se codifican como one-hot, índices, embeddings aprendidos o metadata para filtrar.

Aquí aparece una parte muy de ingeniería de datos e IA: no basta con tener datos. Hay que construir una representación coherente, reproducible y alineada con el uso real. Si esa representación se construye mal, el modelo puede aprender una señal falsa, olvidar una señal importante o medir con información que no debería haber visto.

Qué no es una feature

Una feature no es cualquier columna que tengamos a mano. student_id existe en la tabla, pero quizá no debería entrar al modelo. Si entra, el sistema podría aprender estilos de estudiantes concretos en vez de patrones generales. source_id existe, pero puede actuar como atajo si cada documento está demasiado asociado a una etiqueta. label existe, pero usarla como entrada sería convertir la respuesta en pista.

Tampoco es una transformación hecha “porque mejora la métrica”. Si una feature mejora mucho el resultado, hay que preguntar por qué. Puede ser una señal legítima, como la antigüedad de un caso. Puede ser una fuga, como una fecha de resolución disponible solo después de cerrar el ticket. Puede ser una variable de identidad, como un código interno que en train coincide con la etiqueta pero en producción cambia.

Y un embedding no es conocimiento puro. Es una representación numérica aprendida o calculada. Puede capturar parecido semántico, pero no garantiza verdad, actualidad, permisos ni relación exacta. Si un vector store devuelve un fragmento cercano, todavía necesitamos comprobar si ese fragmento contiene evidencia suficiente para la pregunta.

Qué sí es una representación

Una representación es la forma en que describimos un objeto para que un algoritmo pueda trabajar con él. En aprendizaje estadístico, el punto de partida suele ser una matriz XX, donde cada fila representa un ejemplo y cada columna representa una feature.1 La etiqueta o valor que queremos predecir suele separarse como yy.

XRn×dX \in \mathbb{R}^{n \times d}
SímboloSignificadoEjemplo
XXMatriz de features.24 casos por 49 features.
nnNúmero de ejemplos.24 filas.
ddNúmero de features.49 columnas generadas por el kit.
xi,jx_{i,j}Valor de la feature jj para el ejemplo ii.product__becas = 1.

En un proyecto de IA moderna, XX puede mezclar varias familias de señal:

FamiliaEjemploQué aporta
NuméricaDías desde la primera fecha de train.Orden temporal, recencia, duración.
CategóricaProducto, canal, país, tipo de usuario.Segmentos y contexto operativo.
Texto dispersoTF-IDF, bolsa de palabras, BM25.Coincidencia lexical y términos técnicos.
Texto densoEmbeddings de frases o documentos.Parecido semántico y paráfrasis.
Metadatacase_id, permisos, versión de documento.Trazabilidad, filtros y auditoría.

La clave es no mezclar funciones. Metadata puede ser imprescindible para auditar o filtrar, pero no necesariamente debe ser feature del modelo. El contrato decide esa frontera.

Cómo se construye una feature por dentro

Construir una representación es una cadena de decisiones. Primero elegimos columnas permitidas. Después definimos transformaciones. Luego ajustamos lo que tenga que aprenderse usando solo train. Finalmente transformamos train, validation y test con los parámetros ya congelados.

Una feature numérica puede normalizarse así:

x~=xxmintrainxmaxtrainxmintrain\tilde{x} = \frac{x - x_{min}^{train}} {x_{max}^{train} - x_{min}^{train}}
SímboloSignificadoEjemplo
xxValor original.Día 10 desde el inicio.
xmintrainx_{min}^{train}Mínimo observado en train.Día 0.
xmaxtrainx_{max}^{train}Máximo observado en train.Día 15.
x~\tilde{x}Valor normalizado.10/15=0.6710/15 = 0.67.

La parte importante está en los superíndices: mínimo y máximo salen de train. Si usas todo el dataset, test participa en la escala. Puede parecer poco, pero en pipelines grandes esa pequeña comodidad se acumula con imputación, selección de variables, vocabularios e índices.

Una categoría puede codificarse con one-hot:

onehot(c)k={1si c=k 0si ckonehot(c)_k = \begin{cases} 1 & \text{si } c = k \ 0 & \text{si } c \ne k \end{cases}
SímboloSignificadoEjemplo
ccCategoría de la fila.becas.
kkCategoría concreta del vocabulario.matricula.
onehot(c)konehot(c)_kColumna binaria para kk.0 si el producto es becas.

Si en train vemos becas, horarios, matricula, pagos, practicas y titulos, esas son las columnas que crea el contrato. Si mañana aparece doctorado, el sistema no debería improvisar silenciosamente una columna nueva en producción. Debe registrarlo como categoría desconocida, decidir cómo tratarla y actualizar el contrato si procede.

Para texto lexical, TF-IDF pondera términos usando frecuencia local y rareza global. Una forma habitual es:

tfidf(t,d)=tf(t,d)(log1+N1+df(t)+1)tfidf(t,d) = tf(t,d) \cdot \left( \log \frac{1 + N}{1 + df(t)} + 1 \right)
SímboloSignificadoEjemplo
ttTérmino.beca.
ddDocumento o texto de una fila.“requisitos de beca”.
tf(t,d)tf(t,d)Veces que aparece tt en dd.1.
NNNúmero de textos de train.15.
df(t)df(t)Número de textos de train que contienen tt.2.
tfidf(t,d)tfidf(t,d)Peso final del término.Mayor si el término es informativo.

BM25, una familia clásica de ranking lexical, parte de una intuición parecida pero ajusta saturación de frecuencia y longitud del documento.2 En RAG híbrido, estas señales lexicales siguen siendo muy útiles: los embeddings toleran paráfrasis; lo lexical rescata términos exactos, códigos, siglas y nombres propios.

Embeddings: vectores densos con contrato

Un embedding es un vector denso:

e=fθ(objeto)Rme = f_{\theta}(objeto) \in \mathbb{R}^{m}
SímboloSignificadoEjemplo
objetoobjetoLo que queremos representar.Texto de un caso, imagen, usuario, producto.
fθf_{\theta}Encoder o función de representación.Modelo de embeddings o encoder local.
θ\thetaParámetros del encoder.Pesos entrenados o reglas congeladas.
mmDimensión del vector.64 en el kit; 768 en muchos modelos BERT.
eeVector resultante.[0.0, -0.12, ...].

La historia moderna de embeddings no empieza con los LLM actuales. Bengio y colaboradores ya propusieron representar palabras mediante vectores aprendidos dentro de modelos de lenguaje neuronales.3 Word2Vec popularizó embeddings preentrenados eficientes para palabras.4 BERT llevó la idea a representaciones contextuales: el vector de una palabra depende de la frase completa.5 Sentence-BERT adaptó arquitecturas BERT para producir embeddings de frases útiles en similitud semántica.6

La similitud coseno compara direcciones:

cos(a,b)=abab\cos(a,b) = \frac{a \cdot b} {\|a\| \|b\|}
SímboloSignificadoEjemplo
a,ba,bDos vectores.Query y caso indexado.
aba \cdot bProducto escalar.Suma de productos dimensión a dimensión.
a\|a\|Norma de aa.Longitud del vector.
cos(a,b)\cos(a,b)Similitud por dirección.1 si apuntan igual; 0 si son ortogonales.

Dimensión no significa “inteligencia”. Significa longitud del vector y, por tanto, memoria, coste de cálculo, coste de índice y capacidad de representar matices. Un embedding de 64 dimensiones cabe barato y sirve como baseline local. Uno de 768 o más puede capturar mucha más estructura, pero cuesta más guardar, comparar y servir.

La anatomía de una representación publicable

Anatomía de un pipeline de features y embeddings Diagrama en blanco y negro que conecta datos crudos, contrato, fit con train, matrices, embeddings y búsqueda vectorial. De datos crudos a representación usable Una feature publicable tiene contrato, fit scope, dimensión, metadata y evaluación. Datos crudos created_at product channel text label no todo lo que existe puede ser entrada Contrato de features permitidas prohibidas fit_scope = train versiona la frontera Transformaciones normalización one-hot TF-IDF encoder denso Fit solo con train vocabulario categorías IDF mínimos y máximos validation/test solo se transforman Matriz de features 49 columnas tabular + texto sirve para ML clásico Embedding denso 64 dimensiones normalización L2 sirve para similitud Manifest hash dataset hash split dimensión vocabulario sin esto no hay trazabilidad Búsqueda query vector coseno top-k out-of-vocab Decisión pass review block no todo top-k es suficiente La representación es parte del sistema: se versiona, se evalúa y se puede explicar. IA para gente curiosa / Facsímil 08 / Capítulo 04 / 686f6c61
Una representación publicable conecta contrato, transformación, fit con train, manifiesto y evaluación.

Esto en un proyecto real

En un equipo profesional, las features no deberían vivir escondidas dentro de un notebook. Deben tener nombre, definición, propietario, tipo, fuente, ventana temporal, reglas de null, método de cálculo, versión y criterio de retirada. Cuando la misma feature se usa para entrenamiento offline y predicción online, además aparece un problema clásico: que el cálculo de entrenamiento y el cálculo de producción no coincidan.

Ahí entra la idea de feature store: un sistema o una disciplina para compartir definiciones de features, materializarlas, servirlas y versionarlas. Feast, por ejemplo, documenta esta filosofía de definir entidades, feature views y fuentes para servir features de manera consistente.7 Lo importante para este libro no es casarnos con una herramienta concreta, sino entender la responsabilidad: si una feature decide, esa feature debe poder explicarse.

En RAG ocurre algo parecido. El embedding de un chunk no es una columna tradicional, pero es un dato derivado. Debe conservar document_id, versión del documento, versión del chunking, encoder, dimensión, fecha de creación y permisos. Si cambias cualquiera de esas piezas, el índice ya no es el mismo aunque el texto visible parezca igual.

Por qué debería importarte

Una mala representación puede arruinar un sistema sin que el error sea evidente. El modelo compila, la API responde y la métrica puede subir, pero quizá aprendió una identidad, una fecha posterior, una categoría mal codificada o un embedding sin metadata. La representación es el lugar donde se decide qué puede aprender el sistema.

También es una cuestión de coste. Si tienes 10 millones de documentos y pasas de 384 a 3072 dimensiones, multiplicas almacenamiento y cálculo. Si además replicas el índice, guardas metadata y añades estructuras de vecinos aproximados, el coste ya no es marginal. FAISS y HNSW existen porque buscar vecinos en espacios vectoriales grandes requiere estructuras especializadas.89

Manos a la obra

El kit del capítulo está en:

kit/

Construye dos artefactos: una matriz de features y una búsqueda vectorial mínima. Todo se hace sin dependencias externas para que puedas leer el mecanismo completo.

Estructura

kit/
  README.md
  data/feature_cases.csv
  data/search_queries.csv
  data/split_assignments.csv
  contracts/feature_contract.json
  ops/build_feature_vectors.py
  ops/search_feature_vectors.py
  output/feature_manifest.json
  output/feature_matrix.csv
  output/dense_embedding_matrix.csv
  output/feature_quality_report.json
  output/feature_decision.md
  output/search_results.csv
  output/search_report.json
  output/search_decision.md

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/build_feature_vectors.py --write
cat output/feature_decision.md
python3 ops/search_feature_vectors.py --write
cat output/search_decision.md

Qué deberías ver

El primer script debería dejar el gate en pass:

Genera 49 features tabulares/textuales y embeddings densos locales de 64 dimensiones.

La matriz feature_matrix.csv incluye columnas como product__becas, channel__email y tfidf__matricula. El archivo dense_embedding_matrix.csv incluye embedding_00 hasta embedding_63. El manifiesto guarda hashes, vocabularios, dimensión y fit_scope.

El segundo script debería quedar en review, no porque el sistema esté roto, sino porque algunas consultas tienen términos fuera del vocabulario de train:

q002 -> justificante, pendiente
q004 -> bloqueada

Eso es una lección real: si el vocabulario se ajusta solo con train, validation y test pueden contener palabras nuevas. Un buen pipeline no las esconde; las reporta. Después puedes decidir si necesitas más datos, un encoder neural, búsqueda híbrida, expansión de consultas o revisión del split.

Cómo lo adaptas a tu caso

Si tu proyecto tiene...Qué cambias
Nuevas columnas tabularesAñádelas a allowed_input_columns y define transformación.
IDs o columnas sensiblesMételas en forbidden_input_columns.
Más textoSube max_terms o cambia el encoder.
Embeddings realesSustituye deterministic_hash_projection, pero conserva dimensión y versión.
Índice de producciónAñade metadata, permisos, fecha de indexado y versión de corpus.
Evaluación RAGCalcula recall@k, cobertura por producto, latencia y out-of-vocabulary.

Qué entregaría un alumno

  1. feature_manifest.json generado.
  2. feature_quality_report.json explicado.
  3. search_report.json con una lectura de cada consulta.
  4. Tres consultas nuevas y su resultado top-k.
  5. Una propuesta para sustituir el encoder local por embeddings reales sin perder trazabilidad.

Cómo encaja todo

Este mapa debe leerse como una brújula, no como un inventario de técnicas. Los capítulos anteriores del facsímil nos dieron linaje, calidad y splits; los facsímiles previos nos dieron tokens, embeddings, RAG y vector stores. Este capítulo hace de puente: decide qué puede ver el sistema y cómo queda esa decisión convertida en matriz, vector, manifiesto y búsqueda.

La continuidad posterior también es importante. Una representación no termina cuando se genera feature_matrix.csv: se evalúa por slices, se monitoriza cuando cambia la producción, se mide como recuperación si entra en RAG y se gobierna si toca permisos, identidad o decisiones sensibles.

graph TD
    subgraph "Este capítulo"
        Q["Qué puede ver<br/>el sistema"]
        BOUND["Señal útil<br/>vs atajo"]
        CONTRACT["Contrato<br/>de representación"]
        FIT["Fit solo<br/>con train"]
        REP["Matriz y vector"]
        MANIFEST["Feature manifest"]
        DEC["Decisión de uso"]
    end
    subgraph "Mismo facsímil"
        C01["Linaje<br/>cap. 1"]
        C02["Calidad<br/>cap. 2"]
        C03["Split honesto<br/>cap. 3"]
        C05["Slices<br/>cap. 5"]
        C06["DataOps<br/>cap. 6"]
    end
    subgraph "Otros facsímiles"
        TOK["Tokens y embeddings<br/>fasc. 1"]
        RAG["RAG y vector stores<br/>fasc. 4"]
        EVAL["Evaluar retrieval<br/>fasc. 7"]
        GOV["Gobernanza<br/>fasc. 9"]
    end

    C01 -->|"aporta procedencia"| CONTRACT
    C02 -->|"exige datos sanos"| CONTRACT
    C03 -->|"limita el ajuste"| FIT
    TOK -->|"da intuición"| REP
    RAG -->|"usa índice"| REP

    Q -->|"define"| BOUND
    BOUND -->|"se formaliza en"| CONTRACT
    CONTRACT -->|"ordena"| FIT
    FIT -->|"produce"| REP
    REP -->|"se registra en"| MANIFEST
    MANIFEST -->|"sostiene"| DEC

    DEC -->|"se mide por"| C05
    MANIFEST -->|"se compara en"| C06
    REP -->|"se evalúa en"| EVAL
    CONTRACT -->|"declara límites"| GOV

    style Q fill:#F5F5F5,stroke:#000000,stroke-width:2
    style BOUND fill:#F5F5F5,stroke:#000000,stroke-width:2
    style CONTRACT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style FIT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style REP fill:#F5F5F5,stroke:#000000,stroke-width:2
    style MANIFEST fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DEC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C01 stroke-dasharray: 5 5
    style C02 stroke-dasharray: 5 5
    style C03 stroke-dasharray: 5 5
    style C05 stroke-dasharray: 5 5
    style C06 stroke-dasharray: 5 5
    style TOK stroke-dasharray: 5 5
    style RAG stroke-dasharray: 5 5
    style EVAL stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
FeatureVariable de entrada que un modelo puede usar.
RepresentaciónForma numérica de describir un objeto.
One-hotCodificación binaria de categorías.
NormalizaciónCambio de escala para comparar valores.
TF-IDFPeso lexical basado en frecuencia local y rareza global.
EmbeddingVector denso que permite comparar objetos por similitud.
DimensiónLongitud del vector o número de coordenadas.
Similitud cosenoComparación de dirección entre dos vectores.
Out-of-vocabularyTérmino que no estaba en el vocabulario ajustado.
Feature manifestArtefacto que versiona columnas, vocabulario, hashes y dimensiones.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Usar todas las columnasParece que más información siempre ayuda.Separar entradas, target, IDs y metadata.
Ajustar vocabulario con todo el datasetEs más cómodo hacerlo antes del split.Crear split primero y hacer fit solo con train.
Llamar conocimiento a un embeddingEl vector parece semántico.Conservar evidencia, metadata, permisos y evaluación.
Ignorar dimensión y costeEl modelo de embeddings se ve como una caja externa.Calcular almacenamiento, latencia e índice.
Mirar solo el top-1El primer vecino puede ser casual.Evaluar top-k, slices y términos fuera de vocabulario.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Por qué una feature no es simplemente una columna?
  2. ¿Qué diferencia hay entre feature, metadata y target?
  3. ¿Por qué one-hot necesita vocabulario ajustado en train?
  4. ¿Qué aprende TF-IDF y por qué puede contaminar si se ajusta con todo el dataset?
  5. ¿Qué significa que un embedding viva en Rm\mathbb{R}^{m}?
  6. ¿Qué mide la similitud coseno?
  7. ¿Por qué la dimensión afecta coste y ranking?
  8. ¿Qué guarda feature_manifest.json?
  9. ¿Por qué search_report.json queda en review?
  10. ¿Qué cambiarías para usar embeddings reales sin perder trazabilidad?

En resumen

IdeaQué te llevas
La representación es parte del sistema.No se improvisa dentro de un notebook.
El fit pertenece a train.Escalas, vocabularios e IDF se congelan antes de validation y test.
Embedding no significa verdad.Es una geometría útil que necesita metadata y evaluación.
La dimensión tiene coste.Afecta memoria, latencia, índice y calidad de ranking.
Una práctica real deja artefactos.Contrato, matriz, manifiesto, reporte y decisión.

Para saber más

Bengio, Y., Ducharme, R., Vincent, P. y Janvin, C. (2003). A Neural Probabilistic Language Model. Journal of Machine Learning Research, 3, 1137-1155. Paper

Devlin, J., Chang, M.-W., Lee, K. y Toutanova, K. (2019). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL-HLT 2019, 4171-4186. DOI

Feast. (2026). Feast Documentation. Documentación

Hastie, T., Tibshirani, R. y Friedman, J. (2009). The Elements of Statistical Learning (2.ª ed.). Springer. Libro

Johnson, J., Douze, M. y Jégou, H. (2019). Billion-Scale Similarity Search with GPUs. IEEE Transactions on Big Data, 7(3), 535-547. DOI

Malkov, Y. A. y Yashunin, D. A. (2020). Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs. IEEE Transactions on Pattern Analysis and Machine Intelligence, 42(4), 824-836. DOI

Mikolov, T., Chen, K., Corrado, G. y Dean, J. (2013). Efficient Estimation of Word Representations in Vector Space. arXiv

Reimers, N. y Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. EMNLP-IJCNLP 2019, 3982-3992. DOI

Robertson, S. y Zaragoza, H. (2009). The Probabilistic Relevance Framework: BM25 and Beyond. Foundations and Trends in Information Retrieval, 3(4), 333-389. DOI

Notas

  1. Hastie, T., Tibshirani, R. y Friedman, J. (2009). The Elements of Statistical Learning (2.ª ed.). Springer. Libro.

  2. Robertson, S. y Zaragoza, H. (2009). The Probabilistic Relevance Framework: BM25 and Beyond. Foundations and Trends in Information Retrieval, 3(4), 333-389. DOI.

  3. Bengio, Y., Ducharme, R., Vincent, P. y Janvin, C. (2003). A Neural Probabilistic Language Model. Journal of Machine Learning Research, 3, 1137-1155. Paper.

  4. Mikolov, T., Chen, K., Corrado, G. y Dean, J. (2013). Efficient Estimation of Word Representations in Vector Space. arXiv.

  5. Devlin, J., Chang, M.-W., Lee, K. y Toutanova, K. (2019). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL-HLT 2019, 4171-4186. DOI.

  6. Reimers, N. y Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. EMNLP-IJCNLP 2019, 3982-3992. DOI.

  7. Feast. (2026). Feast Documentation. Documentación. Consultado el 6 de junio de 2026.

  8. Johnson, J., Douze, M. y Jégou, H. (2019). Billion-Scale Similarity Search with GPUs. IEEE Transactions on Big Data, 7(3), 535-547. DOI.

  9. Malkov, Y. A. y Yashunin, D. A. (2020). Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs. IEEE Transactions on Pattern Analysis and Machine Intelligence, 42(4), 824-836. DOI.

Capítulo 05

Facsímil 8 · La ciencia de los datos

Capítulo 05: Slices, sesgos y decisión algorítmica

Qué deberías poder hacer al terminar

En el capítulo anterior convertimos datos en representaciones. Ahora viene una pregunta menos cómoda: ¿esa representación se comporta igual de bien en todas las partes importantes del problema?

La respuesta casi nunca sale mirando solo la media global. Una accuracy de 0,86, un recall de 0,78 o un coste medio aceptable pueden esconder que el sistema falla en un producto, un canal, un idioma, una fuente de datos, una necesidad de accesibilidad o una combinación pequeña pero importante. A esa partición útil del comportamiento la llamamos slice.

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Definir slices útiles.No partes por columnas al azar: eliges segmentos conectados con la decisión.
Separar atributo de auditoría y feature.Entiendes que un campo puede servir para medir aunque no deba entrar al modelo.
Calcular métricas por slice.Obtienes recall, tasa de revisión, falsos positivos, coste y captura segura por grupo.
Leer disparidades sin convertirlas en eslogan.Sabes qué métrica se compara, qué tamaño de muestra la sostiene y qué acción permite.
Entender criterios clásicos de equidad algorítmica.Distingues paridad demográfica, igualdad de oportunidad, odds igualadas y calibración por grupo.
Convertir una auditoría en decisión.Produces un reporte, un CSV de slices, una ficha y una decisión operativa.

La frase central del capítulo:

Un sistema no se publica porque la media global suene bien; se publica cuando sabes dónde funciona, dónde no y qué harás con esa diferencia.

La escena: la media global llega demasiado tarde

Imagina un sistema que ayuda a priorizar casos académicos. Cada caso recibe un score. Si el score es alto, se prioriza. Si es bajo, sigue el flujo normal. Si cae en medio, se manda a revisión.

La métrica global parece razonable. El sistema acierta muchos casos, revisa una parte manejable y mantiene buena latencia. En una reunión rápida alguien podría decir: “vamos adelante”.

Pero al partir los resultados por slices aparece otra lectura. Los casos con necesidad de adaptación tienen más casos prioritarios enviados al flujo normal. En inglés se revisa mucho más. En un producto concreto, los casos importantes no quedan capturados. La media global no mentía; simplemente comprimía demasiado.

Este capítulo enseña a no dejar que eso pase.

Qué no es auditar por slices

Auditar por slices no es hacer una tabla enorme con todas las columnas del CSV. Si cada valor distinto se convierte en una fila de auditoría, obtienes ruido. Un slice debe existir porque representa una hipótesis: “este canal cambia la forma de escribir”, “este producto tiene más ambigüedad”, “este idioma tiene menos ejemplos”, “este grupo necesita que no confundamos silencio con baja prioridad”.

Tampoco es declarar que una diferencia numérica demuestra una injusticia completa. Una disparidad es una señal medible, no una sentencia universal. Puede venir de datos escasos, etiquetas inconsistentes, política de negocio, diseño del umbral, cobertura desigual, drift o un error real del modelo. La ingeniería consiste en separar esas causas antes de automatizar más.

Y no es lo mismo usar un atributo para decidir que usarlo para auditar. En muchos sistemas, ciertos campos no deben entrar como feature. Aun así, puede ser imprescindible medir resultados agregados por esos campos para detectar si el sistema está fallando justo donde más importa. El contrato debe decirlo: campo no usado por el modelo, campo permitido para auditoría agregada.

Qué sí es un slice

Un slice es un subconjunto definido por una condición. Si DD es el conjunto evaluado y AA es un atributo de auditoría, el slice asociado al valor aa es:

Da={(xi,yi,s^i)D:Ai=a}D_a = \{(x_i, y_i, \hat{s}_i) \in D : A_i = a\}
SímboloSignificadoEjemplo
DDDataset de evaluación.36 casos de test del kit.
AAAtributo usado para auditar.language.
aaValor concreto del atributo.en.
DaD_aSlice formado por casos con ese valor.Casos de test en inglés.
xix_iEntrada o representación del caso.Texto, producto, canal, metadata.
yiy_iEtiqueta real.true_priority = 1.
s^i\hat{s}_iScore producido por el sistema.0.84.

La parte importante es que el slice conserva la unidad de decisión. No evaluamos “idioma” en abstracto. Evaluamos decisiones sobre casos dentro de un idioma, producto, canal o combinación de condiciones.

Ejemplo de fórmula: en el kit del capítulo, una política de triaje convierte score en decisión. Los números son umbrales didácticos congelados para la práctica; en un proyecto real se fijarían con validación, capacidad humana y coste operativo antes de mirar test.

d(s^)={Ps^0.78 Ns^<0.38 Rotro casod(\hat{s}) = \begin{cases} P & \hat{s} \ge 0.78 \ N & \hat{s} < 0.38 \ R & \text{otro caso} \end{cases}
SímboloSignificadoEjemplo
s^\hat{s}Score producido por el sistema.0,36.
PPPriorizar.Caso claro de alta prioridad.
NNFlujo normal.Caso claro de baja prioridad.
RRRevisar.Caso intermedio.
0,78Umbral alto congelado antes de mirar test.Priorizar casos claros.
0,38Umbral bajo congelado antes de mirar test.Enviar al flujo normal casos claros.

Esta política no se ajusta en test. Test sirve para medir. Si tocamos umbrales mirando el slice que falla, ya no estamos auditando: estamos usando la evaluación como desarrollo. Eso lo vimos en el capítulo 03 del facsímil 08.

Métricas por slice: lo mínimo que un ingeniero debería mirar

Para cada slice conviene calcular una matriz de confusión. En una decisión binaria clásica, tendríamos TP, FP, FN y TN. En una política con revisión, añadimos una tercera salida: revisar. Eso cambia la lectura.

Si un caso prioritario se manda a normal, tenemos un fallo operativo fuerte. Si se manda a revisar, no se ha automatizado bien, pero tampoco se ha dejado pasar sin mirar. Por eso el kit distingue tres métricas:

MétricaFórmulaLectura
Auto-recallTP/PTP / PDe los casos prioritarios, cuántos se priorizan automáticamente.
Miss rateFN/PFN / PDe los casos prioritarios, cuántos se envían a flujo normal.
Captura segura(TP+reviewP)/P(TP + review_P) / PDe los prioritarios, cuántos quedan priorizados o revisados.

Donde:

SímboloSignificadoEjemplo
PPNúmero de casos positivos reales en el slice.6 casos prioritarios.
TPTPPositivos reales priorizados.2 casos.
FNFNPositivos reales enviados a flujo normal.4 casos.
reviewPreview_PPositivos reales mandados a revisión.1 caso.

La diferencia entre auto-recall y captura segura es muy útil. Si auto-recall es bajo pero captura segura es alta, quizá el sistema no automatiza mucho, pero protege la decisión con revisión. Si captura segura es baja, el problema es más serio: casos importantes están pasando al flujo normal.

Ejemplo de fórmula: para no olvidar el coste, el kit usa esta función lineal. Es una plantilla pedagógica: cada equipo debería cambiar pesos y unidades según impacto real, tiempo de revisión, riesgo y capacidad.

C=cFNFN+cFPFP+cRRC = c_{FN} \cdot FN + c_{FP} \cdot FP + c_R \cdot R
SímboloSignificadoEjemplo del kit
CCCoste operativo total del slice.19,6.
cFNc_{FN}Coste de enviar un prioritario a flujo normal.8,0.
cFPc_{FP}Coste de priorizar un no prioritario.3,0.
cRc_RCoste de revisión.1,2.
RRNúmero de casos revisados.3.

Un coste no tiene que ser euros. Puede ser minutos de equipo, riesgo operativo, saturación de soporte o coste de oportunidad. Lo importante es hacerlo explícito antes de elegir política.

Criterios clásicos: nombres útiles, no dogmas

La literatura de equidad algorítmica distingue varios criterios. Conviene conocerlos porque aparecen en papers, herramientas y auditorías, pero no deben usarse como recetas automáticas.

La paridad demográfica compara tasas de selección entre grupos. En nuestro caso sería comparar qué proporción de casos se prioriza en cada slice:

P(Y^=1A=a)P(\hat{Y}=1 \mid A=a)

Sirve para detectar diferencias de tasa de salida. No sabe si los casos positivos reales estaban distribuidos igual. Si un producto recibe más casos realmente prioritarios que otro, exigir la misma tasa de priorización puede ser una mala idea.

La igualdad de oportunidad compara la tasa de verdaderos positivos entre grupos, es decir, si los casos positivos reales reciben la salida positiva con tasas parecidas.1 En el kit se parece al auto-recall por slice:

P(Y^=1Y=1,A=a)P(\hat{Y}=1 \mid Y=1, A=a)

Las odds igualadas comparan tanto verdaderos positivos como falsos positivos entre grupos. Pide que el sistema tenga comportamiento parecido para positivos reales y negativos reales. Es más exigente que mirar solo recall.

La calibración por grupo pregunta si un score significa lo mismo en cada grupo. Si los casos con score 0,8 aciertan el 80 % en un slice y el 55 % en otro, no basta con decir que el score ordena bien globalmente. Esto conecta con calibración e incertidumbre en el facsímil 07.

Hay un punto clave: algunos criterios no se pueden satisfacer todos a la vez salvo en condiciones especiales. Chouldechova y Kleinberg, Mullainathan y Raghavan mostraron incompatibilidades entre nociones de equidad cuando las tasas base difieren entre grupos.23 Traducido a ingeniería: elegir una métrica de equidad es elegir qué error quieres controlar y qué compromiso aceptas.

Sesgo no siempre significa lo mismo

La palabra sesgo se usa demasiado rápido. Para ingeniería, decir “el modelo tiene sesgo” sin precisar de qué tipo es casi no ayuda. Necesitamos localizar dónde entra, cómo se manifiesta, qué métrica lo hace visible y qué acción permite.

En este capítulo no usamos sesgo como insulto técnico. Lo usamos como una diferencia sistemática que puede afectar a una decisión. Puede estar en los datos, en el objetivo, en la representación, en el modelo, en el umbral, en la interfaz o en la forma de medir. Si no separas esas capas, acabas arreglando el sitio equivocado.

Fuente de sesgoQué ocurreCómo se detectaQué suele hacerse
CoberturaUn slice tiene pocos ejemplos o no aparece en train.Conteos, intervalos, unknowns, categorías raras.Recoger más datos, limitar automatización, declarar cobertura.
SelecciónLos datos observados no representan el uso real.Comparar distribución de train, test y producción.Rehacer split, muestreo, ponderación o contrato de uso.
MediciónUn campo no mide lo mismo en todos los grupos.Revisar definición, instrumento de captura y linaje.Cambiar proxy, añadir variable mejor, documentar límite.
ProxyUna variable cómoda sustituye mal al concepto real.Correlación con slices, errores concentrados, revisión de dominio.Sustituir proxy o cambiar objetivo.
EtiquetadoLas etiquetas se aplican con criterios distintos.Acuerdo entre anotadores, desacuerdo por slice, revisión de casos frontera.Reescribir política de anotación y reetiquetar muestra.
RepresentaciónLas features o embeddings capturan peor un segmento.OOV, vecinos pobres, recall por slice, sensibilidad a idioma o formato.Cambiar encoder, vocabulario, normalización o datos de entrenamiento.
AgregaciónUn único modelo o umbral mezcla subpoblaciones con comportamientos distintos.Buen promedio global con slices débiles.Umbrales por contexto, rutas de revisión o modelos especializados con control.
EvaluaciónEl test no contiene el problema que aparecerá en producción.Falta de slices críticos, test pequeño, ausencia de intersecciones.Nueva eval, holdout, monitorización por slice.
InteracciónLa interfaz cambia lo que el usuario escribe o aporta.Diferencias por canal, longitud, idioma, plantilla o formulario.Rediseñar entrada, instrucciones y validaciones.
PolíticaEl mismo score produce consecuencias distintas según contexto.Coste, revisión, capacidad operativa y efectos por segmento.Cambiar umbrales, limitar automatización o exigir revisión.

Un caso clásico de la literatura sanitaria mostró que usar coste sanitario como proxy de necesidad médica podía reducir la identificación de pacientes con necesidades reales en ciertos grupos, porque el gasto histórico no medía necesidad de forma neutral.4 La lección para este libro no es copiar ese dominio; es entender el patrón: un proxy cómodo puede cambiar la decisión que crees estar midiendo.

Por eso el capítulo 01 insistía en linaje y uso permitido, el 02 en calidad, el 03 en splits y el 04 en representación. Los slices son donde esas decisiones anteriores se vuelven visibles.

Qué sabemos por estudios en modelos reales

Los sesgos no aparecen solo en clasificadores tabulares. También se han observado en embeddings, modelos de lenguaje, clasificadores de texto, sistemas de visión y sistemas de decisión basados en proxies. Ver esos estudios ayuda porque cambia la pregunta: ya no es “¿puede pasar?”, sino “¿cómo lo detectaría en mi caso?”.

EstudioTipo de modelo o sistemaQué mostróSeñal detectable
Bolukbasi et al. (2016)Word embeddingsAlgunas analogías en embeddings capturaban asociaciones de género no deseadas.5Direcciones en el espacio vectorial y vecinos semánticos.
Caliskan et al. (2017)Embeddings entrenados con corpusWEAT mostró asociaciones recuperables desde lenguaje ordinario.6Test de asociación entre conjuntos de términos.
Buolamwini y Gebru (2018)Clasificación facial comercialLas tasas de error variaban mucho por intersección de tono de piel y género en sistemas evaluados.7Accuracy por grupos e intersecciones, no solo global.
Dixon et al. (2018)Clasificación de toxicidadCiertos términos de identidad podían disparar predicciones tóxicas aunque el texto no lo fuera.8Falsos positivos asociados a términos concretos.
CrowS-Pairs (2020)Modelos de lenguaje enmascaradosComparó pares de frases para medir preferencias por frases con estereotipo.9Probabilidad relativa entre pares mínimos.
StereoSet (2021)Modelos de lenguaje preentrenadosMidió sesgo estereotípico junto con capacidad de modelado lingüístico.10Relación entre score lingüístico y score de estereotipo.
BBQ (2022)Pregunta-respuestaEvaluó si modelos recurren a estereotipos cuando el contexto es insuficiente o ambiguo.11Respuestas bajo contexto ambiguo frente a contexto informativo.

Hay dos lecciones de ingeniería en esa tabla.

La primera: el sesgo no siempre aparece como “métrica baja”. A veces aparece como asociación geométrica, falso positivo lexical, peor cobertura en intersecciones, sensibilidad al contexto ambiguo o score calibrado de forma distinta por grupo.

La segunda: cada tipo de sistema necesita su prueba. Para embeddings haces vecinos, direcciones, WEAT o pares mínimos. Para clasificación haces matriz por slice. Para RAG miras recuperación por fuente, idioma, fecha y permisos. Para generación miras pares contrafactuales, respuestas con contexto insuficiente, abstención y criterios de evaluación.

Detectabilidad: cómo se ve un sesgo antes de producción

Una auditoría útil no pregunta “¿hay sesgo?” en abstracto. Pregunta “¿qué señal observable esperaría si este sistema falla de forma sistemática?”.

Señal detectableCómo se calculaQué indicaQué no demuestra sola
Slice con poco nnConteo por segmento.Falta evidencia para concluir.Que el sistema sea malo en ese slice.
Diferencia de recallTP/PTP/P por slice.Un grupo de positivos reales se detecta peor.La causa del problema.
Diferencia de falsos positivosFP/NFP/N por slice.Un grupo recibe más salidas positivas indebidas.Que el objetivo esté bien definido.
Captura segura baja(TP+reviewP)/P(TP + review_P)/P.Casos importantes pasan sin priorizar ni revisar.Qué componente lo provocó.
Tasa de revisión disparR/nR/n por slice.Un segmento se automatiza menos o consume más revisión.Que revisar sea necesariamente malo.
Coste por caso disparC/nC/n por slice.El impacto operativo se concentra.Que el coste esté bien ponderado.
OOV altoTérminos fuera del vocabulario por slice.La representación cubre peor un segmento.Que un embedding real no lo arregle.
Vecinos pobresTop-k sin evidencia útil para un slice.Recuperación débil o índice mal cubierto.Que el generador sea el único culpable.
Pares contrafactuales inestablesCambiar solo un atributo y comparar salida.Sensibilidad indeseada a un cambio controlado.Que todos los casos reales fallen igual.
Contexto ambiguo decide demasiadoProbar preguntas con evidencia insuficiente.El modelo rellena huecos con asociaciones aprendidas.Que falle cuando la evidencia es completa.

La palabra “detectable” importa. Si un sesgo no tiene métrica, muestra, caso de prueba o traza, se convierte en debate interminable. El objetivo no es tener todas las respuestas, sino diseñar señales que permitan revisar.

Buenas prácticas para no fabricar un problema nuevo

La buena práctica empieza antes de entrenar. Un equipo serio no espera al final para “pasar fairness”. Diseña la evaluación desde el contrato de datos.

Buena prácticaQué haces en concreto
Definir la unidad de decisiónNo mezclas usuario, caso, documento, chunk y sesión como si fueran lo mismo.
Separar feature y auditoríaUn campo puede no entrar al modelo y aun así medirse de forma agregada.
Escribir slices críticos antes de testEvitas elegir segmentos solo porque cuentan una historia cómoda.
Medir interseccioneslanguage=en puede parecer aceptable y language=en + access_need=si no.
Añadir mínimos de muestraSin nn, positivos y negativos suficientes, el slice va a revisión.
Guardar política y hashesSi cambia el dataset o el contrato, cambia la auditoría.
Congelar umbrales antes de testAjustar con test convierte auditoría en desarrollo.
Mirar coste, no solo métricaUn fallo raro puede importar más que diez aciertos baratos.
Dejar una acción escritapass, review o block con razones y siguiente paso.
Conectar con monitorizaciónLos mismos slices se observan después en producción.

Y hay cosas que conviene evitar:

EvitaPor qué
“No medimos ese atributo, así que no hay problema”No usar un campo como feature no implica que el sistema no tenga diferencias por ese campo.
“La muestra es pequeña, pero la media global pasa”Un slice pequeño no se arregla escondiéndolo dentro del promedio.
“El benchmark público dice que el modelo es bueno”El benchmark quizá no cubre tu dominio, idioma, interfaz o coste.
“Mitigamos borrando una columna”Otros campos pueden actuar como proxies.
“Probamos muchos slices y publicamos solo los interesantes”Eso convierte auditoría en selección de relato.
“Una herramienta lo certifica”La herramienta calcula; el equipo define uso, consecuencia, coste, límites y acción.
“Arreglamos el test tocando el umbral”Si el umbral se elige mirando test, necesitas nueva evaluación.
“Todos los slices deben tener la misma tasa”Algunas tasas base reales pueden diferir; la pregunta es qué error estás controlando.

El kit del capítulo incorpora estas prácticas en pequeño: fields_not_for_model, audit_fields, critical_slices, mínimos de muestra, gates, hashes y decisión Markdown. No es una auditoría completa de un sistema real, pero sí tiene la forma profesional que debe tener una primera revisión.

Anatomía de una auditoría de decisión

Anatomía de una auditoría por slices Diagrama monocromo que muestra datos de evaluación, política de umbrales, decisiones, slices, métricas, disparidades, gates y acciones de ingeniería. Auditar una decisión por slices No ajusta el modelo: mide una política congelada y decide qué automatización es defendible. Evaluación congelada score etiqueta real split de test metadatos hash + contrato Política score >= 0.78 priorizar score < 0.38 normal en medio: revisar Matriz por slice TP · FP FN · TN revisión latencia p95 tamaño importa Gates captura mínima miss rate máximo gap máximo coste por caso pass · review · block Slices producto canal idioma adaptación intersecciones Métricas auto-recall captura segura falsos positivos revisión coste Disparidad máximo - mínimo intervalo Wilson muestra mínima slice crítico lectura causal pendiente Salida técnica slice_audit_report.json slice_metrics.csv Salida humana slice_decision.md slice_audit_card.md Acciones ampliar datos revisar umbrales IA para gente curiosa / Facsímil 08 / Capítulo 05 / 686f6c61
Auditar por slices convierte una métrica global en una decisión revisable: datos, política, segmentos, métricas, gates y acciones.

Herramientas reales y cómo leerlas

Fecha de corte de esta lectura: 7 de junio de 2026. El mercado cambia rápido, así que no conviene memorizar logos. Conviene memorizar qué artefacto produce cada herramienta: métrica por slice, intervalo, explicación, alerta, comparación de versiones, política de mitigación o evidencia para una revisión.

Una herramienta seria no “quita el sesgo” en abstracto. Hace una de estas cosas: mide una diferencia, ayuda a encontrar causa probable, aplica una técnica de mitigación, deja trazabilidad o vigila si producción se aleja de lo que mediste en validación. Si no produce un artefacto revisable, es una demo bonita, no una práctica de ingeniería.

Herramientas abiertas para auditar y mitigar

Estas herramientas encajan bien cuando el equipo trabaja con notebooks, pandas, scikit-learn, TensorFlow o reportes reproducibles en CI. Son especialmente útiles para enseñar y para construir un primer estándar interno, porque puedes inspeccionar datos, métricas y código.

HerramientaDónde encajaQué permite verQué puede ayudar a mitigarQué no debes delegarle
FairlearnModelos tabulares o pipelines compatibles con scikit-learn.Métricas agrupadas con MetricFrame, comparación entre grupos y visualización de disparidades.12Reducciones como ExponentiatedGradient, búsqueda con restricciones y optimización de umbrales.13La definición de grupos, coste del error y métrica que gobierna la decisión.
AI Fairness 360Comparar algoritmos de fairness, datasets de referencia y métricas clásicas.Métricas, detectores, explicadores y API compatible con scikit-learn para parte del toolkit.14Preprocesamiento, técnicas durante entrenamiento y postprocesamiento.15El encaje con tu contrato de datos real. Muchos ejemplos académicos no se parecen a tu producto.
AequitasAuditoría de scores binarios o continuos con CSV, CLI o interfaz local.Métricas de grupo, disparidades y criterios sobre scores, etiquetas y atributos.16No mitiga por sí sola: ayuda a decidir si el modelo o la política deben cambiar.Convertir una tabla de disparidades en decisión sin revisar el dominio.
Fairness IndicatorsEcosistema TensorFlow, TFMA y evaluación por slices.Visualización de rendimiento por segmentos, intervalos y métricas en pipelines TensorFlow.17No es una varita de mitigación; empuja a localizar slices débiles y a rediseñar datos o entrenamiento.Pensar que solo aplica a “temas sociales”. También sirve para idioma, canal, dispositivo o fuente.
What-If ToolExploración interactiva de ejemplos, umbrales y contrafactuales.Cómo cambian predicciones al mover ejemplos, atributos o umbrales.18Ayuda a descubrir hipótesis antes de automatizar una prueba.Sustituir una evaluación versionada. Explorar no es certificar.
ResponsiblyAprendizaje, prototipos y análisis de fairness en clasificación y NLP.Métricas, visualizaciones y utilidades para enseñar conceptos con código.19Puede acompañar un primer laboratorio o auditoría exploratoria.Producción sin controles propios, versionado y trazabilidad.

Para un curso de ingeniería, Fairlearn y AIF360 son buenas primeras estaciones porque obligan a escribir y_true, y_pred, score, atributo sensible o de auditoría y métrica. Ese gesto parece básico, pero es la mitad del aprendizaje: si no sabes pasar esos arrays con nombres correctos, todavía no sabes qué estás auditando.

Plataformas cloud y de ciclo de vida

Cuando el sistema ya vive en una nube concreta, las herramientas integradas aportan algo que una libreta local no tiene: conexión con jobs, registros de modelo, monitorización, permisos, reportes y gobierno de releases.

PlataformaQué cubreCuándo tiene sentidoCuidado de ingeniería
Amazon SageMaker ClarifySesgo en datos y modelos, explicabilidad, evaluaciones de modelos fundacionales y monitorización integrada con SageMaker.20Si tu entrenamiento, registro o despliegue ya está en SageMaker.Hay que fijar qué features o atributos se analizan, en qué split, con qué baseline y qué acción dispara una alerta.
Azure Responsible AI dashboardPaneles de análisis responsable dentro de Azure ML: errores, importancia de variables, contrafactuales, causalidad y fairness según el tipo de modelo.21Si trabajas con Azure ML y quieres que evaluación, registro y explicación vivan en el mismo flujo.Un panel no sustituye un gate en CI/CD. Debe acabar en una decisión reproducible.
SageMaker Model Monitor, Azure ML monitoring o equivalentesVigilancia de datos, predicciones, latencia y cambios por segmento.Si el riesgo no termina al desplegar.La métrica por slice debe existir antes de producción; no la inventes cuando salta la alerta.

La pregunta correcta para una nube no es “¿tiene dashboard?”. Es: ¿puedo versionar la política, reproducir el reporte, bloquear un release, abrir una incidencia y comparar producción contra validación por los mismos slices? Si no, el panel sirve para mirar, pero no para gobernar.

Observabilidad y herramientas de mercado

En producción aparece otra familia: plataformas de observabilidad de ML y GenAI. No suelen ser la primera herramienta para aprender fairness, pero sí son relevantes cuando tienes tráfico real, múltiples modelos, trazas, embeddings, RAG, usuarios, feedback y alertas.

HerramientaQué suele aportarDónde ayuda con sesgosQué pedir antes de adoptarla
EvidentlyLibrería y plataforma para calidad de datos, drift, evaluación y reportes.22Comparar referencia frente a producción, crear reportes por segmento y vigilar si cambian distribuciones.Exportar reportes, integrarlo en CI y definir tus propios slices, no solo métricas por defecto.
GiskardEvaluación y testing de modelos, agentes y aplicaciones GenAI.23Pruebas de comportamiento en LLMs: toxicidad, estereotipos, robustez de prompts, RAG y regresiones de comportamiento.Datasets de prueba propios y criterios explícitos. Sin casos de tu dominio, solo pruebas una maqueta.
FiddlerObservabilidad, explicabilidad y métricas de fairness en producción.24Monitorizar rendimiento por cohortes, explicar predicciones y detectar degradación por grupos.Acceso a etiquetas o feedback posterior; sin ground truth retrasado, algunas señales serán aproximadas.
ArizeObservabilidad para ML, visión, embeddings y GenAI, con slicing, drift y análisis de rendimiento.25Slices, cohortes, embeddings, drift y degradación de rendimiento en producción.Que los atributos de auditoría lleguen al sistema con permisos y granularidad correcta.
WhyLabsObservabilidad con perfiles de datos, drift, calidad, modelos predictivos y GenAI.26Vigilar cambios de datos, problemas de calidad, drift, outputs de LLM y trazas.Que las alertas estén conectadas con owners, SLOs y acciones, no solo con correos.
Arthur, WhyLabs, Fiddler, Arize u otros proveedores enterpriseGobierno, monitorización, dashboards, explicabilidad y control operativo.27Cuando hay varios equipos, varios modelos y requisitos de trazabilidad.Evita comprar “confianza”. Compra integración, auditoría, permisos, exportación y comparabilidad.

El mercado es útil cuando resuelve un problema de operación: logging, trazas, control de versiones, dashboards compartidos, alertas, permisos, exportaciones y soporte. Pero el mercado no conoce por defecto tu coste de error. Tampoco sabe si un falso positivo molesta, si un falso negativo deja a alguien sin atención o si un slice con poca muestra debe bloquear o pedir más datos.

Mitigar no es borrar una columna

Hay una trampa clásica: detectar una diferencia, borrar el atributo sensible y declarar el problema resuelto. En sistemas reales, los proxies aparecen por código postal, idioma, canal, horario, dispositivo, historial, coste, texto libre o fuente documental. Por eso la mitigación debe elegir dónde está la causa probable.

Capa de mitigaciónQué cambiaEjemplos técnicosCuándo usarlaQué vigilar
DatosLa distribución, cobertura o calidad de las muestras.Recolectar más casos, reetiquetar, balancear, reponderar, mejorar instrucciones de anotación, separar fuentes.Hay slices con poca muestra, etiquetas inconsistentes o proxies claros.No fabricar un dataset artificial que ya no se parezca a producción.
RepresentaciónCómo se codifica el caso.Mejorar features, revisar embeddings, normalizar idioma, añadir metadatos permitidos, cambiar encoder, reducir OOV.El modelo no ve señales suficientes en ciertos grupos o formatos.No meter campos que expliquen demasiado bien una condición sensible sin justificación.
EntrenamientoLa función objetivo o restricciones del modelo.Fairlearn reductions, restricciones de paridad, regularización, pérdidas ponderadas, búsqueda de hiperparámetros con gates.El modelo aprende una frontera útil pero desigual.Medir trade-off: una restricción puede mejorar un slice y empeorar otro.
Umbral y políticaLa conversión de score a acción.Umbral global, banda de revisión, umbrales condicionados con revisión de dominio, abstención, doble lectura humana.El score está razonablemente calibrado, pero la acción automática concentra riesgo.Cambiar umbrales por grupo tiene implicaciones de producto, ética, regulación y soporte. No se improvisa.
ProductoLa experiencia y el circuito humano.Explicación al usuario, apelación, revisión manual, colas por capacidad, feedback posterior, monitorización.La consecuencia de equivocarse es alta o no hay datos suficientes para automatizar.Que la revisión humana no sea un cajón sin dueño, SLA ni trazabilidad.

La mitigación buena suele ser aburrida: cambiar datos, contratos, umbrales, monitorización, revisión y documentación. La mala mitigación suele parecer elegante: un algoritmo nuevo aplicado sin explicar qué consecuencia reduce.

Cómo elegir herramienta según tu stack

Si estás aquíEmpieza porAñade después
Notebook con CSV y modelo sklearnFairlearn o Aequitas para métricas por grupo.AIF360 si necesitas comparar técnicas de mitigación.
Pipeline TensorFlow/TFXFairness Indicators y What-If Tool.Reporte versionado y gate por slice en CI.
SageMakerSageMaker Clarify.Model Monitor, Model Cards y job recurrente por slice.
Azure MLResponsible AI dashboard.Componente de evaluación que exporte métricas a tu release.
Producto con tráfico realEvidently, Fiddler, Arize, WhyLabs o plataforma equivalente.SLO por slice, owner, alerta, runbook y comparación contra validación.
LLM, agente o RAGGiskard, Evidently, Arize Phoenix u otras evals propias.Dataset de pares mínimos, prompts de regresión, trazas y revisión humana en casos críticos.
Auditoría académica o de claseKit propio + Fairlearn/AIF360/Aequitas.Informe reproducible, model card, data card y defensa oral de decisiones.

Para decidir, yo haría esta prueba: toma diez filas reales, un contrato de política y una métrica por slice. Si la herramienta no puede decirte qué fila falló, en qué slice, con qué métrica, contra qué baseline, desde qué versión y qué acción toca, aún no tienes una herramienta de auditoría; tienes una visualización.

Qué evitar al comprar o adoptar una herramienta

  1. Elegir por capturas de pantalla. Hay que pedir exportaciones, API, reproducibilidad y ejemplos con tus datos.
  2. Medir fairness solo en validación y olvidarlo en producción. La distribución cambia y los slices también.
  3. Usar atributos de auditoría sin política de acceso. Medir requiere permiso, minimización y propósito.
  4. Mitigar antes de diagnosticar. No es igual falta de cobertura, proxy, mala etiqueta, mala calibración o umbral mal puesto.
  5. Comparar herramientas sin el mismo dataset, split, métrica y política de decisión.
  6. Aceptar métricas por defecto sin traducirlas a coste. Paridad, recall, falsos positivos y calibración no responden la misma pregunta.
  7. Confundir un panel verde con una decisión publicable. La salida debe ser pass, review o block, con evidencia.

La regla práctica es sencilla: usa herramientas, pero no les delegues el criterio. Una herramienta calcula, visualiza, alerta o ejecuta una técnica. El equipo decide qué métrica representa la consecuencia que quiere controlar, qué slices importan y qué se hace cuando algo no pasa.

Caso completo: de block a review

Un buen capítulo de sesgos no puede quedarse en “usa una herramienta”. Tiene que enseñar una historia completa: una política parece razonable, falla en slices críticos, se propone una mitigación y se vuelve a medir. Eso es lo que hace el kit.

La política base dice:

DecisiónRegla
priorizarscore >= 0.78
normalscore < 0.38
revisar0.38 <= score < 0.78

Con esa política, el resultado global queda en block: captura segura 0.7778, pérdida operativa 0.2222, tasa de revisión 0.3611 y coste por caso 1.4056. El problema no es solo la media. En los slices críticos aparece algo peor:

Slice críticonPositivosAuto-recallPérdidaCaptura seguraRevisiónCoste por caso
language=en940.250.250.750.55561.5556
access_need=si1260.00.66670.33330.53.2667
`product=practicasaccess_need=si`420.01.00.00.5

La lectura humana es directa: algunos casos prioritarios con necesidad de accesibilidad o en inglés están yendo a flujo normal. No basta con decir “la accuracy global es aceptable”. La política está dejando pasar casos que el contrato considera críticos.

La mitigación candidata no cambia el modelo. Cambia la política de decisión: amplía la banda de revisión bajando el umbral de flujo normal de 0.38 a 0.32.

DecisiónPolítica basePolítica candidata
priorizarscore >= 0.78score >= 0.78
normalscore < 0.38score < 0.32
revisar0.38 <= score < 0.780.32 <= score < 0.78

El antes/después queda así:

PolíticaEstadoCaptura seguraPérdida operativaTasa de revisiónCoste por casoFlags blockFlags review
Baseblock0.77780.22220.36111.405657
Banda de revisiónreview1.00.00.52780.716705

Esto no significa “ya está arreglado”. Significa algo más interesante para ingeniería: la candidata elimina los casos prioritarios enviados a flujo normal, pero aumenta la carga de revisión humana. Pasa de block a review, no a pass. Si el equipo no puede revisar aproximadamente el 53 % de los casos, la mitigación mejora una métrica y rompe la operación. Por eso fairness, coste y capacidad deben leerse juntos.

La matemática mínima de la mitigación

En un proyecto serio no se elige mitigación porque “suena mejor”. Ejemplo de fórmula: podemos formularla como una optimización con restricciones. La estructura viene de optimización con restricciones, pero las variables y límites de este ejemplo son una traducción práctica para el caso del capítulo.

minθ,τ L(θ,τ;Dval)sujeto aΔm(S)ϵm,C(τ)B\min_{\theta,\tau}\ \mathcal{L}(\theta,\tau;D_{val}) \quad \text{sujeto a}\quad \Delta_m(S) \leq \epsilon_m,\quad C(\tau) \leq B

Donde:

SímboloQué significa en este capítulo
θ\thetaParámetros del modelo o configuración que produce el score.
τ\tauPolítica de umbrales: cuándo priorizar, revisar o mandar a flujo normal.
L\mathcal{L}Pérdida: error, coste, latencia o combinación definida por el equipo.
DvalD_{val}Validación, no test. Aquí se decide la política antes de medir en test.
SSConjunto de slices auditados.
Δm(S)\Delta_m(S)Disparidad máxima entre slices para una métrica mm.
ϵm\epsilon_mLímite aceptado para esa disparidad.
C(τ)C(\tau)Coste operativo de la política: revisión, falsos positivos, falsos negativos.
BBPresupuesto operativo: capacidad humana, dinero o latencia disponible.

La parte importante es la palabra sujeto a. No queremos solo minimizar error global. Queremos minimizarlo sin romper restricciones de slices, coste y operación. Fairlearn lo expresa con reducciones y restricciones; AIF360 ofrece varias familias de mitigación; nuestro kit lo enseña con algo más humilde pero más transparente: umbrales, gates, slices y coste.

Hay tres familias de respuesta:

FamiliaQué optimizaEjemplo en el kitCuándo sirve
Cambiar datosMejorar cobertura o etiquetas.Recolectar más casos access_need=si.Cuando el slice falla porque casi no hay evidencia fiable.
Cambiar modeloModificar entrenamiento o representación.Reentrenar con features, embeddings o pérdidas mejor controladas.Cuando el score separa mal en ciertos segmentos.
Cambiar políticaModificar umbrales, revisión o automatización.Ampliar banda de revisión de 0.38 a 0.32.Cuando el score es incierto y la consecuencia de mandar a flujo normal es alta.

La mitigación por política suele ser la primera que un equipo puede probar porque no exige reentrenar. También es peligrosa si se usa sin capacidad: cada caso enviado a revisión debe tener owner, SLA, registro y criterio de cierre.

De validación a producción

La auditoría no termina al generar slice_metrics.csv. En producción pueden cambiar los canales, idiomas, productos, prompts, documentos, colas humanas o criterios de etiqueta. Por eso los mismos slices deben convertirse en señales operativas.

Señal en producciónQué mideQué acción debería disparar
review_rate por sliceCarga humana que genera la política.Ajustar capacidad, revisar umbral o limitar automatización.
miss_rate con etiqueta retrasadaCasos importantes que acabaron en flujo normal.Abrir revisión de política y bloquear aumento de automatización.
Drift de distribución por sliceCambio en canales, idiomas, productos o perfiles.Comparar contra validación y revisar datos de entrenamiento.
Latencia p95 por sliceSi ciertos casos tardan más en resolverse.Revisar pipeline, herramientas o colas específicas.
Tasa de apelación o correcciónSi usuarios o revisores corrigen más un segmento.Revisar etiqueta, interfaz, rúbrica o explicación.

Esta es la conexión natural con DataOps: un SLI por slice no es una frase bonita, es una medida que se calcula. Un SLO por slice no es “queremos hacerlo bien”, es un objetivo que decide si se mantiene, se revisa o se detiene una política.

En un proyecto real

En un proyecto de IA aplicada, los slices deben definirse antes de mirar el resultado final. Puedes añadir nuevos slices cuando aparece una señal nueva, pero no deberías probar veinte cortes hasta encontrar el que cuenta la historia que querías contar.

Una plantilla mínima de decisión sería:

PreguntaRespuesta que debe existir
¿Cuál es la unidad de decisión?Caso, usuario, documento, consulta, turno, sesión.
¿Qué campos se usan como features?Lista permitida y lista prohibida.
¿Qué campos se usan solo para auditoría?Segmentos agregados, con permiso y propósito claro.
¿Qué slices son críticos?Los que no pueden fallar aunque la media global pase.
¿Qué métrica gobierna cada slice?Recall, miss rate, revisión, coste, latencia, calibración.
¿Qué gate decide?Umbral medible de pass, review o block.
¿Qué acción sigue si falla?Más datos, revisión de etiqueta, cambio de umbral, desautomatización, monitorización.

Para un ingeniero, lo más peligroso no es que el reporte diga block. Lo peligroso es que no exista reporte. Sin slices, la decisión parece técnica porque tiene números, pero no tiene trazabilidad.

Manos a la obra

El kit del capítulo está en:

kit/

La práctica parte de predicciones ya generadas. No entrena un modelo. No mueve el umbral para mejorar el resultado. Toma una política congelada, la aplica sobre test y produce una auditoría por slices.

Estructura

kit/
  README.md
  data/decision_predictions.csv
  contracts/slice_decision_policy.json
  contracts/slice_decision_policy_review_band.json
  contracts/bias_audit_playbook.md
  ops/audit_decision_slices.py
  ops/compare_mitigation.py
  ops/audit_with_fairlearn.py
  output/slice_audit_report.json
  output/slice_metrics.csv
  output/slice_decision.md
  output/slice_audit_card.md
  output/mitigation_before_after.md
  output/mitigation_before_after.csv
  output/mitigation_critical_slices.csv

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/audit_decision_slices.py --write
cat output/slice_decision.md
python3 -m json.tool output/slice_audit_report.json

Para ver el antes/después de la mitigación por banda de revisión:

python3 ops/compare_mitigation.py --write
cat output/mitigation_before_after.md

Para repetir parte de la lectura con Fairlearn o con el fallback estándar si no tienes dependencias instaladas:

python3 ops/audit_with_fairlearn.py --field access_need --write
python3 -m json.tool output/fairlearn_metricframe.json

Si quieres obtener el MetricFrame real de Fairlearn, crea un entorno e instala dependencias antes de repetir el comando:

python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install pandas fairlearn
python3 ops/audit_with_fairlearn.py --field access_need --write
python3 -m json.tool output/fairlearn_metricframe.json

Qué deberías ver

El resultado esperado queda en block. No porque el sistema no acierte nada, sino porque los gates conectan métricas con consecuencias:

{
  "release_status": "block",
  "overall": {
    "n": 36,
    "safety_capture": 0.7778,
    "miss_rate": 0.2222,
    "review_rate": 0.3611
  }
}

La lectura humana aparece en output/slice_decision.md:

Estado: block
La captura segura global queda por debajo del mínimo.
Un slice crítico contiene casos prioritarios enviados a flujo normal.

La salida más importante para ingeniería es output/slice_metrics.csv. Ahí puedes ordenar por miss_rate, review_rate, cost_per_case o auto_recall. Si solo miras overall, te pierdes el motivo de la decisión.

El archivo contracts/bias_audit_playbook.md funciona como checklist profesional. No calcula nada: obliga a escribir unidad de decisión, fuentes de sesgo, señales detectables, gates, buenas prácticas y cosas que evitar. Es el tipo de documento que conviene tener junto al reporte automático, porque una auditoría no es solo matemática; también es criterio operativo.

El archivo output/mitigation_before_after.md funciona como defensa técnica. Enseña que una mitigación aceptable no se resume en “mejoró la métrica”: debe declarar qué bajó, qué subió, qué coste aparece y por qué la política candidata queda en review.

El script ops/audit_with_fairlearn.py no sustituye el kit. Lo conecta con una herramienta real. Si instalas pandas y fairlearn, genera un MetricFrame por el campo elegido y permite comparar la lectura propia con una librería profesional. Esa comparación es valiosa porque evita dos extremos: reinventarlo todo o delegarlo todo.

Qué cambia si lo adaptas a tu caso

Si tu proyecto tiene...Cambia esto
Un clasificador de incidenciastrue_priority, costes y slices por producto/canal.
Un RAG de soporteSlices por tipo de documento, idioma, fecha de actualización y fuente.
Un evaluador automáticoSlices por criterio de rúbrica, longitud, idioma y tipo de fallo.
Un sistema con revisión humanaCoste de revisión y capacidad diaria.
Un modelo local y uno cloudAñade slice por proveedor, latencia y coste.
Documentos con permisosAudita recuperación por permisos y origen, no solo por texto.
Pocos casos por segmentoUsa review y recolecta más datos antes de automatizar.

Qué entregaría un alumno

  1. slice_audit_report.json generado.
  2. slice_metrics.csv ordenado por una métrica elegida.
  3. slice_decision.md explicado con sus propias palabras.
  4. Dos slices nuevos justificados para su proyecto.
  5. Un cambio en slice_decision_policy.json y explicación de por qué no se ha elegido mirando test.
  6. Una propuesta de recogida de datos para slices con muestra insuficiente.
  7. Una ficha slice_audit_card.md lista para adjuntar a una model card o data card.
  8. Una versión adaptada de bias_audit_playbook.md para su propio dominio.
  9. mitigation_before_after.md explicado como trade-off de ingeniería.
  10. Una salida opcional de Fairlearn o una justificación de por qué otra herramienta encaja mejor.

Cómo encaja todo

Este mapa debe leerse como continuidad de ingeniería. Los capítulos anteriores construyeron el suelo: linaje, calidad, split honesto y representación. Este capítulo pregunta si la política resultante se comporta de forma defendible en los segmentos que importan. Después, el capítulo 06 usará estos mismos slices como señales de monitorización: si producción cambia, no miraremos solo drift global.

La decisión central aquí es pasar de “mi métrica global mejora” a “sé qué slices sostienen o impiden automatizar”. Esa decisión conecta directamente con evaluación, calibración, interpretabilidad y gobernanza.

graph TD
    subgraph "Este capítulo"
        UNIT["Unidad de decisión"]
        POLICY["Política congelada"]
        FIELDS["Campos de auditoría"]
        SLICE["Slices críticos"]
        MET["Métricas por slice"]
        UNC["Tamaño e intervalo"]
        GATE["Gate de decisión"]
        ART["Reporte y card"]
    end
    subgraph "Mismo facsímil"
        C01["Linaje<br/>cap. 1"]
        C02["Etiquetas<br/>cap. 2"]
        C03["Test honesto<br/>cap. 3"]
        C04["Representación<br/>cap. 4"]
        C06["Drift por slice<br/>cap. 6"]
        C07["Causalidad<br/>cap. 7"]
    end
    subgraph "Otros facsímiles"
        CAL["Calibración<br/>fasc. 7"]
        INT["Interpretabilidad<br/>fasc. 7"]
        OPS["EvalOps<br/>fasc. 6"]
        GOV["Gobernanza<br/>fasc. 9"]
    end

    C01 -->|"define campos"| FIELDS
    C02 -->|"define etiquetas"| MET
    C03 -->|"reserva test"| POLICY
    C04 -->|"define señal"| UNIT
    CAL -->|"da umbrales"| POLICY

    UNIT -->|"se evalúa con"| POLICY
    POLICY -->|"se mira por"| SLICE
    FIELDS -->|"segmenta"| SLICE
    SLICE -->|"calcula"| MET
    MET -->|"exige"| UNC
    UNC -->|"matiza"| GATE
    MET -->|"activa"| GATE
    GATE -->|"documenta"| ART

    GATE -->|"se monitoriza en"| C06
    SLICE -->|"pide experimento en"| C07
    ART -->|"ayuda a explicar"| INT
    GATE -->|"se automatiza en"| OPS
    FIELDS -->|"deja límites"| GOV

    style UNIT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style POLICY fill:#F5F5F5,stroke:#000000,stroke-width:2
    style FIELDS fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SLICE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style MET fill:#F5F5F5,stroke:#000000,stroke-width:2
    style UNC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style GATE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style ART fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C01 stroke-dasharray: 5 5
    style C02 stroke-dasharray: 5 5
    style C03 stroke-dasharray: 5 5
    style C04 stroke-dasharray: 5 5
    style C06 stroke-dasharray: 5 5
    style C07 stroke-dasharray: 5 5
    style CAL stroke-dasharray: 5 5
    style INT stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
SliceSubconjunto de datos definido por una condición útil para evaluar una decisión.
Atributo de auditoríaCampo usado para medir comportamiento por segmentos.
Atributo no usado por el modeloCampo que no entra como feature, pero puede usarse para auditoría agregada.
Paridad demográficaComparación de tasas de selección entre grupos.
Igualdad de oportunidadComparación de verdaderos positivos entre grupos positivos reales.
Odds igualadasComparación simultánea de verdaderos positivos y falsos positivos entre grupos.
Calibración por grupoComprobación de que un score significa algo parecido en cada grupo.
DisparidadDiferencia medible entre slices para una métrica concreta.
Captura seguraProporción de casos importantes priorizados o enviados a revisión.
GateRegla medible que convierte métricas en decisión de release.
ProxyVariable que sustituye a otra más difícil de medir, con riesgo de medir otra cosa.
OOVTérmino fuera del vocabulario usado para construir una representación textual.
Par mínimoDos entradas casi iguales que solo cambian una pieza controlada.
WEATTest de asociación para medir relaciones entre grupos de palabras en embeddings.
IntersecciónSlice definido por la combinación de varios atributos.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Mirar solo la media globalEs cómoda y fácil de explicar.Exigir slices críticos antes de aprobar.
Partir por demasiadas columnasParece más completo.Empezar por hipótesis de decisión y coste.
Confundir auditoría con featureSi tengo el campo, parece que puedo usarlo.Separar fields_not_for_model y audit_fields.
Ajustar umbrales mirando testEs tentador arreglar el slice que falla.Congelar umbrales desde validation y versionar la política.
Ignorar tamaños pequeñosUna tabla con números da sensación de rigor.Añadir mínimos, intervalos y estado review.
Elegir una métrica de equidad sin contextoLa palabra suena suficiente.Preguntar qué error controla y qué compromiso acepta.
No dejar acción concretaEl reporte se queda en diagnóstico.Escribir decisión, dueño, gate y siguiente paso.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Qué es un slice y por qué no equivale a cualquier columna?
  2. ¿Qué diferencia hay entre feature y atributo de auditoría?
  3. ¿Por qué una métrica global puede esconder un problema importante?
  4. ¿Qué mide la paridad demográfica?
  5. ¿Qué mide la igualdad de oportunidad?
  6. ¿Por qué odds igualadas mira verdaderos positivos y falsos positivos?
  7. ¿Qué significa que algunas nociones de equidad sean incompatibles en ciertos escenarios?
  8. ¿Por qué conviene separar auto-recall y captura segura?
  9. ¿Qué coste se asigna en el kit a un falso negativo operativo?
  10. ¿Por qué access_need=si bloquea la política del kit?
  11. ¿Qué archivo contiene la tabla plana de métricas por slice?
  12. ¿Qué harías si un slice crítico tiene muestra insuficiente?
  13. ¿Por qué no se deben ajustar umbrales mirando test?
  14. ¿Cómo conectarías esta auditoría con una model card?
  15. ¿Qué slices monitorizarías en producción en el capítulo siguiente?
  16. ¿Qué diferencia hay entre sesgo de cobertura, medición, proxy y representación?
  17. ¿Por qué los estudios de embeddings no se detectan igual que los de clasificación?
  18. ¿Qué señal usarías para detectar falsos positivos asociados a términos concretos?
  19. ¿Qué significa probar pares mínimos o contrafactuales?
  20. ¿Qué parte del playbook adaptarías primero a tu proyecto?
  21. ¿Por qué la política candidata pasa de block a review, pero no a pass?
  22. ¿Qué trade-off aparece al ampliar la banda de revisión?
  23. ¿Qué representa Δm(S)\Delta_m(S) en una mitigación con restricciones?
  24. ¿Qué pedirías a una herramienta antes de incorporarla al ciclo de release?
  25. ¿Qué SLI por slice monitorizarías cuando el sistema llegue a producción?

En resumen

IdeaQué te llevas
La media global no decide sola.Hay que mirar slices conectados con consecuencias reales.
Un campo puede auditar sin decidir.No todo atributo útil para medir debe entrar al modelo.
La métrica depende del error.Paridad, oportunidad, odds y calibración responden preguntas distintas.
El tamaño importa.Un slice pequeño pide revisión o más datos, no conclusión fuerte.
La auditoría debe producir acción.Reporte, CSV, card y decisión son artefactos de ingeniería.
Los sesgos tienen mecanismos distintos.Cobertura, proxy, etiqueta, representación y política requieren pruebas diferentes.
Las buenas prácticas se escriben antes de test.Si eliges slices y gates después, la auditoría pierde fuerza.
Mitigar implica trade-offs.La banda de revisión reduce pérdida, pero aumenta carga humana.
Las herramientas no deciden solas.Fairlearn, AIF360, Clarify o Evidently ayudan si hay contrato, slices y gates.
Producción cambia la pregunta.Los mismos slices deben convertirse en SLI, SLO, alerta y runbook.

Para saber más

Bellamy, R. K. E., Dey, K., Hind, M., Hoffman, S. C., Houde, S., Kannan, K., Lohia, P., Martino, J., Mehta, S., Mojsilovic, A., Nagar, S., Ramamurthy, K. N., Richards, J., Saha, D., Sattigeri, P., Singh, M., Varshney, K. R. y Zhang, Y. (2019). AI Fairness 360: An Extensible Toolkit for Detecting and Mitigating Algorithmic Bias. IBM Journal of Research and Development, 63(4/5), 4:1-4:15. DOI

Amazon Web Services. (2026). Amazon SageMaker Clarify. Documentación

Arize AI. (2026). ML Observability Platform. Producto

Arthur AI. (2020). Product Update - Bias Monitoring v2.1. Blog

Bolukbasi, T., Chang, K.-W., Zou, J. Y., Saligrama, V. y Kalai, A. T. (2016). Man is to Computer Programmer as Woman is to Homemaker? Debiasing Word Embeddings. Advances in Neural Information Processing Systems 29, 4349-4357. Paper

Buolamwini, J. y Gebru, T. (2018). Gender Shades: Intersectional Accuracy Disparities in Commercial Gender Classification. Proceedings of Machine Learning Research, 81, 77-91. Paper

Caliskan, A., Bryson, J. J. y Narayanan, A. (2017). Semantics Derived Automatically from Language Corpora Contain Human-Like Biases. Science, 356(6334), 183-186. DOI

Center for Data Science and Public Policy. (2026). Aequitas documentation. Documentación

Chouldechova, A. (2017). Fair Prediction with Disparate Impact: A Study of Bias in Recidivism Prediction Instruments. Big Data, 5(2), 153-163. DOI

Dixon, L., Li, J., Sorensen, J., Thain, N. y Vasserman, L. (2018). Measuring and Mitigating Unintended Bias in Text Classification. Proceedings of the 2018 AAAI/ACM Conference on AI, Ethics, and Society, 67-73. Google Research

Dwork, C., Hardt, M., Pitassi, T., Reingold, O. y Zemel, R. (2012). Fairness Through Awareness. Proceedings of the 3rd Innovations in Theoretical Computer Science Conference, 214-226. DOI

Evidently AI. (2026). Evidently documentation. Documentación

Fairlearn. (2026). Assessment: Performing a Fairness Assessment. Documentación

Fairlearn. (2026). Mitigations. Documentación

Fiddler AI. (2026). Fairness. Documentación

Gebru, T., Morgenstern, J., Vecchione, B., Vaughan, J. W., Wallach, H., Daumé III, H. y Crawford, K. (2021). Datasheets for Datasets. Communications of the ACM, 64(12), 86-92. DOI

Giskard. (2026). Giskard documentation. Documentación

Hardt, M., Price, E. y Srebro, N. (2016). Equality of Opportunity in Supervised Learning. Advances in Neural Information Processing Systems 29, 3323-3331. Paper

IBM Research. (2026). AI Fairness 360 documentation. Documentación

Kleinberg, J., Mullainathan, S. y Raghavan, M. (2017). Inherent Trade-Offs in the Fair Determination of Risk Scores. arXiv

Microsoft. (2026). Use the Responsible AI dashboard in Azure Machine Learning studio. Documentación

Mitchell, M., Wu, S., Zaldivar, A., Barnes, P., Vasserman, L., Hutchinson, B., Spitzer, E., Raji, I. D. y Gebru, T. (2019). Model Cards for Model Reporting. Proceedings of the Conference on Fairness, Accountability, and Transparency, 220-229. DOI

Nadeem, M., Bethke, A. y Reddy, S. (2021). StereoSet: Measuring Stereotypical Bias in Pretrained Language Models. ACL-IJCNLP 2021, 5356-5371. DOI

Nangia, N., Vania, C., Bhalerao, R. y Bowman, S. R. (2020). CrowS-Pairs: A Challenge Dataset for Measuring Social Biases in Masked Language Models. EMNLP 2020, 1953-1967. DOI

Obermeyer, Z., Powers, B., Vogeli, C. y Mullainathan, S. (2019). Dissecting Racial Bias in an Algorithm Used to Manage the Health of Populations. Science, 366(6464), 447-453. DOI

Parrish, A., Chen, A., Nangia, N., Padmakumar, V., Phang, J., Thompson, J., Htut, P. M. y Bowman, S. R. (2022). BBQ: A Hand-Built Bias Benchmark for Question Answering. Findings of ACL 2022, 2086-2105. DOI

Raji, I. D., Smart, A., White, R. N., Mitchell, M., Gebru, T., Hutchinson, B., Smith-Loud, J., Theron, D. y Barnes, P. (2020). Closing the AI Accountability Gap: Defining an End-to-End Framework for Internal Algorithmic Auditing. arXiv

Responsibly. (2026). Responsibly documentation. Documentación

TensorFlow. (2026). Fairness Indicators. GitHub

Wexler, J., Pushkarna, M., Bolukbasi, T., Wattenberg, M., Viégas, F. y Wilson, J. (2019). The What-If Tool: Interactive Probing of Machine Learning Models. IEEE Transactions on Visualization and Computer Graphics. Google Research

WhyLabs. (2026). WhyLabs documentation. Documentación

Notas

  1. Hardt, M., Price, E. y Srebro, N. (2016). Equality of Opportunity in Supervised Learning. Advances in Neural Information Processing Systems 29, 3323-3331. https://papers.nips.cc/paper/6374-equality-of-opportunity-in-supervised-learning

  2. Chouldechova, A. (2017). Fair Prediction with Disparate Impact: A Study of Bias in Recidivism Prediction Instruments. Big Data, 5(2), 153-163. https://doi.org/10.1089/big.2016.0047

  3. Kleinberg, J., Mullainathan, S. y Raghavan, M. (2017). Inherent Trade-Offs in the Fair Determination of Risk Scores. https://arxiv.org/abs/1609.05807

  4. Obermeyer, Z., Powers, B., Vogeli, C. y Mullainathan, S. (2019). Dissecting Racial Bias in an Algorithm Used to Manage the Health of Populations. Science, 366(6464), 447-453. https://doi.org/10.1126/science.aax2342

  5. Bolukbasi, T., Chang, K.-W., Zou, J. Y., Saligrama, V. y Kalai, A. T. (2016). Man is to Computer Programmer as Woman is to Homemaker? Debiasing Word Embeddings. NeurIPS 2016, 4349-4357. https://papers.nips.cc/paper/6228-man-is-to-computer-programmer-as-woman-is-to-homemaker-debiasing-word-embeddings

  6. Caliskan, A., Bryson, J. J. y Narayanan, A. (2017). Semantics Derived Automatically from Language Corpora Contain Human-Like Biases. Science, 356(6334), 183-186. https://doi.org/10.1126/science.aal4230

  7. Buolamwini, J. y Gebru, T. (2018). Gender Shades: Intersectional Accuracy Disparities in Commercial Gender Classification. Proceedings of Machine Learning Research, 81, 77-91. https://proceedings.mlr.press/v81/buolamwini18a.html

  8. Dixon, L., Li, J., Sorensen, J., Thain, N. y Vasserman, L. (2018). Measuring and Mitigating Unintended Bias in Text Classification. AIES 2018, 67-73. https://research.google/pubs/measuring-and-mitigating-unintended-bias-in-text-classification/

  9. Nangia, N., Vania, C., Bhalerao, R. y Bowman, S. R. (2020). CrowS-Pairs: A Challenge Dataset for Measuring Social Biases in Masked Language Models. EMNLP 2020, 1953-1967. https://doi.org/10.18653/v1/2020.emnlp-main.154

  10. Nadeem, M., Bethke, A. y Reddy, S. (2021). StereoSet: Measuring Stereotypical Bias in Pretrained Language Models. ACL-IJCNLP 2021, 5356-5371. https://doi.org/10.18653/v1/2021.acl-long.416

  11. Parrish, A. et al. (2022). BBQ: A Hand-Built Bias Benchmark for Question Answering. Findings of ACL 2022, 2086-2105. https://doi.org/10.18653/v1/2022.findings-acl.165

  12. Fairlearn. (2026). Assessment: Performing a Fairness Assessment. https://fairlearn.org/main/user_guide/assessment/. Consultado el 7 de junio de 2026.

  13. Fairlearn. (2026). Mitigations. https://fairlearn.org/main/user_guide/mitigation/index.html. Consultado el 7 de junio de 2026.

  14. IBM Research. (2026). AI Fairness 360 documentation. https://aif360.readthedocs.io/en/stable/index.html. Consultado el 7 de junio de 2026.

  15. Bellamy, R. K. E. et al. (2019). AI Fairness 360: An Extensible Toolkit for Detecting and Mitigating Algorithmic Bias. IBM Journal of Research and Development, 63(4/5), 4:1-4:15. https://doi.org/10.1147/JRD.2019.2942287

  16. Center for Data Science and Public Policy. (2026). Aequitas documentation. https://dssg.github.io/aequitas/. Consultado el 7 de junio de 2026.

  17. TensorFlow. (2026). Fairness Indicators. https://github.com/tensorflow/fairness-indicators. Consultado el 7 de junio de 2026.

  18. Wexler, J. et al. (2019). The What-If Tool: Interactive Probing of Machine Learning Models. IEEE TVCG. https://research.google/pubs/the-what-if-tool-interactive-probing-of-machine-learning-models/

  19. Responsibly. (2026). Responsibly documentation. https://docs.responsibly.ai/. Consultado el 7 de junio de 2026.

  20. Amazon Web Services. (2026). Amazon SageMaker Clarify. https://aws.amazon.com/sagemaker/ai/clarify/. Consultado el 7 de junio de 2026.

  21. Microsoft. (2026). Use the Responsible AI dashboard in Azure Machine Learning studio. https://learn.microsoft.com/en-us/azure/machine-learning/how-to-responsible-ai-dashboard. Consultado el 7 de junio de 2026.

  22. Evidently AI. (2026). Evidently documentation. https://docs.evidentlyai.com/docs/library/overview. Consultado el 7 de junio de 2026.

  23. Giskard. (2026). Giskard documentation. https://docs.giskard.ai/. Consultado el 7 de junio de 2026.

  24. Fiddler AI. (2026). Fairness. https://docs.fiddler.ai/observability/fairness. Consultado el 7 de junio de 2026.

  25. Arize AI. (2026). ML Observability Platform. https://arize.com/capabilities/. Consultado el 7 de junio de 2026.

  26. WhyLabs. (2026). WhyLabs documentation. https://docs.whylabs.ai/docs/. Consultado el 7 de junio de 2026.

  27. Arthur AI. (2020). Product Update - Bias Monitoring v2.1. https://www.arthur.ai/blog/product-update-bias-monitoring-v21. Consultado el 7 de junio de 2026.

Capítulo 06

Facsímil 8 · La ciencia de los datos

Capítulo 06: DataOps: pipelines, drift y monitorización

Qué deberías poder hacer al terminar

En el capítulo anterior vimos que una decisión no se publica solo porque tenga una métrica global aceptable. Hay que mirarla por slices, escribir gates y decidir pass, review o block. Ahora viene la pregunta operativa: ¿qué pasa después de publicar?

Los datos cambian. Las colas cambian. Los idiomas cambian. Un producto nuevo concentra tráfico. Un campo deja de llegar. Una traza se pierde. Una latencia sube. La etiqueta real llega días después. Y el sistema que el lunes parecía razonable puede dejar de representar la producción del jueves.

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Diseñar un pipeline de datos para IA.Distingues fuente, validación, transformación, evaluación, serving y monitorización.
Leer una ejecución como artefacto.Sabes qué inputs, outputs, hashes, versiones y estado debe dejar una run.
Definir SLIs y SLOs de datos.Escribes indicadores medibles, objetivos y acciones cuando fallan.
Medir drift sin convertirlo en superstición.Calculas distancia entre referencia y producción y decides qué revisar.
Conectar slices con operación.No miras solo drift global: mides slices críticos y consecuencias.
Crear un runbook y un postmortem.Dejas una guía de respuesta y una explicación técnica de la incidencia.

La frase central:

DataOps no es tener dashboards. Es saber qué dato cambió, qué run lo produjo, qué decisión afecta y qué acción toca.

La escena: ayer pasaba, hoy bloquea

Imagina que el asistente académico ya está en producción. El viernes se aprobó la política de decisión: casos claros se priorizan, casos claramente normales pasan a flujo normal y casos inciertos van a revisión. El lunes todo parece estable.

El martes entra una campaña de prácticas internacionales. De repente suben los casos en inglés, casi todos con necesidad de accesibilidad, y además una parte del pipeline pierde trace_id. La métrica global del mes todavía no parece dramática, pero la ventana del día cuenta otra historia: más latencia, más revisión, más casos prioritarios que acaban como normal.

Ese es el problema que resuelve DataOps. No pregunta solo “¿funcionó el modelo?”. Pregunta:

Pregunta operativaPor qué importa
¿Qué ventana cambió?Una media mensual puede esconder un día roto.
¿Qué versión de pipeline produjo los eventos?Un cambio de código puede explicar el problema.
¿Qué datos entraron?Sin hash ni versión, no se reproduce la decisión.
¿Qué slices fallan?El daño operativo suele concentrarse.
¿Hay trazas completas?Sin trace_id, investigar se vuelve conjetura.
¿Qué runbook se ejecuta?Una alerta sin acción se convierte en ruido.

Qué no es DataOps

DataOps no es “tener un CSV limpio”. Tampoco es instalar un orquestador y dar por resuelta la operación. Un orquestador lanza jobs; no decide por sí mismo si un dataset representa producción, si un slice crítico se degradó o si una ventana debe bloquear un release.

Tampoco es guardar logs infinitos sin contrato. Si cada evento tiene mil campos pero no sabemos cuáles son obligatorios, qué SLI alimentan o quién responde cuando fallan, hemos cambiado desorden pequeño por desorden caro.

Y no es mirar drift como si fuera una alarma universal. Drift significa cambio de distribución. A veces es una incidencia; a veces es una campaña esperada; a veces es una mejora de cobertura; a veces indica que la evaluación ya no representa el uso real. La métrica abre una revisión. No sustituye el criterio.

Qué sí es DataOps para IA

DataOps es tratar los datos, runs y artefactos como piezas operables del sistema. Esto incluye contratos, validaciones, linaje, versionado, monitorización, gates y runbooks. En IA, además, debe conectar con modelos, features, embeddings, prompts, evals, slices y decisiones.

Sculley et al. explicaron que los sistemas de ML acumulan deuda técnica por dependencias de datos, cambios no locales y realimentaciones difíciles de ver.1 TFX formalizó una arquitectura de producción con ingestión, validación, transformación, entrenamiento, evaluación y serving reproducibles.2 El ML Test Score propuso que la madurez de un sistema ML se mida también por tests de datos, monitorización y gestión de cambios.3

Fecha de corte: 7 de junio de 2026. Fuentes consultadas ese día: OpenLineage, OpenTelemetry, Great Expectations, Evidently, Prometheus, Apache Airflow, Dagster, Prefect, dbt, TFX, ML Test Score y literatura de ingeniería de ML. Lo estable no es la herramienta concreta: es la obligación de versionar, medir, trazar y decidir.

El pipeline por dentro

Un pipeline de IA no es solo “entrenar y desplegar”. Es una cadena de contratos. Ejemplo de fórmula: podemos escribirlo como una composición de funciones para recordar que cada paso transforma datos y deja un artefacto. No describe una arquitectura obligatoria; describe una disciplina de trazabilidad.

A=fk(fk1(f2(f1(D0))))A = f_k(f_{k-1}(\dots f_2(f_1(D_0))\dots))
SímboloSignificadoEjemplo
D0D_0Datos de entrada originales.Eventos de soporte académico.
fif_iPaso del pipeline.Validar schema, crear features, evaluar slices.
AAArtefacto final de la run.Reporte, modelo, índice, decisión o alerta.
kkNúmero de pasos encadenados.7 pasos desde ingesta hasta gate.

La clave es que cada paso debe dejar evidencia:

PasoEntradaSalidaEvidencia mínima
IngestaFuente externa o interna.Snapshot controlado.source_id, timestamp, hash.
ValidaciónSnapshot.Reporte de calidad.Checks, columnas, valores inválidos.
TransformaciónDatos válidos.Features, chunks o embeddings.Versión de código, parámetros, hashes.
EvaluaciónPredicciones o outputs.Métricas y slices.Dataset, política, umbrales, intervalos.
GateMétricas.pass, review o block.Regla exacta y motivo.
ServingModelo o política.Decisiones.trace_id, versión, latencia.
MonitorizaciónEventos de producción.Alertas y scorecard.SLI, SLO, runbook, owner.

OpenLineage propone un estándar abierto para capturar metadatos de runs, jobs y datasets en componentes de pipeline.4 OpenTelemetry define señales de observabilidad como trazas, métricas y logs; una traza permite seguir una operación por spans, una métrica mide valores agregados y un log registra eventos.567

En términos prácticos:

SeñalQué contestaEjemplo en IA
LogQué ocurrió.“Evento p013 llegó sin trace_id”.
MétricaCuánto ocurre.missing_trace_rate = 0.1.
TrazaPor dónde pasó.Ingesta → validación → decisión → revisión.
LinajeDe dónde viene y qué produjo.production_events.csvmonitoring_report.json.
RunbookQué hacer ahora.Revisar pipeline pipe-1.4.2, idioma en, slice access_need=si.

Patrones de arquitectura de pipeline

Un ingeniero de software no debería quedarse en “tengo un script”. La pregunta es qué garantías necesita ese script cuando se ejecuta todos los días, con datos que cambian y con personas dependiendo de sus salidas.

PatrónQué resuelveRiesgo si no lo diseñas
BatchProcesar ventanas cerradas.Repetir una ventana y obtener otra decisión sin saber por qué.
StreamingProcesar eventos conforme llegan.Mezclar eventos tardíos, duplicados o incompletos.
CheckpointRecordar hasta dónde llegó una run.Reprocesar a ciegas o perder eventos.
BackfillRecalcular ventanas antiguas.Cambiar histórico sin versionar pipeline, datos y contrato.
ReplayReproducir eventos con una versión concreta.No poder depurar una decisión pasada.
RetryReintentar un paso fallido.Duplicar efectos si no hay idempotencia.
CanaryProbar una versión en una parte controlada.Publicar un cambio a toda producción sin señal temprana.
Shadow modeEjecutar una versión sin afectar la decisión.Confundir evaluación silenciosa con decisión real.

Apache Airflow organiza workflows como DAGs con tareas y dependencias.8 Dagster enfatiza assets definidos por software, linaje, observabilidad y testabilidad.9 Prefect documenta deployments con metadatos de ejecución remota, versiones y configuración, y también retries configurables por workflow o tarea.1011

La herramienta importa menos que el contrato de ejecución:

Decisión de diseñoPregunta que debes responder
Orquestador¿Quién lanza la run, con qué parámetros y dónde queda su estado?
Idempotencia¿Qué clave evita duplicar una decisión si se reintenta?
Retries¿Qué pasos se pueden repetir y cuáles requieren revisión manual?
Backfill¿Qué versión de datos, código y contrato se usa para recalcular?
Checkpoint¿Qué pasa si una run cae a mitad?
Output¿La salida se escribe una vez, se sobreescribe o se versiona?
Rollback¿Cómo volvemos a una política anterior sin perder trazabilidad?

Idempotencia merece una explicación propia. Una operación es idempotente si repetirla produce el mismo efecto observable que ejecutarla una vez. En pipelines de IA, la clave suele ser algo como:

idempotency_key = window + event_id

Si una tarea falla después de emitir una decisión y se reintenta sin esa clave, puedes duplicar un caso, mandar dos revisiones humanas o contar dos veces una alerta. Esto no es un detalle de plataforma: es ingeniería de software aplicada al dato.

Contratos entre servicios y evolución de schema

En capítulos anteriores hablamos de contrato de datos. Aquí ampliamos la idea: un pipeline de producción tiene contratos entre productores y consumidores. El productor promete columnas, tipos, semántica, frecuencia y trazabilidad. El consumidor promete cómo usará esos campos y qué cambios acepta.

dbt model contracts permiten declarar y hacer cumplir columnas, tipos y restricciones en modelos dbt.12 Great Expectations organiza expectativas verificables sobre datos. OpenLineage conecta jobs y datasets. OpenTelemetry conecta ejecución y trazas. Son capas distintas de la misma idea: un cambio no debería romper al consumidor en silencio.

CambioCompatibleRequiere revisiónRompe
Añadir columna opcionalSi afecta coste o privacidad.No.
Añadir valor nuevo a catálogoA veces.Sí, si cambia slices o política.Si el consumidor no lo acepta.
Renombrar columna obligatoriaNo.Sí.Sí, salvo alias versionado.
Cambiar significado de decisionNo.Sí.Sí.
Quitar trace_idNo.Sí.Sí.
Subir un SLOSí.Sí, si bloquea más ventanas.No necesariamente.

Un contrato de evolución debería declarar:

PiezaEjemplo
Compatibilidad hacia atrásLa versión nueva acepta datos de la versión anterior.
Compatibilidad hacia delanteLa versión anterior puede ignorar campos nuevos opcionales.
DeprecaciónCampo permitido hasta una fecha o versión.
Aliasesstudent_profile puede aceptar temporalmente profile.
Campo obligatoriotrace_id no se puede quitar.
Política de rollbackVolver a pipe-1.4.1 conserva outputs y hashes.

Observabilidad correlacionada

La observabilidad de IA no consiste en guardar un log grande. Consiste en poder saltar de una alerta a los eventos concretos y de ahí a la traza que explica dónde se degradó.

Una traza mínima de decisión debería poder responder:

CampoPor qué importa
trace_idUne logs, métricas, spans y evento final.
event_idIdentifica la unidad de decisión.
pipeline_versionDistingue cambio de código de cambio de datos.
model_versionPermite comparar comportamiento por versión.
data_versionEvita investigar con otro snapshot.
policy_versionExplica por qué el mismo score acabó en otra decisión.
span_nameLocaliza ingesta, validación, scoring, decisión o emisión.
duration_msSepara problema de calidad de problema de latencia.

En el kit, el contrato de ingeniería exige spans ingest, validate, score, decide y emit. El evento p013 no tiene trace_id. El evento p017 tiene traza, pero le falta emit. Los eventos p011, p012 y p017 muestran score lento. Esa correlación permite decir algo concreto: la ventana 2026-06-08 no solo cambió de distribución; también llegó peor instrumentada y más lenta.

EventoVentanaSeñal
p0112026-06-08Traza total 710 ms, score lento.
p0122026-06-08Traza total 755 ms, score lento.
p0132026-06-08Sin trace_id.
p0172026-06-08Falta span emit, score lento.

Sin esta correlación, el equipo podría culpar al modelo, al dato o al usuario sin evidencia suficiente. Con trazas, la pregunta cambia: ¿qué parte del pipeline cambió entre pipe-1.4.1 y pipe-1.4.2?

Testing de pipelines de IA

Un pipeline de IA necesita tests, pero no todos los tests son iguales. Un test unitario puede comprobar que una función calcula una media. Eso es necesario, pero insuficiente. En producción también hay que probar contratos, ventanas, trazabilidad, linaje, regresiones por slices y comportamiento operativo.

Tipo de testQué compruebaEjemplo útil
UnitarioUna función aislada.total_variation_distance(P, Q) devuelve 0.8 en un caso conocido.
Contract testProductor y consumidor hablan el mismo idioma.trace_id, event_id, decision, latency_ms y window existen y tienen tipo esperado.
Data quality testLa ventana tiene datos válidos.No hay nulos en campos obligatorios, catálogos permitidos y rangos razonables.
Lineage testLa run conserva procedencia.Los hashes de inputs y outputs quedan escritos en lineage_event.json.
Regression testUna versión nueva no empeora una referencia.pipe-1.4.2 no reduce captura segura frente a pipe-1.4.1.
Slice testNo se esconde un fallo en la media.language=en y access_need=si mantienen SLO propio.
Trace testLa operación se puede investigar.Cada evento crítico tiene spans ingest, validate, score, decide y emit.
Replay testSe puede reproducir una ventana.Reejecutar 2026-06-08 con la misma versión produce la misma decisión.

El error típico es probar solo el código y no probar el sistema. En IA, el sistema incluye datos, contratos, scheduler, runtime, versión de modelo, política de decisión, evals, slices y observabilidad. Por eso el ML Test Score no se limita a accuracy: pregunta por tests de datos, monitorización, cambios y dependencia de features.13

Para un equipo de ingeniería, una regla práctica sería esta:

No hay release de pipeline si no pasan:
1. contrato de datos,
2. contrato de trazas,
3. replay de una ventana conocida,
4. scorecard de slices críticos,
5. evento de linaje con hashes.

Esto parece mucho hasta que ocurre la primera incidencia real. Entonces descubres que esos cinco puntos no son burocracia: son la diferencia entre investigar en una hora o discutir durante días.

Drift, SLI, SLO y presupuesto de error

El drift se mide comparando una distribución de referencia PP con una distribución actual QQ. Una medida sencilla es la distancia de variación total:

TV(P,Q)=12cCP(c)Q(c)TV(P,Q)=\frac{1}{2}\sum_{c\in C}|P(c)-Q(c)|
SímboloSignificadoEjemplo
PPDistribución de referencia.Idiomas durante validación.
QQDistribución actual.Idiomas del 8 de junio de 2026.
CCCategorías posibles.es, ca, en.
P(c)P(c)Proporción de la categoría cc en referencia.en = 0.2.
Q(c)Q(c)Proporción de la categoría cc en producción.en = 1.0.
TV(P,Q)TV(P,Q)Distancia entre 0 y 1.0.8, cambio fuerte.

También se usa PSI:

PSI(P,Q)=cC(Q(c)P(c))logQ(c)P(c)PSI(P,Q)=\sum_{c\in C}(Q(c)-P(c))\log\frac{Q(c)}{P(c)}
SímboloSignificadoEjemplo
PSIPSIÍndice de estabilidad poblacional.11.711575 para language.
log\logLogaritmo natural.Penaliza cambios grandes de proporción.
Q(c)P(c)Q(c)-P(c)Diferencia de proporciones.en sube mucho.

Pero drift no es lo único. Para operar necesitamos SLIs y SLOs.

ConceptoDefiniciónEjemplo
SLIIndicador medible.latency_p95_ms, miss_rate, missing_trace_rate.
SLOObjetivo sobre un SLI.latency_p95_ms <= 650.
Presupuesto de errorMargen tolerado antes de frenar cambios.Si miss_rate > 0.12, no se aumenta automatización.
GateRegla que convierte SLOs en estado.block si falta trazabilidad o cae captura segura.

Prometheus insiste en que los nombres de métricas deben ser claros, consistentes y expresar unidades cuando aplica.14 Eso parece menor hasta que tienes que investigar una alerta a las 9 de la mañana. latency es ambiguo; decision_latency_p95_ms dice mucho más.

Arquitectura operativa de un sistema de datos para IA

Anatomía de un pipeline DataOps para IA Diagrama en blanco y negro que conecta fuentes, contrato, validación, transformación, evaluación, serving, telemetría, drift, gates y runbook. DataOps en IA: de evento a decisión operativa Cada caja debe dejar artefacto, versión y owner. Fuentes tickets documentos eventos Contrato schema valores permitidos SLOs Run hash inputs versión pipeline outputs Gate pass review block Telemetría logs · métricas · trazas trace_id obligatorio Drift TV · PSI referencia vs ventana Slices idioma · acceso producto crítico Runbook owner acción y salida Decisión operativa no aumentar automatización · revisar ventana · corregir trazabilidad · conservar evidencia IA para gente curiosa / Facsímil 08 / Capítulo 06 / 686f6c61
Un pipeline DataOps convierte eventos en evidencia: contrato, run, telemetría, drift, slices, gate y runbook.

Cómo se ve en producción

En producción trabajamos con ventanas. Una ventana puede ser un día, una hora, un batch, una versión de modelo, una campaña o un segmento de tráfico. La ventana es importante porque las medias largas esconden problemas cortos.

En el kit del capítulo, la ventana 2026-06-07 pasa. La ventana 2026-06-08 bloquea.

VentanaEstadonTrace faltanteLatencia p95RevisiónPérdidaCaptura seguraFlags
2026-06-07pass100.0590.00.40.01.00
2026-06-08block100.1760.00.70.60.415

La segunda ventana no bloquea por una sola razón. Bloquea porque varias señales coinciden:

SeñalLectura
missing_trace_rate = 0.1Falta trazabilidad; una investigación quedaría incompleta.
latency_p95_ms = 760La ventana supera el SLO de latencia.
miss_rate = 0.6Demasiados casos prioritarios pasan a flujo normal.
safety_capture = 0.4La política ya no captura de forma segura los casos importantes.
Drift en language y access_needProducción se aleja mucho de la referencia.
Slices críticos fallanlanguage=en, access_need=si y product=practicas concentran señales.

Aquí se ve la diferencia entre dashboard y operación. Un dashboard muestra números. Un gate operativo dice: no aumentes automatización ni uses esta ventana para reentrenar sin investigar.

Incidentes, postmortems y acciones correctivas

Cuando una ventana queda en block, el trabajo no termina en “hay alerta”. Empieza la parte profesional: reconstruir impacto, señales, causa probable, acción correctiva y criterio de cierre. El postmortem no busca repartir culpa. Busca impedir que el mismo patrón vuelva a repetirse sin que el sistema lo detecte.

Un postmortem técnico mínimo debería incluir:

BloquePregunta que respondeEjemplo del kit
Resumen¿Qué estado queda y qué se bloquea?Estado de ingeniería: block.
Impacto¿Qué decisión queda afectada?No aumentar automatización en 2026-06-08.
Timeline¿Qué scripts y señales detectaron el problema?monitor_dataops.py y inspect_pipeline_engineering.py.
Señales¿Qué eventos concretos fallaron?p013 sin trace_id, p017 sin emit.
Causa probable¿Qué explicación encaja con la evidencia?Cambio de distribución más trazabilidad incompleta y score lento.
Acción correctiva¿Qué se cambia en código, contrato o operación?Hacer trace_id bloqueante y añadir test de spans.
Criterio de cierre¿Cómo sabemos que está resuelto?Replay con trazas completas y scorecard sin block.

El detalle importante es que cada acción correctiva debe convertirse en una defensa técnica. Si el problema fue una columna obligatoria ausente, añade un contract test. Si fue una traza incompleta, añade un trace test. Si fue un retry que duplicó efectos, añade clave de idempotencia. Si fue una ventana de datos rota, añade un gate que impida usarla para reentrenamiento.

Problema detectadoAcción pobreAcción de ingeniería
Falta trace_id“Mirarlo manualmente”.Bloquear emisión si falta trace_id en eventos críticos.
Span score lento“Optimizar algo”.Medir p95 por versión y crear SLO por span.
Slice crítico degradado“Avisar al equipo”.Añadir SLO por slice y replay de la ventana.
Drift fuerte“Reentrenar rápido”.Separar drift esperado, drift operativo y datos no aptos.
Backfill de histórico“Recalcular y ya”.Congelar versión de código, contrato, datos y política.

Un postmortem útil también deja una decisión negativa explícita: qué no se va a hacer. En el kit, no se usa 2026-06-08 para aumentar automatización ni para reentrenar hasta que el gate cierre. Esa frase protege al equipo de convertir datos dudosos en verdad operativa.

Por qué debería importarte

Si no entiendes DataOps, puedes tomar malas decisiones con muy buena intención. Puedes reentrenar con una ventana rota. Puedes comparar modelos con datos que ya no representan producción. Puedes ignorar un slice crítico porque la media global parece estable. Puedes perder trazas justo cuando más las necesitas.

La operación de IA necesita una idea incómoda: el modelo no vive solo. Vive dentro de contratos, datos, versiones, colas, revisiones humanas, latencia, permisos, trazas y decisiones de producto.

Manos a la obra

El kit del capítulo está en:

kit/

Estructura

kit/
  README.md
  data/reference_events.csv
  data/production_events.csv
  contracts/monitoring_contract.json
  contracts/pipeline_engineering_contract.json
  contracts/runbook.md
  data/trace_spans.csv
  ops/monitor_dataops.py
  ops/inspect_pipeline_engineering.py
  output/monitoring_report.json
  output/slo_scorecard.csv
  output/alerts.md
  output/operational_decision.md
  output/lineage_event.json
  output/trace_correlation_report.json
  output/trace_scorecard.csv
  output/incident_postmortem.md

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/monitor_dataops.py --write
cat output/operational_decision.md
cat output/alerts.md
python3 -m json.tool output/monitoring_report.json
python3 ops/inspect_pipeline_engineering.py --write
cat output/incident_postmortem.md
python3 -m json.tool output/trace_correlation_report.json

Qué deberías ver

El estado global queda en block porque la ventana 2026-06-08 incumple el contrato:

Estado global: block
2026-06-07: pass
2026-06-08: block

Los artefactos importantes son:

ArchivoQué demuestra
monitoring_report.jsonReporte completo para CI o pipeline.
slo_scorecard.csvScorecard por ventana con SLIs principales.
alerts.mdLectura humana de señales y umbrales.
operational_decision.mdDecisión operativa defendible.
lineage_event.jsonRun, inputs, outputs y hashes.
runbook.mdQué hacer cuando la ventana falla.
trace_correlation_report.jsonQué eventos tienen traza, qué spans faltan y qué spans superan SLO.
trace_scorecard.csvTabla por evento para depurar la operación.
incident_postmortem.mdPostmortem generado desde evidencia, no desde memoria.

La segunda herramienta (inspect_pipeline_engineering.py) debe detectar:

SeñalValor esperadoLectura
Eventos revisados20Todas las decisiones de producción entran en el análisis.
Eventos que requieren detalle de spans5No todo evento necesita spans completos, pero los críticos sí.
Eventos sin traza1p013 no se puede investigar bien.
Eventos con spans obligatorios faltantes1p017 no emitió todo el recorrido esperado.
Claves de idempotencia duplicadas0Reintentar no duplicó decisiones en este dataset.
Estado de ingenieríablockLa ventana no está lista para automatizar más.

Cómo lo adaptarías

Si tu sistema es...Cambia esto
Un RAG documentalSlices por fuente, versión de documento, idioma y permisos.
Un clasificador de ticketsSlices por producto, canal, equipo y severidad.
Un agente con herramientasSlices por herramienta, estado, tipo de tarea y resultado.
Un modelo localAñade memoria, batch, saturación y versión de runtime.
Una API cloudAñade proveedor, región, coste, latencia y modelo servido.

Qué entregaría un alumno

  1. operational_decision.md generado.
  2. slo_scorecard.csv interpretado con sus palabras.
  3. Un cambio razonado en monitoring_contract.json.
  4. Un cambio razonado en pipeline_engineering_contract.json.
  5. Un nuevo SLI por slice para su proyecto.
  6. Una adaptación de runbook.md con owner, acción y criterio de salida.
  7. Una explicación de por qué la ventana 2026-06-08 no debe usarse para aumentar automatización.
  8. Un postmortem que convierta el fallo en una acción verificable.
  9. Un test nuevo que habría impedido repetir el problema.

Cómo encaja todo

Este mapa se lee como continuidad del facsímil. Los capítulos 01 a 05 construyeron contrato, calidad, split, representación y slices. Este capítulo convierte esas piezas en operación: ventanas, SLIs, SLOs, drift, trazas, linaje y runbooks.

La decisión que enseña no es “qué modelo elegir”. Es más básica y más profesional: qué ventana de producción es apta para seguir tomando decisiones y cuál exige revisión. Después, el capítulo 07 usará esta evidencia para análisis aplicado, experimentos y causalidad.

graph TD
    subgraph "Este capítulo"
        WINDOW["Ventana de producción"]
        RUN["Run versionada"]
        TEL["Telemetría<br/>logs · métricas · trazas"]
        DRIFT["Drift"]
        SLO["SLI · SLO"]
        GATE["Gate operativo"]
        RUNBOOK["Runbook"]
        POST["Postmortem"]
    end
    subgraph "Mismo facsímil"
        C01["Contrato y linaje<br/>cap. 1"]
        C02["Calidad<br/>cap. 2"]
        C03["Referencia de test<br/>cap. 3"]
        C04["Versiones de features<br/>cap. 4"]
        C05["Slices críticos<br/>cap. 5"]
        C07["Experimentos<br/>cap. 7"]
    end
    subgraph "Otros facsímiles"
        OBS["Observabilidad<br/>fasc. 6"]
        CI["Operación y CI<br/>fasc. 6"]
        EVAL["Evaluación<br/>fasc. 7"]
        GOV["Gobernanza<br/>fasc. 9"]
    end

    C01 -->|"aporta hashes"| RUN
    C02 -->|"aporta gates"| GATE
    C03 -->|"da referencia"| DRIFT
    C04 -->|"versiona señal"| RUN
    C05 -->|"matiza"| SLO
    OBS -->|"aporta señales"| TEL

    WINDOW -->|"se ejecuta como"| RUN
    RUN -->|"emite"| TEL
    TEL -->|"mide"| SLO
    WINDOW -->|"se compara con"| DRIFT
    DRIFT -->|"alimenta"| SLO
    SLO -->|"decide"| GATE
    GATE -->|"activa"| RUNBOOK
    RUNBOOK -->|"cierra en"| POST

    GATE -->|"prepara evidencia"| C07
    GATE -->|"se automatiza en"| CI
    TEL -->|"explica degradaciones"| EVAL
    POST -->|"deja controles"| GOV

    style WINDOW fill:#F5F5F5,stroke:#000000,stroke-width:2
    style RUN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style TEL fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DRIFT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style SLO fill:#F5F5F5,stroke:#000000,stroke-width:2
    style GATE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style RUNBOOK fill:#F5F5F5,stroke:#000000,stroke-width:2
    style POST fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C01 stroke-dasharray: 5 5
    style C02 stroke-dasharray: 5 5
    style C03 stroke-dasharray: 5 5
    style C04 stroke-dasharray: 5 5
    style C05 stroke-dasharray: 5 5
    style C07 stroke-dasharray: 5 5
    style OBS stroke-dasharray: 5 5
    style CI stroke-dasharray: 5 5
    style EVAL stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
DataOpsOperar datos como producto versionado, verificable y monitorizable.
PipelineSecuencia reproducible de pasos que transforma entradas en artefactos.
RunEjecución concreta con inputs, outputs, versiones, hashes y estado.
DriftCambio medible entre referencia y producción.
SLIIndicador medible.
SLOObjetivo sobre un SLI.
Presupuesto de errorMargen permitido antes de frenar cambios.
Trace IDIdentificador que permite seguir una operación por el sistema.
RunbookGuía de acción cuando una alerta o gate falla.
Gate operativoRegla que convierte señales en pass, review o block.
IdempotenciaPropiedad que permite repetir una operación sin duplicar efectos.
BackfillReprocesado de ventanas antiguas con versión controlada de datos, código y contrato.
ReplayReejecución de una ventana para reproducir o comparar una decisión.
SpanTramo de una traza que representa un paso medible de una operación.
Contract testTest que verifica que productor y consumidor cumplen el contrato pactado.
PostmortemDocumento técnico que convierte una incidencia en acciones verificables.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Mirar solo métricas globalesLa media da sensación de control.Medir ventanas y slices críticos.
Confundir drift con fallo automáticoUn cambio puede ser esperado.Revisar causa, contexto y consecuencia.
No exigir trace_idParece detalle de logging.Tratar trazabilidad como SLO bloqueante.
Tener alerta sin runbookEl dashboard avisa, pero nadie sabe qué hacer.Escribir owner, acción y criterio de salida.
Reentrenar con producción rotaSe intenta arreglar rápido.Bloquear ventanas con gate block.
Reintentar sin idempotenciaSe piensa que retry siempre es inocente.Definir idempotency_key antes de automatizar retries.
Hacer backfill sin congelar versiónParece solo recalcular.Guardar datos, código, contrato, política y hashes.
Escribir postmortem sin test nuevoSe documenta el problema, pero no se evita repetirlo.Cada postmortem debe cerrar con una defensa verificable.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Qué diferencia hay entre pipeline y run?
  2. ¿Por qué una ventana corta puede contar más que una media larga?
  3. ¿Qué mide missing_trace_rate y por qué puede bloquear?
  4. ¿Qué diferencia hay entre log, métrica y traza?
  5. ¿Qué mide la distancia de variación total?
  6. ¿Qué mide PSI y por qué no se lee sin contexto?
  7. ¿Qué es un SLI?
  8. ¿Qué es un SLO?
  9. ¿Qué significa presupuesto de error?
  10. ¿Por qué 2026-06-08 queda en block en el kit?
  11. ¿Qué hace lineage_event.json?
  12. ¿Qué debe contener un runbook útil?
  13. ¿Qué slices críticos monitorizarías en tu proyecto?
  14. ¿Por qué no deberías reentrenar con una ventana rota?
  15. ¿Por qué un retry sin idempotencia puede duplicar efectos?
  16. ¿Qué diferencia hay entre backfill y replay?
  17. ¿Qué comprobaría un contract test de trazas?
  18. ¿Qué acción correctiva añadirías al postmortem del kit?
  19. ¿Cómo conecta este capítulo con análisis aplicado?

En resumen

IdeaQué te llevas
DataOps es operación, no decoración.Contratos, runs, hashes, gates y runbooks sostienen el sistema.
El drift abre investigación.Un cambio de distribución no se interpreta sin contexto ni consecuencia.
Los SLOs deben ser medibles.latency_p95_ms <= 650 es operativo; “que vaya bien” no lo es.
La trazabilidad puede bloquear.Sin trace_id, no hay investigación fiable.
Los slices siguen vivos en producción.Lo que se auditó en test debe monitorizarse después.
Un gate protege decisiones.Evita aumentar automatización o reentrenar con ventanas rotas.
Los retries necesitan idempotencia.Repetir una tarea no debe duplicar decisiones ni alertas.
Un postmortem debe crear una defensa.La acción correctiva se traduce en test, contrato o gate.

Para saber más

Baylor, D., Breck, E., Cheng, H.-T., Fiedel, N., Foo, C. Y., Haque, Z., Haykal, S., Ispir, M., Jain, V., Koc, L., Koo, C. Y., Lew, L., Mewald, C., Modi, A. N., Polyzotis, N., Ramesh, S., Roy, S., Whang, S. E., Wicke, M., Wilkiewicz, J., Zhang, X. y Zinkevich, M. (2017). TFX: A TensorFlow-Based Production-Scale Machine Learning Platform. KDD, 1387-1395. DOI

Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction. IEEE Big Data, 1123-1132. Google Research

Apache Airflow. (2026). Core Concepts. Documentación

Dagster. (2026). Dagster documentation. Documentación

dbt Labs. (2026). Model contracts. Documentación

Evidently AI. (2026). Data Drift Documentation. Documentación

Great Expectations. (2026). Expectations Overview. Documentación

OpenLineage. (2026). OpenLineage Documentation. Documentación

OpenTelemetry. (2026). Logs. Documentación

OpenTelemetry. (2026). Metrics. Documentación

OpenTelemetry. (2026). Traces. Documentación

Prefect. (2026). Deployments. Documentación

Prefect. (2026). How to automatically rerun your workflow when it fails. Documentación

Prometheus. (2026). Metric and label naming. Documentación

Sculley, D. et al. (2015). Hidden Technical Debt in Machine Learning Systems. NeurIPS. Paper

Notas

  1. Sculley, D. et al. (2015). Hidden Technical Debt in Machine Learning Systems. NeurIPS. https://papers.nips.cc/paper_files/paper/2015/hash/86df7dcfd896fcaf2674f757a2463eba-Abstract.html

  2. Baylor, D. et al. (2017). TFX: A TensorFlow-Based Production-Scale Machine Learning Platform. KDD, 1387-1395. https://doi.org/10.1145/3097983.3098021

  3. Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction. IEEE Big Data, 1123-1132. https://research.google/pubs/pub46555/

  4. OpenLineage. (2026). OpenLineage Documentation. https://openlineage.io/docs/. Consultado el 7 de junio de 2026.

  5. OpenTelemetry. (2026). Traces. https://opentelemetry.io/docs/concepts/signals/traces/. Consultado el 7 de junio de 2026.

  6. OpenTelemetry. (2026). Metrics. https://opentelemetry.io/docs/concepts/signals/metrics/. Consultado el 7 de junio de 2026.

  7. OpenTelemetry. (2026). Logs. https://opentelemetry.io/docs/concepts/signals/logs/. Consultado el 7 de junio de 2026.

  8. Apache Airflow. (2026). Core Concepts. https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/. Consultado el 7 de junio de 2026.

  9. Dagster. (2026). Dagster documentation. https://docs.dagster.io/getting-started. Consultado el 7 de junio de 2026.

  10. Prefect. (2026). Deployments. https://docs.prefect.io/concepts/deployments. Consultado el 7 de junio de 2026.

  11. Prefect. (2026). How to automatically rerun your workflow when it fails. https://docs.prefect.io/v3/how-to-guides/workflows/retries. Consultado el 7 de junio de 2026.

  12. dbt Labs. (2026). Model contracts. https://docs.getdbt.com/docs/mesh/govern/model-contracts. Consultado el 7 de junio de 2026.

  13. Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction. IEEE Big Data, 1123-1132. https://research.google/pubs/pub46555/

  14. Prometheus. (2026). Metric and label naming. https://prometheus.io/docs/practices/naming/. Consultado el 7 de junio de 2026.

Capítulo 07

Facsímil 8 · La ciencia de los datos

Capítulo 07: Análisis aplicado: experimentos, causalidad y decisión

Qué deberías poder hacer al terminar

En el capítulo anterior aprendimos a operar datos: ventanas, drift, trazas, SLOs, gates y postmortems. Eso nos protege de tomar decisiones con datos rotos. Ahora damos el siguiente paso: decidir si una acción cambia algo.

Esta es una de las fronteras más importantes para cualquier persona que trabaja con IA. Un modelo puede predecir que un estudiante no resolverá su trámite a tiempo. Pero otra pregunta mucho más difícil es: ¿qué acción aumenta realmente la probabilidad de resolverlo? ¿Enviar una plantilla? ¿Escalarlo? ¿Cambiar el orden de cola? ¿Dar un mensaje más claro? ¿Nada?

Al terminar deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Separar predicción de intervención.No usas un score predictivo como prueba de efecto causal.
Escribir una pregunta causal.Distingues tratamiento, control, resultado, unidad y población.
Diseñar un experimento mínimo.Defines asignación, métrica primaria, guardrails, tamaño y criterio de decisión.
Leer un A/B test como artefacto de ingeniería.Buscas SRM, balance, slices, intervalos y trazabilidad.
Diseñar una plataforma mínima de experimento.Separas flag, contexto, exposición, métricas, análisis y release gate.
Calcular readiness estadístico.Escribes MDE, alpha, potencia, muestra y política de peeking.
Entender ATE, CATE y uplift.Sabes cuándo importa el efecto medio y cuándo importa el efecto por segmento.
Auditar datos observacionales con cuidado.No cierras una conclusión causal si falta solapamiento o hay confounding.
Generar una decisión reproducible.Dejas reportes, scorecards y una decisión versionada.

La frase central:

Predecir responde qué puede pasar. Causalidad responde qué cambiaría si actuamos.

La escena: el descuento que parecía funcionar

Imagina que tenemos un asistente para soporte académico. El sistema predice qué casos tienen más probabilidad de resolverse tarde. Un equipo propone enviar una plantilla guiada a ciertos casos antes de que el operador responda. Al mirar datos históricos, los casos que recibieron plantilla parecen resolverse mucho más.

La tentación es decir: “perfecto, la plantilla funciona”. Pero quizá la plantilla se mandaba sobre todo a casos de matrícula, que ya tenían más probabilidad de resolverse. O quizá se mandaba a estudiantes con expedientes más completos. O quizá los operadores más expertos usaban más la plantilla y también resolvían mejor sin ella.

El análisis aplicado empieza cuando frenamos esa conclusión rápida y escribimos la pregunta correcta:

Pregunta flojaPregunta útil
¿Quién resuelve mejor?¿Qué cambia si asignamos la plantilla?
¿Qué variable predice resolución?¿Qué acción modifica la resolución?
¿La gente con plantilla resolvió más?¿Casos comparables resolverían más con plantilla que sin plantilla?
¿El modelo lo explica?¿El diseño permite estimar el efecto?

Qué no es análisis causal

Análisis causal no es mirar una correlación y escribir una historia convincente. Las historias pueden ayudar a formular hipótesis, pero no convierten una asociación en efecto.

Tampoco es una capa que arregle datos malos por sí sola. Si la asignación está rota, si el resultado se mide tarde, si cambió el producto a mitad del experimento o si falta trazabilidad, la fórmula no salva la decisión. Por eso este capítulo depende tanto del capítulo 06 sobre DataOps.

Y no es interpretabilidad. SHAP, importancia de variables, PDP, ICE o trazas pueden ayudarnos a preguntar mejor, pero no prueban por sí solas que una acción cause un resultado. Si una variable aparece como importante, quizá sea causa, quizá sea proxy, quizá sea síntoma o quizá esté recogiendo una regla de negocio.

Qué sí es análisis aplicado para IA

Análisis aplicado es convertir datos en una decisión defendible. En IA suele aparecer en tres momentos:

MomentoPreguntaEjemplo
Antes de publicar¿Este cambio mejora algo real?Nuevo prompt, nuevo ranking, nueva política de revisión.
Después de publicar¿La mejora se mantiene?Ventana post-release comparada con control o holdout.
Al priorizar acciones¿Dónde conviene intervenir?Casos donde una plantilla cambia la resolución, no donde ya iba a resolverse.

Rubin formalizó el enfoque de resultados potenciales: para cada unidad imaginamos el resultado bajo tratamiento y bajo control, aunque solo observemos uno.1 Holland popularizó la idea de que la inferencia causal se enfrenta a un problema fundamental: no podemos observar simultáneamente ambos resultados potenciales para la misma unidad.2 Pearl desarrolló un marco gráfico y el operador do para razonar sobre intervención, ajuste y supuestos causales.3

Fecha de corte: 7 de junio de 2026. Fuentes consultadas ese día: literatura clásica de causalidad, Microsoft ExP, CUPED, DoWhy, EconML, OpenFeature, LaunchDarkly, Statsig, GrowthBook y trabajos sobre calidad de experimentos a escala. Lo estable es la diferencia entre asociación, intervención, contrafactual y decisión. Lo que cambia son herramientas, plataformas y automatizaciones.

Predicción e intervención no responden lo mismo

La confusión más habitual cabe en dos expresiones parecidas:

P(YX=x)P(Y \mid X=x) P(Ydo(X=x))P(Y \mid do(X=x))
SímboloSignificadoEjemplo
YYResultado que medimos.Caso resuelto.
XXVariable o acción que miramos.Recibir plantilla.
xxValor concreto de XX.plantilla = sí.
P(YX=x)P(Y \mid X=x)Probabilidad observada dado que XX ocurrió.Resolución entre casos que recibieron plantilla.
do(X=x)do(X=x)Intervención que fija XX desde el diseño.Asignar plantilla por experimento.
P(Ydo(X=x))P(Y \mid do(X=x))Probabilidad bajo intervención.Resolución si forzamos plantilla en casos comparables.

La primera expresión es predictiva u observacional. Nos dice qué pasa entre casos donde XX aparece. La segunda es causal. Nos pregunta qué pasa si intervenimos.

Para un ingeniero de IA, la diferencia es práctica:

Si haces...Necesitas...Por qué
Ordenar casos por riesgoPredicción bien evaluada.Quieres anticipar qué ocurrirá.
Cambiar una políticaEfecto causal o experimento.Quieres saber qué cambia por actuar.
Elegir a quién enviar una acciónUplift o CATE.No basta saber quién tiene más probabilidad de éxito.
Publicar un cambio de productoDiseño experimental y guardrails.Debes proteger métricas secundarias y operación.

El problema de los resultados potenciales

La notación de resultados potenciales escribe dos mundos para cada unidad:

Yi(1)Y_i(1) Yi(0)Y_i(0)
SímboloSignificadoEjemplo
iiUnidad analizada.Ticket u014.
Yi(1)Y_i(1)Resultado de la unidad si recibe tratamiento.Resolvería con plantilla.
Yi(0)Y_i(0)Resultado de la unidad si recibe control.Resolvería sin plantilla.
11Tratamiento activo.treatment.
00Control.control.

El problema es que para una misma unidad solo observamos una de las dos columnas. Si u014 recibió plantilla, vemos Y014(1)Y_{014}(1), pero no vemos Y014(0)Y_{014}(0). Ese resultado no observado es el contrafactual.

Por eso no medimos el efecto individual real de cada caso. Estimamos efectos agregados bajo supuestos:

ATE=E[Y(1)Y(0)]ATE = E[Y(1)-Y(0)]
SímboloSignificadoEjemplo
ATEATEEfecto medio del tratamiento.+0.25 en tasa de resolución.
E[]E[\cdot]Esperanza o promedio poblacional.Media sobre los casos del experimento.
Y(1)Y(1)Resultado bajo tratamiento.Resolver con plantilla.
Y(0)Y(0)Resultado bajo control.Resolver sin plantilla.

Si aleatorizamos bien, el grupo control actúa como aproximación del mundo sin tratamiento y el grupo tratamiento como aproximación del mundo con tratamiento.

Un A/B test como sistema de ingeniería

Kohavi, Longbotham, Sommerfield y Henne trataron los experimentos online como práctica central para tomar decisiones en la web, pero también documentaron problemas habituales de diseño, métrica y ejecución.4 Microsoft ExP describe una plataforma de experimentación con portal, servicio de ejecución, procesamiento de logs y análisis como piezas separadas de una arquitectura escalable.5

Esto es importante: un A/B test no es una tabla con control y treatment. Es un sistema.

PiezaPregunta de ingenieríaFallo típico
Unidad¿Qué se asigna?Mezclar usuario, sesión y ticket.
Asignación¿Cómo se decide control o tratamiento?Reparto roto o no reproducible.
Persistencia¿La unidad conserva variante?Un usuario cambia de grupo entre eventos.
Métrica primaria¿Qué decide el experimento?Optimizar una proxy cómoda.
Guardrails¿Qué no puede empeorar?Mejorar resolución subiendo coste o latencia.
Logging¿Qué evento demuestra exposición?Medir casos que nunca vieron la intervención.
Análisis¿Qué estimador y regla de parada usamos?Mirar cada día y parar cuando conviene.
Decisión¿Qué hacemos con el resultado?Publicar sin contrato ni evidencia.

Plan de análisis antes de tocar resultados

Un experimento serio se empieza escribiendo antes qué se va a mirar. Esto no es solemnidad académica: es protección contra cambiar la pregunta cuando ya hemos visto la respuesta.

El kit incluye analysis_plan.json. Ese archivo fija hipótesis, población, tratamiento, control, métrica primaria, guardrails, slices a reportar, exclusiones y reglas de decisión. También incluye metric_catalog.json, porque una métrica sin definición estable se convierte en una palabra elástica.

Pieza del planPregunta que respondeEjemplo
Hipótesis¿Qué creemos que cambiará?La plantilla guiada aumenta resolución a 7 días.
Población¿Sobre quién vale la decisión?Casos académicos con trazabilidad completa.
Unidad¿Qué se asigna y analiza?unit_id.
Tratamiento¿Qué cambia exactamente?Plantilla guiada + contexto documental revisado.
Control¿Contra qué comparamos?Flujo actual.
Métrica primaria¿Qué decide el experimento?resolved.
Ventana¿Cuándo madura la métrica?day_7.
Guardrails¿Qué no puede empeorar?Feedback, latencia, coste, cita válida.
Exclusiones¿Qué se elimina antes del análisis?Sin exposure event, fallback no etiquetado, unidad inestable.
Regla de decisión¿Qué significa pass, review o block?Publicar solo con readiness y guardrails en pass.

El detalle importante es “antes”. Si primero miramos el resultado y luego elegimos la métrica que más favorece a la variante, no estamos evaluando; estamos buscando una justificación.

validate_experiment_design.py revisa que el plan, catálogo y contrato de flag encajen. No calcula efecto. Hace algo anterior y muy de ingeniería: comprueba si el experimento está suficientemente definido para poder medir.

El catálogo de métricas cumple otra función: evita que dos personas usen la misma palabra para cosas distintas. En un proyecto real, resolved no puede significar “el operador cerró el ticket” un día y “el estudiante no volvió a escribir” al siguiente. Si la métrica decide publicación, tiene que tener unidad, ventana, dirección y definición operativa.

Campo en metric_catalog.jsonQué obliga a decidirEjemplo del kit
nameNombre estable para código, SQL y reporte.resolved.
typePapel de la métrica.primary, guardrail, diagnostic.
unitGrano de medición.unit_id.
windowCuándo se considera madura.day_7 o exposure.
directionQué significa mejorar.higher_is_better o lower_is_better.
definitionInterpretación que debe sobrevivir al cambio de equipo.Caso resuelto correctamente dentro de la ventana observada.

Esto parece burocrático hasta que falla. Si un experimento mejora answer_accepted pero empeora citation_valid, o si latency_ms se mide desde puntos distintos del backend, no tienes una decisión: tienes una conversación interminable. El catálogo corta esa ambigüedad antes de ejecutar.

Plataforma experimental para sistemas de IA

Cuando un equipo de IA madura, el experimento deja de vivir en una hoja de cálculo. Se convierte en una plataforma con piezas separadas. OpenFeature define una especificación abierta para feature flags con una API común y proveedores intercambiables.6 La especificación de evaluation context describe el contexto que viaja con una evaluación de flag, incluyendo un targeting key que identifica la unidad sobre la que se evalúa la variante.7

La idea que nos interesa no es la marca de la herramienta. Es el contrato de plataforma:

ComponenteQué haceQué debe quedar trazado
Feature flagDecide qué variante recibe una unidad.flag_key, versión, proveedor y regla.
Evaluation contextAporta atributos para evaluar la flag.targeting_key, segmento, región, canal, entorno.
Assignment serviceHace persistente la variante.Unidad, variante, timestamp, hash de regla.
Exposure eventRegistra que la unidad vio la variante.Evento de exposición, no solo asignación teórica.
Metrics layerDefine métricas con una semántica estable.Nombre, ventana, unidad, filtros, owner.
WarehouseUne exposición, eventos y métricas.Tablas, particiones, linaje y retrasos de datos.
Analysis serviceCalcula efecto, intervalos, slices y guardrails.Método, parámetros, fecha, versión de contrato.
Release gateConvierte análisis en acción.pass, review, block, rollout o rollback.

LaunchDarkly describe experimentación conectando métricas a flags y configuraciones para medir cambios en comportamiento, y menciona A/A testing para validar instrumentación antes de un A/B real.8 GrowthBook se presenta como plataforma open source de feature flags y experimentación, con énfasis en métricas sobre datos existentes y transparencia de consultas.9 Statsig documenta opciones avanzadas como duración de asignación, periodo de análisis, covariables, sequential testing y correcciones por múltiples comparaciones.10

En IA, esta arquitectura tiene matices propios:

Caso de IAQué se experimentaRiesgo de ingeniería
Nuevo promptVariante textual o plantilla.La exposición debe registrar versión exacta del prompt.
Nuevo modeloModelo, proveedor o configuración.Latencia, coste y fallback importan tanto como calidad.
RAGRetriever, reranker, chunking o fuente.Cambia el contexto recuperado, no solo la respuesta.
AgentePolítica de herramientas o aprobación.La unidad puede ser tarea, conversación o usuario.
RecomendaciónRanking o regla de diversidad.Un usuario puede afectar inventario, cola o experiencia de otros.
Moderación de colaUmbral o política de revisión.Guardrails humanos y operativos son obligatorios.

La pregunta de ingeniería no es “¿qué librería uso?”. Es esta:

¿Puedo reconstruir qué unidad recibió qué variante,
con qué contexto, bajo qué versión, y qué métricas maduraron después?

Si la respuesta es no, todavía no hay experimento publicable.

Unidad, exposición e interferencia

La unidad de asignación es una decisión de diseño. Si asignas por sesión, pero el usuario vuelve varias veces, puede ver control y tratamiento. Si asignas por ticket, pero el operador aprende de una variante y cambia su comportamiento en otros tickets, hay contaminación entre unidades. Si asignas por empresa, tendrás menos unidades pero menos mezcla entre grupos.

UnidadSirve cuandoCuidado
UsuarioLa experiencia se mantiene en el tiempo.Varias sesiones deben conservar variante.
SesiónLa intervención dura solo una visita.No sirve para métricas que maduran por usuario.
TicketCada caso es independiente.Un mismo operador puede influir varios tickets.
EmpresaHay efecto compartido entre usuarios.Menos muestra y más varianza.
ConversaciónAgentes o asistentes conversacionales.Una conversación puede contener varias tareas.

La exposición también importa. Asignar una variante no significa que la unidad la haya recibido. En un sistema de IA puede haber fallback, timeout, caché, error de proveedor, ruta alternativa o una regla de permisos que impide mostrar la variante. Por eso el contrato del kit exige experiment_exposure: una decisión experimental se analiza sobre unidades expuestas, no solo asignadas.

Interferencia significa que una unidad puede afectar el resultado de otra. En producto digital aparece en marketplaces, colas, rankings, soporte compartido y sistemas con capacidad limitada. En IA aparece también cuando un agente consume herramientas compartidas, cambia una cola humana, modifica documentos o prioriza casos que compiten por el mismo recurso. Si hay interferencia fuerte, el A/B clásico por usuario puede quedarse corto y quizá necesites asignar por clúster, equipo, cola o ventana temporal.

El kit incluye cluster_interference_events.csv. La idea es sencilla: si dentro de un mismo equipo conviven control y tratamiento, y el operador aprende de la variante nueva, el control puede contaminarse. En ese caso quizá la unidad correcta no sea unit_id, sino cluster_id.

SeñalLectura
Cluster con control y treatment mezcladosPosible contaminación de comportamiento.
Mismo operador en ambas variantesPuede aprender de treatment y aplicarlo a control.
Cola compartidaUna variante puede cambiar tiempos de la otra.
Recurso limitadoLa mejora de un grupo puede desplazar capacidad.

Una regla práctica:

Si las unidades comparten operador, inventario, cola, aula, empresa o herramienta limitada,
pregunta si deberías asignar por clúster.

Si asignas por clúster, la pregunta cambia ligeramente. Ya no preguntas solo por tickets individuales; preguntas por equipos, empresas, aulas o colas completas. Una forma pedagógica de verlo es calcular primero el resultado medio de cada clúster y después comparar clústeres:

ATE^cluster=1KTkTYˉk1KCkCYˉk\widehat{ATE}_{cluster} = \frac{1}{K_T}\sum_{k \in T}\bar{Y}_k - \frac{1}{K_C}\sum_{k \in C}\bar{Y}_k
SímboloSignificadoEjemplo
kkClúster completo.team_a, team_b, team_c.
Yˉk\bar{Y}_kResultado medio dentro del clúster kk.Resolución media del equipo.
KTK_TNúmero de clústeres en tratamiento.Equipos asignados a la variante nueva.
KCK_CNúmero de clústeres en control.Equipos asignados al flujo actual.

La ventaja es que reduces contaminación entre unidades. El precio es que tienes menos observaciones efectivas: cien tickets dentro de tres equipos no equivalen a cien unidades independientes si el equipo comparte operador, cola y aprendizaje. Por eso la decisión de unidad no es un detalle técnico pequeño; cambia la potencia, el coste y la credibilidad del experimento.

El estimador básico en un A/B test es diferencia de medias:

ATE^=YˉTYˉC\widehat{ATE} = \bar{Y}_{T} - \bar{Y}_{C}
SímboloSignificadoEjemplo
ATE^\widehat{ATE}Estimación del efecto medio.0.25.
YˉT\bar{Y}_{T}Media del resultado en tratamiento.0.833333 resueltos.
YˉC\bar{Y}_{C}Media del resultado en control.0.583333 resueltos.
TTGrupo tratamiento.Casos con plantilla guiada.
CCGrupo control.Casos sin plantilla nueva.

En el kit, el efecto observado es:

ATE^=0.8333330.583333=0.25\widehat{ATE} = 0.833333 - 0.583333 = 0.25

Esto suena fuerte, pero no basta. Hay que mirar incertidumbre:

SE(ATE^)=sT2nT+sC2nCSE(\widehat{ATE}) = \sqrt{ \frac{s_T^2}{n_T} + \frac{s_C^2}{n_C} }
SímboloSignificadoEjemplo
SESEError estándar de la estimación.0.186339.
sT2s_T^2Varianza del resultado en tratamiento.Varianza de resolved en treatment.
sC2s_C^2Varianza del resultado en control.Varianza de resolved en control.
nTn_TNúmero de unidades en tratamiento.12.
nCn_CNúmero de unidades en control.12.

Y un intervalo aproximado:

IC95%=ATE^±1.96SE(ATE^)IC_{95\%} = \widehat{ATE} \pm 1.96 \cdot SE(\widehat{ATE})
SímboloSignificadoEjemplo
IC95%IC_{95\%}Intervalo de confianza aproximado al 95%.[-0.115224, 0.615224].
1.961.96Multiplicador normal aproximado para 95%.Valor estándar.
ATE^\widehat{ATE}Efecto estimado.0.25.
SESEError estándar.0.186339.

La lectura honesta es: señal positiva, todavía imprecisa. Publicar automáticamente sería precipitado. Repetir o ampliar muestra es más defendible.

Calidad del experimento antes de mirar el resultado

Antes de celebrar un efecto, un ingeniero revisa si el experimento merece confianza. En el kit lo hacemos con tres controles: SRM, balance y guardrails.

SRM significa sample ratio mismatch: el reparto observado no coincide con el reparto esperado. Si diseñamos 50/50 y aparece 70/30, quizá la asignación, tracking o filtrado está fallando. Nie y colaboradores describen validaciones automáticas de aleatorización y detección de SRM en plataformas de experimentación a escala.11

Una comprobación clásica usa chi-cuadrado:

χ2=gG(OgEg)2Eg\chi^2 = \sum_{g \in G} \frac{(O_g-E_g)^2}{E_g}
SímboloSignificadoEjemplo
χ2\chi^2Estadístico de desajuste.0.0.
GGGrupos del experimento.control, treatment.
OgO_gConteo observado en grupo gg.12.
EgE_gConteo esperado en grupo gg.12.

El balance revisa si las covariables previas al tratamiento son parecidas. Si los grupos ya eran distintos antes de actuar, el efecto puede mezclarse con composición.

Una medida simple es la diferencia de medias estandarizada:

SMD=XˉTXˉCspooledSMD = \frac{\bar{X}_T-\bar{X}_C}{s_{pooled}}
SímboloSignificadoEjemplo
SMDSMDDiferencia estandarizada entre grupos.0.0.
XˉT\bar{X}_TMedia de covariable previa en tratamiento.Tareas previas en treatment.
XˉC\bar{X}_CMedia de covariable previa en control.Tareas previas en control.
spooleds_{pooled}Desviación típica combinada.Variación compartida entre grupos.

Los guardrails son métricas que no deciden la victoria, pero sí pueden impedir publicar. En el kit, la intervención mejora resolución, pero vigilamos coste, latencia y feedback negativo.

Tamaño muestral, MDE y peeking

El error más común al enseñar A/B testing es quedarse en la fórmula del efecto y no hablar de cuánta muestra hace falta para medirlo. Un experimento con 12 unidades por variante puede ser excelente para aprender el mecanismo, pero no para tomar una decisión global si queremos detectar un cambio pequeño.

El MDE (minimum detectable effect) es el efecto mínimo que el experimento está diseñado para detectar con una potencia determinada. Para dos grupos del mismo tamaño y una métrica aproximadamente continua, una aproximación útil es:

n2(z1α/2+z1β)2σ2δ2n \approx \frac{ 2(z_{1-\alpha/2}+z_{1-\beta})^2\sigma^2 }{ \delta^2 }
SímboloSignificadoEjemplo
nnUnidades necesarias por variante.1530 para el MDE del kit.
α\alphaProbabilidad aceptada de falso positivo.0.05.
1β1-\betaPotencia: probabilidad de detectar el efecto si existe.0.8.
z1α/2z_{1-\alpha/2}Cuantil normal para el nivel de confianza.1.959964.
z1βz_{1-\beta}Cuantil normal para la potencia.0.841621.
σ2\sigma^2Varianza aproximada de la métrica.Para binaria: p(1p)p(1-p).
δ\deltaMDE que queremos detectar.0.05.

Para una métrica binaria como resolved, usamos:

σ2=p(1p)\sigma^2 = p(1-p)
SímboloSignificadoEjemplo
ppTasa base esperada.0.58.
1p1-pComplemento de la tasa base.0.42.
σ2\sigma^2Varianza binaria aproximada.0.2436.

El kit calcula:

ParámetroValor
Baseline0.58
Alpha0.05
Potencia0.8
MDE planificado0.05
n actual por variante12
n recomendado por variante1530
MDE aproximado con n actual0.564504

Eso explica por qué el capítulo deja el experimento en review: la señal observada es positiva, pero la muestra solo permite detectar efectos enormes. Para decidir con un MDE pequeño, necesitamos más unidades.

Peeking es mirar resultados muchas veces y decidir cuando la gráfica parece favorable. Statsig recomienda configurar sequential testing cuando se quiere evitar que mirar varias veces aumente falsos positivos.12 En un contrato serio, la regla debe estar escrita antes:

DecisiónQué escribir antes de empezar
Cuándo mirarFecha final, número de looks o regla secuencial.
Qué métrica decideUna primaria, no cinco primarias cambiantes.
Qué guardrails bloqueanUmbrales concretos y dirección.
Qué pasa si queda reviewAmpliar muestra, repetir ventana o limitar rollout.
Qué no se permiteCambiar metodología al ver el resultado.

También conviene ejecutar A/A antes de A/B. En A/A, ambas variantes se comportan igual. Si el sistema detecta efecto donde no debería, tenemos problema de instrumentación, asignación, logging o análisis. Es una prueba humilde y muy de ingeniería: antes de medir impacto, comprobamos que el contador mide.

Métricas, jerarquía y comparaciones múltiples

Otro tropiezo habitual: medir muchas cosas y quedarse con la que sale bonita. Si miras diez métricas, cinco slices y tres ventanas, alguna diferencia llamativa aparecerá por azar. Por eso el plan debe separar métrica primaria, guardrails y diagnósticas.

TipoDecideEjemploCómo se interpreta
Primariaresolved_day_7.Una, fijada antes.
GuardrailBloquealatency_ms, cost_eur, citation_valid.No gana el experimento, pero puede impedir publicar.
DiagnósticaExplicaretrieval_precision.Ayuda a depurar, no decide sola.
SliceMatizasegment=becas.Señal de heterogeneidad o riesgo.
Ventana secundariaComplementaday_1, day_30.Ayuda a maduración, no reemplaza primaria sin plan.

Si declaramos muchos resultados como “primarios”, sube el riesgo de falso descubrimiento. Una corrección conservadora es Bonferroni:

α\*=αm\alpha^\* = \frac{\alpha}{m}
SímboloSignificadoEjemplo
α\*\alpha^\*Umbral corregido por número de pruebas.0.01 si α=0.05\alpha=0.05 y m=5m=5.
α\alphaUmbral original.0.05.
mmNúmero de pruebas consideradas.5 guardrails o hipótesis.

Benjamini y Hochberg propusieron controlar la tasa de descubrimientos falsos, menos conservadora que Bonferroni cuando se exploran muchas hipótesis.13

En este libro la regla pedagógica es clara:

Una métrica primaria.
Guardrails bloqueantes.
Slices y diagnósticas como explicación, no como celebración automática.

CUPED: reducir varianza sin cambiar la pregunta

CUPED usa información previa al experimento para reducir ruido. Deng, Xu, Kohavi y Walker propusieron usar datos pre-experimento para mejorar la sensibilidad de experimentos online.14 Microsoft ExP lo describe como técnica de reducción de varianza en A/B testing.15

La idea no es manipular el resultado. Es restar parte del ruido explicable por una covariable medida antes del tratamiento:

Yi\*=Yiθ(XiXˉ)Y_i^\* = Y_i - \theta(X_i-\bar{X})
SímboloSignificadoEjemplo
Yi\*Y_i^\*Resultado ajustado por CUPED.resolved ajustado.
YiY_iResultado original.resolved = 1.
XiX_iCovariable previa al experimento.historical_resolution_rate.
Xˉ\bar{X}Media de la covariable previa.Media histórica del dataset.
θ\thetaPeso del ajuste.3.107096 en el kit.

El peso suele estimarse así:

θ=Cov(Y,X)Var(X)\theta = \frac{Cov(Y,X)}{Var(X)}
SímboloSignificadoEjemplo
Cov(Y,X)Cov(Y,X)Covarianza entre resultado y covariable previa.Relación entre resolución y histórico.
Var(X)Var(X)Varianza de la covariable previa.Dispersión de historical_resolution_rate.
θ\thetaCoeficiente de ajuste.3.107096.

En el kit, CUPED mantiene el efecto en 0.25, pero baja el error estándar de 0.186339 a 0.162557. Eso no convierte una señal en verdad absoluta, pero ayuda a medir con menos ruido.

Causalidad observacional: cuando no puedes aleatorizar

No siempre podemos hacer un A/B test. A veces trabajamos con datos históricos. En ese caso, el primer deber es no vender la asociación como efecto.

El problema típico se llama confounding. Una variable ZZ influye en el tratamiento y en el resultado:

flowchart LR
  Z["Prioridad previa Z"] --> T["Recibe acción T"]
  Z --> Y["Resultado Y"]
  T --> Y

  classDef node fill:#ffffff,stroke:#111111,color:#111111,stroke-width:1.4px;
  class Z,T,Y node;

Si no ajustamos por ZZ, podemos atribuir a TT lo que en realidad viene de la prioridad previa. El ajuste por backdoor escribe:

P(Ydo(T=t))=zP(YT=t,Z=z)P(Z=z)P(Y \mid do(T=t)) = \sum_z P(Y \mid T=t, Z=z)P(Z=z)
SímboloSignificadoEjemplo
TTTratamiento o acción.Recibir plantilla.
ttValor del tratamiento.1 o 0.
YYResultado.Caso resuelto.
ZZConfounder observado.Prioridad previa.
zzNivel concreto de ZZ.high, medium, low.
P(YT=t,Z=z)P(Y \mid T=t, Z=z)Resultado dentro de un estrato comparable.Resolución de casos medium con plantilla.
P(Z=z)P(Z=z)Peso del estrato en la población.Proporción de prioridad medium.

Esto exige solapamiento. Si en prioridad low nadie recibió tratamiento, no podemos comparar tratamiento contra control dentro de ese nivel. El kit lo muestra: el efecto ingenuo es 0.5, pero al estratificar por prioridad baja a 0.0375 en la población estimable y queda en review por falta de solapamiento.

DoWhy separa modelado causal, identificación, estimación y refutación.16 Su documentación actual insiste en tratar los supuestos como ciudadanos de primera clase y separar identificación de estimación.17 EconML aplica técnicas de machine learning a estimación de respuestas causales individuales o heterogéneas en datos experimentales u observacionales.18

La regla para el libro es sencilla: si no puedes escribir supuestos, estimando, población y prueba de robustez, todavía no tienes conclusión causal.

Una herramienta clásica en observacional es el propensity score: la probabilidad de recibir tratamiento dado el contexto observado.19 Se escribe:

e(x)=P(T=1X=x)e(x) = P(T=1 \mid X=x)
SímboloSignificadoEjemplo
e(x)e(x)Propensity score.Probabilidad de recibir plantilla.
T=1T=1Recibir tratamiento.received_action = 1.
X=xX=xContexto observado.Prioridad, segmento, histórico.

Sirve para emparejar, ponderar o estratificar casos con probabilidades parecidas de recibir tratamiento. Pero no resuelve el sesgo por sí solo: solo ajusta por variables observadas. Si falta una causa importante, el sesgo puede seguir ahí. Imbens y Rubin desarrollan con detalle este tipo de inferencia causal basada en supuestos explícitos.20

Uplift y CATE: actuar donde cambia algo

El ATE puede ser positivo y aun así esconder una decisión mala. Quizá la intervención no ayuda a todos por igual. En IA aplicada, muchas veces queremos saber dónde cambia algo.

El efecto condicionado se escribe:

CATE(x)=E[Y(1)Y(0)X=x]CATE(x) = E[Y(1)-Y(0)\mid X=x]
SímboloSignificadoEjemplo
CATE(x)CATE(x)Efecto medio condicionado al contexto xx.Efecto en segment=becas.
X=xX=xContexto o características del caso.Segmento, idioma, canal, prioridad.
Y(1)Y(1)Resultado con tratamiento.Resolución con plantilla.
Y(0)Y(0)Resultado sin tratamiento.Resolución sin plantilla.

Esto conecta directamente con slices. En el kit:

SegmentoControlTratamientoEfecto observado
becas0.250.750.50
matricula1.001.000.00
practicas0.500.750.25

La decisión no debería ser “plantilla para todo el mundo”. Podría ser: ampliar muestra, estudiar por qué becas concentra mejora y comprobar que matricula no necesita gasto adicional.

Del experimento al rollout

Un resultado experimental no es el final del trabajo. Es la entrada a una decisión de release. En sistemas de IA, publicar al 100% sin escalones puede mezclar tres problemas a la vez: efecto causal, estabilidad operativa y coste.

Una política de rollout sobria puede ser:

PasoQué ocurreQué se mira
A/AVariantes iguales.SRM, exposición, métricas estables.
A/B pequeñoPrimera ventana controlada.Señal, guardrails, slices.
Ramp 5%Tráfico real limitado.Latencia, coste, errores y trazas.
Ramp 25%Más diversidad de casos.CATE, segmentos raros, operación humana.
Ramp 50%Estrés realista.SLOs y presupuesto de error.
100%Publicación completa.Monitorización post-release y rollback.

En el contrato del kit aparece:

{
  "initial_ramp_percent": 5,
  "ramp_steps_percent": [5, 25, 50, 100],
  "rollback_if_guardrail_blocks": true,
  "publish_requires_status": "pass"
}

Esto no es decoración. Si el experimento queda en review, no debería pasar a 100%. Puede pasar a otra ventana de medición, a un A/A pendiente, a un rollout limitado o a una mejora de instrumentación. La salida profesional no es “ganó B”. La salida profesional es: qué hacemos ahora, con qué riesgo y qué evidencia queda guardada.

Bandits y experimentos adaptativos

Un A/B test clásico mantiene proporciones estables mientras mide. Eso es útil porque simplifica la interpretación: si control y tratamiento están bien asignados, estimar el efecto es directo. Pero a veces el objetivo no es solo medir; también queremos aprender y asignar más tráfico a variantes que parecen mejores durante el proceso.

Ahí aparecen los bandits. En un problema de bandits elegimos acciones, observamos recompensa y vamos actualizando la política de asignación. Sutton y Barto lo explican como una tensión entre exploración y explotación: probar para aprender frente a usar lo que parece mejor.21

La idea mínima se puede escribir así:

at=argmaxaQt(a)a_t = \arg\max_a Q_t(a)
SímboloSignificadoEjemplo
ata_tAcción elegida en el paso tt.Variante de prompt para el ticket actual.
aaAcción candidata.control, treatment_a, treatment_b.
Qt(a)Q_t(a)Valor estimado de la acción en el paso tt.Tasa media de resolución observada.
argmax\arg\maxAcción con mayor valor estimado.Variante que parece mejor.

Pero si siempre elegimos la que parece mejor, podemos dejar de explorar demasiado pronto. Una regla epsilon-greedy añade exploración:

at={accioˊn aleatoriacon probabilidad ϵ argmaxaQt(a)con probabilidad 1ϵa_t = \begin{cases} \text{acción aleatoria} & \text{con probabilidad } \epsilon\ \arg\max_a Q_t(a) & \text{con probabilidad } 1-\epsilon \end{cases}
SímboloSignificadoEjemplo
ϵ\epsilonProbabilidad de explorar.0.1.
1ϵ1-\epsilonProbabilidad de explotar lo mejor conocido.0.9.
Qt(a)Q_t(a)Estimación acumulada por acción.Calidad media por variante.

Para IA aplicada, la tabla de decisión sería:

DiseñoÚtil cuandoNo lo uses si
A/B fijoNecesitas una conclusión clara y auditable.La pérdida de oportunidad durante la prueba es muy alta.
A/AQuieres validar instrumentación.Esperas medir efecto real.
BanditQuieres aprender y reasignar tráfico mientras operas.Necesitas estimación simple del ATE con reparto estable.
Rollout progresivoQuieres publicar con control operativo.Lo confundes con experimento causal completo.
Holdout persistenteQuieres medir impacto largo plazo.No puedes mantener grupo sin tratamiento.

Los bandits pueden ser muy útiles en recomendación, prompts alternativos o selección de respuesta, pero complican inferencia, métricas tardías y comunicación. Si cambias la asignación durante el experimento, el análisis debe saberlo. No puedes tratarlo luego como si hubiese sido un A/B fijo.

Herramientas y decisiones de compra o montaje

No hace falta que cada equipo construya Microsoft ExP desde cero. Pero sí debe saber qué está comprando o montando.

OpciónEncaja cuandoPreguntas antes de usarla
Feature flags simplesSolo necesitas activar o desactivar variantes.¿Registra exposición? ¿Persistencia? ¿Auditoría?
Plataforma de experimentaciónQuieres análisis, métricas y decisiones recurrentes.¿SRM, A/A, CUPED, sequential testing, slices?
Warehouse-nativeYa tienes métricas en BigQuery, Snowflake, Databricks o similar.¿La definición SQL de métricas es versionable?
Implementación propiaNecesitas control completo o restricciones internas.¿Quién mantiene asignación, logs, análisis y UI?
OpenFeature + proveedorQuieres no acoplar código a una herramienta.¿El proveedor soporta contexto, tracking y trazas?

Para IA, añade estas preguntas:

PreguntaPor qué importa
¿La variante incluye versión de modelo, prompt y parámetros?Cambiar temperature, prompt o modelo cambia el tratamiento.
¿La exposición registra fallback?Si el modelo nuevo falla y se usa otro, no puedes contar esa unidad igual.
¿Las métricas maduran tarde?Una resolución puede medirse días después de la exposición.
¿Hay trazas de herramienta o RAG?Sin ellas no sabes qué contexto o tool produjo el resultado.
¿El coste se mide por unidad asignada o expuesta?Una variante puede resolver más y aun así no compensar.

Experimentos RAG y métricas tardías

Un experimento RAG no mide solo “la respuesta gustó”. Cambiar el retriever, el reranker o el chunking cambia qué evidencia llega al modelo. Por eso las métricas deben separar resultado, calidad de recuperación y guardrails técnicos.

En el kit añadimos rag_experiment_events.csv con estas señales:

MétricaQué midePor qué importa
answer_acceptedSi la respuesta fue aceptada.Métrica de utilidad.
citation_validSi la cita apuntaba a evidencia válida.Guardrail documental.
retrieval_precisionSi los documentos recuperados eran relevantes.Calidad del sistema RAG, no solo del LLM.
latency_msTiempo de respuesta.Un reranker puede mejorar calidad y empeorar experiencia.
cost_eurCoste por unidad.La mejora puede no compensar si el coste sube demasiado.

La salida del kit deja el experimento RAG en review: el tratamiento mejora aceptación y recuperación, pero sube latencia y coste. Esa es una decisión realista. En IA aplicada, muchas mejoras son tradeoffs, no victorias limpias.

También añadimos late_metric_events.csv. Algunas métricas maduran tarde. Un caso puede parecer resuelto en el día 1 y reabrirse en el día 7. O puede necesitar seguimiento al principio y terminar bien después. Por eso la tabla de métricas debe declarar ventana:

VentanaQué puede medirRiesgo
day_0Exposición, latencia, coste.Todavía no sabes si ayudó.
day_1Resolución temprana.Puede ignorar reaperturas.
day_7Resolución más estable.Llega tarde para decisiones rápidas.
day_30Retención o satisfacción persistente.Mezcla más cambios del entorno.

Un sistema profesional no pregunta solo “¿qué métrica?”. Pregunta “¿en qué ventana, con qué unidad y con qué maduración?”.

Schema, CI y contrato de análisis

El kit incluye warehouse_schema.sql para dejar una idea de arquitectura mínima. Hay cuatro tablas:

TablaQué guardaPor qué existe
experiment_unitsUnidad, variante, flag y contexto.Saber qué se asignó.
exposure_eventsExposición real a la variante.Saber qué se vio o recibió.
metric_eventsMétricas por unidad y ventana.Separar exposición de resultado.
experiment_decisionsDecisión final y evidencia.Versionar la salida profesional.

Además, ci_experiment_gate.py revisa que existan contratos, outputs y campos obligatorios del reporte. No bloquea por estar en review; lo deja explícito. Bloquearía si faltan archivos, si el schema falla, si SRM queda en block o si algún guardrail bloquea.

Eso es importante para equipos de ingeniería: una decisión en review puede ser aceptable si significa “seguir midiendo”. Una decisión en block significa “no publiques, hay una condición rota”. El CI no debe sustituir criterio, pero sí debe impedir que un experimento incompleto parezca listo.

Arquitectura de una decisión experimental

Anatomía de una decisión experimental para IA Diagrama en blanco y negro que conecta pregunta causal, contrato experimental, asignación, exposición, métricas, guardrails, análisis, slices, decisión y aprendizaje operativo. De hipótesis a decisión experimental Una decisión causal necesita contrato, asignación, exposición, métricas, trazabilidad y salida operativa. Pregunta causal Unidad: ticket T: plantilla guiada Y: caso resuelto Contrato flag y targeting key métrica primaria guardrails y MDE Ejecución asignación persistente exposure event logs y unidad estable Readiness A/A · SRM balance · peeking muestra suficiente Estimación ATE · CATE · IC95% CUPED si procede Slices CATE por segmento heterogeneidad Guardrails latencia · coste feedback negativo Rollout 5 · 25 · 50 · 100 rollback por guardrail Salida profesional pass · review · block · ampliar muestra · repetir ventana · publicar solo por slice IA para gente curiosa / Facsímil 08 / Capítulo 07 / 686f6c61
Una decisión experimental no empieza en el p-value: empieza en la pregunta causal y termina en una salida operativa versionada.

Cómo se ve en producción

En producción no basta con decir que el tratamiento “gana”. El resultado tiene que pasar por un contrato.

En el kit del capítulo, el A/B test tiene 24 unidades: 12 en control y 12 en tratamiento. La métrica primaria es resolved, que debe subir. Los guardrails vigilan feedback negativo, latencia y coste.

SeñalResultadoLectura
Control resolved0.583333Línea base.
Treatment resolved0.833333Mejora observada.
ATE observado0.25Señal positiva.
IC95%[-0.115224, 0.615224]Intervalo demasiado ancho.
SRMpassAsignación 50/50 correcta.
Balance previopassCovariables iniciales equilibradas.
GuardrailspassCoste y latencia no bloquean.
DecisiónreviewPrometedor, pero falta precisión.

El readiness añade otra capa:

Señal de readinessResultadoLectura
A/A previoreviewFalta documentarlo antes de confiar en el A/B.
Exposure eventpassEl contrato exige experiment_exposure.
Asignación persistentepassLa unidad conserva variante.
n recomendado por variante1530El MDE de 0.05 exige mucha más muestra.
MDE aproximado con n actual0.564504Con 12 por variante solo detectas efectos enormes.
Política de peekingpassHay una sola mirada planificada.
RolloutpassHay pasos 5/25/50/100 y rollback por guardrail.

El análisis observacional cuenta otra historia:

LecturaResultado
Efecto ingenuo0.5
Efecto estratificado por prioridad0.0375
Población estimable por prioridad0.75
Decisiónreview

La diferencia enseña la lección del capítulo: lo que parece enorme en datos históricos puede encogerse cuando comparas contextos más parecidos.

Por qué debería importarte

Si no separas predicción de intervención, puedes construir sistemas que gastan recursos donde no cambian nada. Puedes enviar acciones a quienes ya iban a resolver. Puedes castigar un segmento porque aparece asociado a un resultado, cuando en realidad recibe casos más difíciles. Puedes publicar un cambio por una métrica primaria bonita mientras se degrada latencia, coste o experiencia.

Para ingeniería de IA, causalidad no es lujo académico. Es control de daños en decisiones que actúan sobre el mundo.

Manos a la obra

El kit está en:

kit/

Estructura

kit/
  README.md
  data/experiment_events.csv
  data/observational_campaign.csv
  data/rag_experiment_events.csv
  data/late_metric_events.csv
  data/cluster_interference_events.csv
  contracts/experiment_contract.json
  contracts/analysis_plan.json
  contracts/metric_catalog.json
  contracts/causal_question.md
  contracts/feature_flag_contract.json
  contracts/warehouse_schema.sql
  contracts/ci_gate_policy.json
  ops/analyze_ab_experiment.py
  ops/audit_observational_effect.py
  ops/validate_experiment_design.py
  ops/simulate_feature_flag_assignment.py
  ops/analyze_rag_experiment.py
  ops/summarize_metric_maturation.py
  ops/analyze_cluster_interference.py
  ops/ci_experiment_gate.py
  output/experiment_report.json
  output/experiment_scorecard.csv
  output/balance_report.csv
  output/slice_effects.csv
  output/experiment_decision.md
  output/experiment_readiness.md
  output/experiment_design_validation.json
  output/experiment_design_validation.md
  output/exposure_events.csv
  output/flag_assignment_manifest.json
  output/rag_experiment_report.json
  output/metric_maturation_report.json
  output/cluster_interference_report.json
  output/cluster_interference_decision.md
  output/ci_gate_report.json
  output/observational_causal_report.json
  output/observational_strata.csv
  output/observational_decision.md

Cómo lo ejecutas

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/analyze_ab_experiment.py --write
cat output/experiment_decision.md
cat output/experiment_readiness.md
python3 -m json.tool output/experiment_report.json

Para comparar con datos no aleatorizados:

python3 ops/audit_observational_effect.py --write
cat output/observational_decision.md
python3 -m json.tool output/observational_causal_report.json

Para simular plataforma experimental:

python3 ops/validate_experiment_design.py --write
cat output/experiment_design_validation.md
python3 ops/simulate_feature_flag_assignment.py --write
cat output/flag_assignment_decision.md
python3 ops/analyze_rag_experiment.py --write
cat output/rag_experiment_decision.md
python3 ops/summarize_metric_maturation.py --write
cat output/metric_maturation_decision.md
python3 ops/analyze_cluster_interference.py --write
cat output/cluster_interference_decision.md
python3 ops/ci_experiment_gate.py --write
cat output/ci_gate_decision.md

Qué deberías ver

El experimento queda en review:

Estado: review
ATE observado: 0.25
IC95%: [-0.115224, 0.615224]

La muestra observacional también queda en review:

Efecto ingenuo: 0.5
Efecto estratificado por prioridad: 0.0375
Población estimable por prioridad: 0.75

La validación de diseño debería quedar en pass:

Estado: pass
plan_field:hypothesis: pass
primary_metric_in_catalog: pass
exposure_fields: pass

La interferencia por clúster queda en review:

Estado: review
Clusters mezclados con aprendizaje compartido: team_a, team_b, team_c
Decisión: considerar asignación por cluster_id

Los artefactos principales son:

ArchivoQué demuestra
experiment_report.jsonReporte completo del experimento.
experiment_scorecard.csvMétricas por variante.
balance_report.csvBalance previo entre grupos.
slice_effects.csvEfectos por segmento.
experiment_decision.mdDecisión operativa versionable.
experiment_readiness.mdMDE, potencia, A/A, peeking y rollout.
experiment_design_validation.jsonValidación del plan antes de mirar resultados.
experiment_design_validation.mdLectura humana de esa validación.
exposure_events.csvEventos de exposición generados desde la flag.
flag_assignment_manifest.jsonReparto por flag y discrepancias con el dataset.
rag_experiment_report.jsonExperimento RAG con calidad, citas, latencia y coste.
metric_maturation_report.jsonMétricas por ventana de maduración.
cluster_interference_report.jsonMezcla de variantes dentro de equipos, colas u otros clústeres.
cluster_interference_decision.mdDecisión sobre si la unidad individual es suficiente.
ci_gate_report.jsonGate de CI para contratos y outputs.
observational_causal_report.jsonLectura de efecto ingenuo y ajuste por contexto.
observational_decision.mdPor qué la muestra histórica no cierra la conclusión.

Cómo lo adaptarías

Si tu proyecto es...Cambia esto
Un RAG documentalTratamiento: nuevo chunking o reranker. Resultado: respuesta aceptada. Guardrail: citas válidas.
Un agente con herramientasTratamiento: política de aprobación. Resultado: tarea completada. Guardrail: coste y reversión.
Un clasificador de ticketsTratamiento: plantilla, cola o SLA. Resultado: resolución. Guardrail: revisión humana.
Una API de recomendaciónTratamiento: nuevo ranking. Resultado: conversión incremental. Guardrail: latencia y diversidad.
Un modelo localTratamiento: modelo cuantizado o prompt. Resultado: calidad aceptada. Guardrail: memoria y tiempo.

Qué entregaría un alumno

  1. experiment_decision.md generado e interpretado.
  2. Un cambio razonado en experiment_contract.json.
  3. Una nueva métrica guardrail para su proyecto.
  4. Una lectura de slice_effects.csv indicando dónde se concentra el efecto.
  5. Una explicación de por qué observational_campaign.csv no permite cerrar conclusión causal.
  6. Un diseño de próximo experimento: unidad, tratamiento, métrica primaria, guardrails y criterio de parada.
  7. Un readiness de experimento: A/A, exposure event, MDE, potencia, política de peeking y rollout.
  8. Un analysis_plan.json propio, validado antes de mirar resultados.
  9. Un metric_catalog.json con primaria, guardrails y diagnósticas.
  10. Una decisión sobre unidad individual o clúster, justificada con datos.

Cómo encaja todo

Este mapa se lee desde los capítulos anteriores. Los datos y contratos vienen del capítulo 01, la evaluación honesta del capítulo 03, los slices del capítulo 05 y la operación del capítulo 06. Este capítulo enseña a decidir si una acción cambia algo.

La decisión que introduce es nueva: no basta con medir calidad predictiva; necesitamos estimar efecto, revisar diseño experimental y dejar una salida operativa. En el cierre del facsímil, esto se convertirá en laboratorio integrador.

graph LR
    subgraph "Este capítulo"
        Q["Pregunta causal<br/>unidad · T · Y"]
        PLAN["Plan y métricas<br/>hipótesis · ventana · guardrails"]
        EXP["Exposición<br/>flag · unidad · versión"]
        DESIGN["Diseño experimental<br/>SRM · balance · MDE · clúster"]
        EFFECT["Estimación<br/>ATE · CATE · CUPED · observacional"]
        DEC["Decisión<br/>pass · review · block"]
    end
    subgraph "Mismo facsímil"
        DATA["Datos y linaje<br/>cap. 1"]
        QUALITY["Calidad<br/>cap. 2"]
        SPLIT["Splits<br/>cap. 3"]
        SLICES["Slices<br/>cap. 5"]
        OPS["DataOps<br/>cap. 6"]
        LAB["Laboratorio<br/>cap. 8"]
    end
    subgraph "Otros facsímiles"
        EVALS["Evals<br/>fasc. 7"]
        RAG["RAG<br/>fasc. 4"]
        AGENTS["Agentes<br/>fasc. 5"]
        GOV["Gobernanza<br/>fasc. 9"]
        UX["Producto y UX<br/>fasc. 11"]
    end

    DATA -->|"define población"| Q
    QUALITY -->|"limpia entrada"| DESIGN
    SPLIT -->|"separa medición"| DESIGN
    SLICES -->|"pide CATE"| EFFECT
    OPS -->|"aporta trazas"| EXP
    EVALS -->|"aporta criterio"| PLAN
    RAG -->|"necesita experimento"| EXP
    AGENTS -->|"necesita despliegue gradual"| DEC

    Q -->|"se escribe en"| PLAN
    PLAN -->|"ordena"| EXP
    EXP -->|"alimenta"| DESIGN
    DESIGN -->|"permite"| EFFECT
    EFFECT -->|"con guardrails"| DEC

    DEC -->|"se practica en"| LAB
    DEC -->|"deja evidencia"| GOV
    DEC -->|"cambia experiencia"| UX

    style Q fill:#F5F5F5,stroke:#000000,stroke-width:2
    style PLAN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EXP fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DESIGN fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EFFECT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DEC fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DATA stroke-dasharray: 5 5
    style QUALITY stroke-dasharray: 5 5
    style SPLIT stroke-dasharray: 5 5
    style SLICES stroke-dasharray: 5 5
    style OPS stroke-dasharray: 5 5
    style LAB stroke-dasharray: 5 5
    style EVALS stroke-dasharray: 5 5
    style RAG stroke-dasharray: 5 5
    style AGENTS stroke-dasharray: 5 5
    style GOV stroke-dasharray: 5 5
    style UX stroke-dasharray: 5 5

Vocabulario aprendido

TérminoDefinición breve
TratamientoAcción o variante cuyo efecto queremos medir.
ControlCondición de comparación sin la intervención nueva.
ResultadoVariable que medimos después de la intervención.
UnidadElemento que se asigna y analiza: usuario, ticket, empresa o sesión.
ATEEfecto medio del tratamiento.
CATEEfecto medio condicionado a un contexto o segmento.
ContrafactualResultado que no observamos para la misma unidad bajo otra acción.
ConfounderVariable que afecta al tratamiento y al resultado.
DAG causalGrafo que explicita hipótesis sobre relaciones causales.
SRMDesajuste entre asignación esperada y observada.
GuardrailMétrica que no debe empeorar aunque la primaria mejore.
CUPEDAjuste con covariable previa para reducir varianza.
SolapamientoExistencia de tratamiento y control dentro de contextos comparables.
Feature flagInterruptor controlado en ejecución para servir variantes sin desplegar código nuevo.
Evaluation contextContexto usado para evaluar una flag: unidad, segmento, canal, entorno o atributos.
Exposure eventEvento que demuestra que la unidad recibió la variante.
A/A testPrueba con variantes equivalentes para validar instrumentación y reparto.
MDEEfecto mínimo detectable bajo una muestra y potencia dadas.
PeekingMirar resultados repetidamente sin regla previa.
RolloutPublicación progresiva con pasos, guardrails y rollback.
Plan de análisisContrato previo con hipótesis, población, métrica, ventanas, exclusiones y reglas de decisión.
Catálogo de métricasRegistro versionado que define nombre, unidad, ventana, dirección y propósito de cada métrica.
Comparaciones múltiplesRiesgo de encontrar señales aparentes al mirar muchas métricas, slices o ventanas.
Propensity scoreProbabilidad estimada de recibir tratamiento dado el contexto observado.
Asignación por clústerDiseño que asigna grupos completos cuando las unidades pueden influirse entre sí.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Usar predicción como efectoEl score parece accionable.Preguntar si queremos P(YX)P(Y\mid X) o P(Ydo(X))P(Y\mid do(X)).
Celebrar un ATE sin guardrailsLa métrica primaria sube.Revisar coste, latencia, feedback y slices antes de decidir.
Mirar el resultado antes de validar asignaciónQueremos saber quién ganó.Comprobar SRM, balance y exposición antes del efecto.
Vender datos históricos como experimentoHay muchas filas y parece serio.Escribir DAG, confounders, solapamiento y supuestos.
Ignorar heterogeneidadEl promedio es cómodo.Revisar CATE o slices antes de publicar una política global.
Parar cuando el resultado gustaLa señal temprana seduce.Fijar criterio de parada y decisión antes de mirar.
No registrar exposición realLa asignación parece suficiente.Medir solo unidades que vieron o recibieron la variante.
No calcular MDEEl resultado parece grande.Escribir MDE, alpha, potencia y n antes de empezar.
Pasar de experimento a 100%El equipo quiere cerrar rápido.Usar rollout por pasos y rollback si falla un guardrail.
Confundir métrica primaria con métrica diagnósticaTodas parecen interesantes.Una primaria decide; las demás explican o bloquean.
Ignorar clústeres naturalesLa unidad individual da más muestra aparente.Preguntar si equipo, empresa, aula, operador o cola comparten efectos.
Ajustar observacional sin mirar solapamientoEl modelo devuelve un número.Revisar si existen casos comparables antes de hablar de efecto.

Antes de pasar página

Antes de avanzar, deberías poder responder:

  1. ¿Qué diferencia hay entre P(YX)P(Y\mid X) y P(Ydo(X))P(Y\mid do(X))?
  2. ¿Por qué no observamos Yi(1)Y_i(1) y Yi(0)Y_i(0) a la vez?
  3. ¿Qué mide el ATE?
  4. ¿Qué mide el CATE?
  5. ¿Qué es un contrafactual?
  6. ¿Qué piezas debe tener una pregunta causal?
  7. ¿Qué comprueba SRM?
  8. ¿Qué significa balance previo entre grupos?
  9. ¿Por qué un guardrail puede bloquear un experimento ganador?
  10. ¿Qué hace CUPED y qué no hace?
  11. ¿Qué es un confounder?
  12. ¿Por qué hace falta solapamiento en datos observacionales?
  13. ¿Por qué el kit deja el experimento en review?
  14. ¿Por qué el efecto ingenuo observacional no basta?
  15. ¿Qué demuestra un exposure event?
  16. ¿Por qué un A/A test puede ahorrar un experimento mal medido?
  17. ¿Qué significa MDE?
  18. ¿Por qué mirar resultados muchas veces sin regla previa cambia el riesgo de error?
  19. ¿Qué debería contener una política de rollout?
  20. ¿Qué campos mínimos debe tener un plan de análisis?
  21. ¿Qué diferencia hay entre métrica primaria, guardrail y diagnóstica?
  22. ¿Cuándo usarías Bonferroni o control de descubrimientos falsos?
  23. ¿Qué intenta resumir un propensity score?
  24. ¿Por qué una asignación por clúster puede ser más honesta aunque tenga menos potencia?
  25. ¿Cómo conecta este capítulo con el laboratorio final del facsímil?

En resumen

IdeaQué te llevas
Predicción no es intervención.Un score útil para anticipar no prueba que una acción cambie el resultado.
Un experimento es arquitectura.Unidad, asignación, logging, métricas y análisis deben estar contratados.
El efecto necesita incertidumbre.Un ATE observado sin intervalo puede llevar a decisiones precipitadas.
Los guardrails importan.Una mejora primaria no justifica degradar coste, latencia o experiencia.
Causalidad observacional exige supuestos.Si falta solapamiento o hay confounding, la lectura queda en triage.
Las decisiones se versionan.El resultado útil es un artefacto: reporte, scorecard y decisión.
La plataforma importa.Flags, exposición, métricas, warehouse y análisis forman parte del experimento.
El MDE evita autoengaños.Una muestra pequeña puede aprender mucho y decidir poco.
El rollout también es causalidad aplicada.Publicar progresivamente protege calidad, coste y operación.
El plan evita cambiar la pregunta.Hipótesis, métrica, ventanas y reglas deben existir antes del resultado.
Los clústeres cambian el diseño.Si hay aprendizaje compartido, la unidad individual puede engañar.
Las métricas necesitan contrato.Nombre, unidad, ventana y dirección deben ser inequívocos.

Para saber más

Rubin, D. B. (1974). Estimating Causal Effects of Treatments in Randomized and Nonrandomized Studies. Journal of Educational Psychology, 66(5), 688-701. DOI

Holland, P. W. (1986). Statistics and Causal Inference. Journal of the American Statistical Association, 81(396), 945-960. DOI

Pearl, J. (2009). Causality: Models, Reasoning, and Inference (2.ª ed.). Cambridge University Press.

Kohavi, R., Longbotham, R., Sommerfield, D. y Henne, R. M. (2009). Controlled Experiments on the Web: Survey and Practical Guide. Data Mining and Knowledge Discovery, 18(1), 140-181. Microsoft Research

Deng, A., Xu, Y., Kohavi, R. y Walker, T. (2013). Improving the Sensitivity of Online Controlled Experiments by Utilizing Pre-Experiment Data. WSDM, 123-132. PDF

Gupta, S., Ulanova, L., Bhardwaj, S., Dmitriev, P., Raff, P. y Fabijan, A. (2018). The Anatomy of a Large-Scale Experimentation Platform. IEEE International Conference on Software Architecture. Microsoft Research

Nie, K., Zhang, Z., Xu, B. y Yuan, T. (2022). Ensure A/B Test Quality at Scale with Automated Randomization Validation and Sample Ratio Mismatch Detection. CIKM. arXiv

Sharma, A. y Kiciman, E. (2020). DoWhy: An End-to-End Library for Causal Inference. arXiv

PyWhy. (2026). DoWhy documentation. Documentación

PyWhy. (2026). EconML documentation. Documentación

OpenFeature. (2026). Introduction. Documentación

OpenFeature. (2026). Evaluation Context. Especificación

LaunchDarkly. (2026). Experimentation. Documentación

Rosenbaum, P. R. y Rubin, D. B. (1983). The Central Role of the Propensity Score in Observational Studies for Causal Effects. Biometrika, 70(1), 41-55. DOI

Benjamini, Y. y Hochberg, Y. (1995). Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing. Journal of the Royal Statistical Society: Series B, 57(1), 289-300. DOI

Imbens, G. W. y Rubin, D. B. (2015). Causal Inference for Statistics, Social, and Biomedical Sciences: An Introduction. Cambridge University Press. DOI

Statsig. (2026). Experiment Options. Documentación

GrowthBook. (2026). GrowthBook Documentation. Documentación

Notas

  1. Rubin, D. B. (1974). Estimating Causal Effects of Treatments in Randomized and Nonrandomized Studies. Journal of Educational Psychology, 66(5), 688-701. https://doi.org/10.1037/h0037350

  2. Holland, P. W. (1986). Statistics and Causal Inference. Journal of the American Statistical Association, 81(396), 945-960. https://doi.org/10.1080/01621459.1986.10478354

  3. Pearl, J. (2009). Causality: Models, Reasoning, and Inference (2.ª ed.). Cambridge University Press.

  4. Kohavi, R., Longbotham, R., Sommerfield, D. y Henne, R. M. (2009). Controlled Experiments on the Web: Survey and Practical Guide. Data Mining and Knowledge Discovery, 18(1), 140-181. https://doi.org/10.1007/s10618-008-0114-1

  5. Gupta, S., Ulanova, L., Bhardwaj, S., Dmitriev, P., Raff, P. y Fabijan, A. (2018). The Anatomy of a Large-Scale Experimentation Platform. IEEE International Conference on Software Architecture. https://www.microsoft.com/en-us/research/publication/the-anatomy-of-a-large-scale-experimentation-platform/

  6. OpenFeature. (2026). Introduction. https://openfeature.dev/docs/reference/intro/. Consultado el 7 de junio de 2026.

  7. OpenFeature. (2026). Evaluation Context. https://openfeature.dev/specification/sections/evaluation-context/. Consultado el 7 de junio de 2026.

  8. LaunchDarkly. (2026). Experimentation. https://launchdarkly.com/docs/home/experimentation. Consultado el 7 de junio de 2026.

  9. GrowthBook. (2026). GrowthBook Documentation. https://docs.growthbook.io/. Consultado el 7 de junio de 2026.

  10. Statsig. (2026). Experiment Options. https://docs.statsig.com/statsig-warehouse-native/features/experiment-options. Consultado el 7 de junio de 2026.

  11. Nie, K., Zhang, Z., Xu, B. y Yuan, T. (2022). Ensure A/B Test Quality at Scale with Automated Randomization Validation and Sample Ratio Mismatch Detection. CIKM. https://doi.org/10.1145/3511808.3557087

  12. Statsig. (2026). Experiment Options. https://docs.statsig.com/statsig-warehouse-native/features/experiment-options. Consultado el 7 de junio de 2026.

  13. Benjamini, Y. y Hochberg, Y. (1995). Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing. Journal of the Royal Statistical Society: Series B, 57(1), 289-300. https://doi.org/10.1111/j.2517-6161.1995.tb02031.x

  14. Deng, A., Xu, Y., Kohavi, R. y Walker, T. (2013). Improving the Sensitivity of Online Controlled Experiments by Utilizing Pre-Experiment Data. WSDM, 123-132. https://doi.org/10.1145/2433396.2433413

  15. Microsoft Research. (2022). Deep Dive Into Variance Reduction. https://www.microsoft.com/en-us/research/articles/deep-dive-into-variance-reduction/

  16. Sharma, A. y Kiciman, E. (2020). DoWhy: An End-to-End Library for Causal Inference. arXiv:2011.04216. https://arxiv.org/abs/2011.04216

  17. PyWhy. (2026). DoWhy documentation. https://www.pywhy.org/dowhy/main/index.html. Consultado el 7 de junio de 2026.

  18. PyWhy. (2026). EconML documentation. https://www.pywhy.org/EconML/spec/overview.html. Consultado el 7 de junio de 2026.

  19. Rosenbaum, P. R. y Rubin, D. B. (1983). The Central Role of the Propensity Score in Observational Studies for Causal Effects. Biometrika, 70(1), 41-55. https://doi.org/10.1093/biomet/70.1.41

  20. Imbens, G. W. y Rubin, D. B. (2015). Causal Inference for Statistics, Social, and Biomedical Sciences: An Introduction. Cambridge University Press. https://doi.org/10.1017/CBO9781139025751

  21. Sutton, R. S. y Barto, A. G. (2018). Reinforcement Learning: An Introduction (2.ª ed.). MIT Press. https://incompleteideas.net/book/the-book-2nd.html

Capítulo 08

Facsímil 8 · La ciencia de los datos

Capítulo 08: Recapitulación y laboratorio de ciencia de datos

Qué deberías poder hacer al terminar

Este facsímil empezó con una idea sencilla: en IA, los datos no son un trámite. Son parte del sistema. Si el dataset está mal definido, si el contrato no existe, si el split engaña, si los slices fallan, si falta trazabilidad o si confundimos predicción con intervención, el modelo puede parecer sofisticado y aun así tomar malas decisiones.

Al cerrar el facsímil deberías poder hacer esto:

Resultado de aprendizajeEvidencia de que lo sabes hacer
Auditar un dataset antes de usarlo.Revisas contrato, columnas, valores, licencias, linaje y trazabilidad.
Diseñar una evaluación honesta.Separas train, validation y test sin leakage.
Leer features y embeddings como decisiones.No conviertes columnas en vectores sin contrato.
Medir slices críticos.No publicas una media global si falla un segmento importante.
Operar datos en producción.Escribes SLIs, SLOs, runbooks, trazas y gates.
Diseñar un experimento aplicable.Separas predicción de intervención, ATE de CATE y A/B de observacional.
Entregar una decisión defendible.Generas scorecard, reporte y documento de salida.

La frase de cierre:

La ciencia de datos en IA no consiste en encontrar una métrica bonita. Consiste en construir una decisión que aguante preguntas.

Lo que hemos construido

El recorrido del facsímil puede leerse como una cadena:

La cadena no es una ocurrencia editorial. Datasheets for Datasets consolidó la idea de documentar motivación, composición, recogida, usos y límites de un dataset antes de ponerlo a circular.1 Model Cards hizo algo parecido para modelos, obligándonos a declarar uso previsto, métricas, grupos evaluados y limitaciones.2 Y el ML Test Score recordaba una cosa muy de ingeniería: un sistema de ML no está maduro solo porque tenga una métrica alta; necesita tests de datos, monitorización, reproducibilidad y gestión de cambios.3

CapítuloPreguntaArtefacto mental
01¿Qué dato tenemos y de dónde viene?Contrato, linaje y dataset card.
02¿El dato cumple lo mínimo?Gate de calidad.
03¿Medimos sin engañarnos?Split y manifiesto de evaluación.
04¿Cómo representamos la información?Features, embeddings y búsqueda.
05¿A quién falla la decisión?Slices, políticas y mitigación.
06¿Qué pasa cuando llega producción?DataOps, drift, trazas y postmortem.
07¿Una acción cambia algo?Experimento, causalidad y rollout.

Si una persona termina este facsímil y solo recuerda una cosa, que sea esta: cada métrica necesita una historia de procedencia, una unidad de análisis, una ventana, un contrato y una decisión permitida.

Cómo encaja todo

Este mapa une el facsímil completo. No intenta repetir cada tabla, sino mostrar el flujo profesional: del dato inicial a la decisión de publicación. La lectura buena no es lineal del todo: contrato, calidad, split, representación, slices, operación y causalidad se revisan entre sí.

graph TD
    subgraph "Facsímil 08: ciencia de datos para IA"
        C01["Cap. 1<br/>contrato · linaje · card"]
        C02["Cap. 2<br/>schema · duplicados · etiquetas"]
        C03["Cap. 3<br/>split · muestreo · leakage"]
        C04["Cap. 4<br/>features · embeddings"]
        C05["Cap. 5<br/>slices · decisión"]
        C06["Cap. 6<br/>DataOps · drift · SLO"]
        C07["Cap. 7<br/>experimentos · causalidad"]
    end
    subgraph "Salida profesional"
        AUDIT["Auditoría<br/>qué falla y por qué"]
        EVIDENCE["Evidencia reproducible<br/>reportes · hashes · trazas"]
        DECISION["Decisión<br/>pass · review · block"]
        LAB["Laboratorio<br/>dos retos aplicables"]
    end
    subgraph "Conecta con otros facsímiles"
        F4["Caja de herramientas<br/>APIs · RAG · embeddings"]
        F6["Construir y operar<br/>observabilidad · runbooks"]
        F7["Evaluar y calibrar<br/>métricas · interpretación"]
        F9["Gobernanza<br/>políticas · evidencia"]
        F11["Producto y UX<br/>impacto en uso real"]
    end

    C01 -->|"declara procedencia"| C02
    C02 -->|"bloquea datos rotos"| C03
    C03 -->|"protege medición"| C04
    C04 -->|"define señal"| C05
    C05 -->|"marca segmentos críticos"| C06
    C06 -->|"aporta trazas"| C07
    C07 -->|"mide intervención"| DECISION

    C01 -->|"documenta"| EVIDENCE
    C02 -->|"genera gates"| AUDIT
    C03 -->|"evita autoengaño"| AUDIT
    C04 -->|"explica matriz y vector"| EVIDENCE
    C05 -->|"matiza la media"| AUDIT
    C06 -->|"vigila producción"| EVIDENCE
    C07 -->|"separa predicción y acción"| DECISION

    AUDIT -->|"ordena"| DECISION
    EVIDENCE -->|"defiende"| DECISION
    DECISION -->|"se practica en"| LAB

    F4 -->|"aporta sistemas que medir"| C04
    F4 -->|"entra en experimentos RAG"| C07
    F6 -->|"aporta operación"| C06
    F7 -->|"aporta métricas"| C03
    F7 -->|"explica resultados"| C05
    DECISION -->|"deja controles para"| F9
    DECISION -->|"cambia experiencia"| F11

    style C01 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C02 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C03 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C04 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C05 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C06 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style C07 fill:#F5F5F5,stroke:#000000,stroke-width:2
    style AUDIT fill:#F5F5F5,stroke:#000000,stroke-width:2
    style EVIDENCE fill:#F5F5F5,stroke:#000000,stroke-width:2
    style DECISION fill:#F5F5F5,stroke:#000000,stroke-width:2
    style LAB fill:#F5F5F5,stroke:#000000,stroke-width:2
    style F4 stroke-dasharray: 5 5
    style F6 stroke-dasharray: 5 5
    style F7 stroke-dasharray: 5 5
    style F9 stroke-dasharray: 5 5
    style F11 stroke-dasharray: 5 5

Anatomía visual: de dataset a decisión

El cierre del facsímil necesitaba una figura propia porque la ciencia de datos no termina en el dataframe. Termina cuando alguien puede explicar qué dato entró, qué se midió, qué se corrigió, qué quedó fuera y qué decisión se tomó.

Release de datos: no se publica una media, se publica una decisión Contrato, calidad, split, slices, operación y experimento producen una evidencia única. 1 · Contrato unidad de análisis schema · linaje · licencia 2 · Calidad nulos · duplicados etiquetas · leakage 3 · Split train · validation · test tiempo · grupos · holdout 4 · Señal features · embeddings normalización · versión 5 · Slices segmentos críticos errores y mitigación Operación drift · SLI · SLO trazas · runbook · gate CI Experimento exposure event · métrica guardrails · ventana Decisión pass · review · block owner · fecha · evidencia La evidencia buena permite repetir la decisión sin repetir la discusión. IA para gente curiosa / Facsímil 08 / Capítulo 08 / 686f6c61
La revisión de datos une contrato, calidad, medición, segmentos, operación y experimento. El resultado útil no es “la métrica sube”, sino una decisión trazable.

Laboratorio

Un laboratorio, dentro de este libro, es un espacio de práctica guiada. No está pensado para pillar a nadie, sino para obligarnos a trabajar como trabajaríamos fuera del libro: con datos imperfectos, contratos, umbrales, decisiones y una salida que otra persona pueda revisar.

En este laboratorio vamos a tocar:

TemaCapítulos que lo sostienen
Contrato y linajeCapítulos 01 y 02.
Split y evaluaciónCapítulo 03.
Slices críticosCapítulo 05.
Operación y trazabilidadCapítulo 06.
Experimento y decisión causalCapítulo 07.

El kit está en:

kit/

Cómo trabajar este laboratorio

No lo plantees como “ejecutar un script y copiar el estado”. Plantealo como una revisión de release. En una empresa o en un proyecto universitario serio, el resultado útil no es decir que un sistema “va bien” o “va mal”, sino dejar una cadena de evidencia:

PasoQué hacesQué artefacto miras
1Lees el contrato antes de mirar resultados.contracts/final_review_contract.json.
2Ejecutas la auditoría final.ops/run_final_review.py.
3Separas bloqueo, revisión y pase.output/final_decision.md.
4Compruebas comportamiento por split.output/final_split_summary.csv.
5Compruebas slices críticos.output/final_slice_summary.csv.
6Escribes un plan de corrección.correction_plan.md.
7Diseñas una intervención medible.next_experiment_plan.md.
8Validamos una entrega profesional.ops/check_student_submission.py.

La entrega fuerte contiene una decisión y una siguiente iteración. Si solo entregas “Estado: block”, te falta ingeniería. Un bloqueo bien explicado debe decir qué se rompe, por qué importa, qué evidencia lo demuestra y qué harías antes de volver a medir.

Antes de ejecutar, abre también las evidencias fuente del kit:

evidence/traceability_policy.md
evidence/data_quality_contract.json
evidence/slice_remediation_plan.md
evidence/experiment_exposure_contract.json
evidence/data_release_scope.md

Estas piezas salen directamente del temario: trazabilidad y operación del capítulo 06, calidad y contrato del capítulo 02, slices del capítulo 05, experimento del capítulo 07 y alcance/linaje del capítulo 01. No hay una capa nueva escondida en el laboratorio; solo estamos juntando lo que ya aprendimos.

Reto 1: auditar si un mini sistema puede publicarse

Contexto

Un equipo quiere publicar una automatización para priorizar casos académicos. Tienes un dataset pequeño con splits, predicciones, trazas, citas, latencias y variantes de experimento. La pregunta no es si el modelo “parece bueno”. La pregunta es si hay evidencia suficiente para publicarlo.

La situación es realista: el sistema acierta algunos casos, cita bastante bien y parece tener valor. El problema es que una release no se decide por una impresión global. Se decide por contrato. Si faltan trazas, si hay campos incompletos o si un slice crítico falla, el sistema puede ser prometedor y aun así no ser publicable.

Objetivo

Generar una decisión de publicación reproducible: pass, review o block.

Enunciado

Ejecuta:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/run_final_review.py --write
cat output/final_decision.md
cat output/technical_decision_memo.md
cat output/source_evidence_review.md
cat output/final_split_summary.csv
cat output/final_slice_summary.csv
cat output/correction_plan.md
cat output/next_experiment_plan.md
python3 -m json.tool output/final_review_report.json
python3 -m json.tool output/data_release_ci_gate.json

Después responde:

  1. ¿Qué checks bloquean?
  2. ¿Qué checks quedan en revisión?
  3. ¿Qué slices concentran fallos?
  4. ¿Qué cambiarías antes de publicar?
  5. ¿Qué parte del contrato no cambiarías aunque el equipo tenga prisa?
  6. ¿Qué evidencia enseñarías en una revisión de release?
  7. ¿Qué experimento diseñarías para el slice más débil?
  8. ¿Qué evidencia fuente existe para cada parte de la decisión?
  9. ¿Qué comando usarías como gate de CI?

Resolución paso a paso

Primero miramos contrato. El dataset cumple columnas, así que el problema no es schema. Eso es importante: un schema correcto no significa que el sistema sea publicable. Solo significa que el formato mínimo existe.

Después miramos trazabilidad. Hay un evento sin trace_id; eso bloquea porque no podemos reconstruir una decisión concreta. Si una persona pregunta “por qué se priorizó o no se priorizó este caso”, nos falta la pieza que conecta dato, predicción, decisión y ejecución. No es un detalle administrativo: es la diferencia entre depurar y adivinar.

Luego miramos campos obligatorios. Hay un caso con campos incompletos. También bloquea. En el capítulo 02 insistimos en esto: si la ingesta deja pasar filas incompletas, el modelo puede estar midiendo ausencias, rutas alternativas o errores de formulario.

Después miramos evaluación. test_accuracy queda en 0.6, por debajo del umbral 0.75. No bloquea por sí solo en el contrato, pero deja el sistema en revisión. La lectura correcta no es “el modelo es malo”, sino “con este split y este umbral no alcanza el mínimo que dijimos antes de mirar”.

Finalmente miramos slices: language=en, segment=practicas y source=form concentran misses. Eso conecta con el capítulo 05: la media global no basta. Si el sistema falla donde más necesitamos robustez, no se publica globalmente.

CheckValorUmbralLectura
missing_trace_rate0.0833330.0Bloquea: hay decisión sin reconstrucción.
missing_required_fields_rate0.0833330.0Bloquea: hay dato incompleto.
latency_p95_ms730720Revisión: la ruta p95 supera SLO.
test_accuracy0.60.75Revisión: el test no sostiene publicación.
citation_valid_rate0.9166670.9Pasa: la capa documental aguanta.
language=en miss rate0.80.25Revisión fuerte: slice crítico muy débil.
segment=practicas miss rate0.750.25Revisión fuerte: segmento problemático.
source=form miss rate0.6666670.25Revisión fuerte: fuente problemática.

Respuesta modelo

La decisión correcta es:

Estado: block

Motivo: faltan trazas, hay campos obligatorios incompletos, test no alcanza el umbral y los slices críticos fallan demasiado. Que citation_valid_rate pase no compensa los bloqueos; una parte sana del sistema no convierte en publicable una decisión que no se puede reconstruir.

Por qué funciona

La solución no intenta arreglar el modelo a ciegas. Separa problemas:

ProblemaCapítulo que lo explicaAcción
Falta trazabilidad06Bloquear publicación hasta recuperar trace_id.
Campos incompletos02Corregir contrato y pipeline de ingesta.
Test bajo03Revisar split y evaluación.
Slices con misses altos05Revisar datos, política y umbrales por segmento.

Cómo explicarlo a otra persona

“No publicaría este sistema todavía. No porque una métrica sea fea, sino porque hay decisiones que no podríamos reconstruir, datos incompletos y segmentos críticos donde falla demasiado. Antes de automatizar, hay que arreglar trazabilidad, calidad y comportamiento por slice.”

Entrega profesional esperada

La entrega no debería ser una respuesta suelta, sino una carpeta de revisión:

final-data-release-review/
  final_decision.md
  technical_decision_memo.md
  final_review_report.json
  final_split_summary.csv
  final_slice_summary.csv
  source_evidence_review.md
  correction_plan.md
  next_experiment_plan.md
  data_release_ci_gate.json

Como gate de CI:

python3 ops/run_final_review.py --write --fail-on-blocker

Si el estado final es block, el comando debe salir con código 2. Eso convierte una discusión en una regla ejecutable: no se publica si falta trazabilidad o si entran filas incompletas.

correction_plan.md debe incluir:

  1. Qué campos o trazas se corrigen.
  2. Qué validación impide que el fallo vuelva a entrar.
  3. Qué slice se prioriza y por qué.
  4. Qué métrica se volverá a mirar.
  5. Qué umbral no se cambia después de ver el resultado.

Variaciones

  1. Cambia max_latency_p95_ms a 760 y observa qué deja de estar en revisión.
  2. Añade un nuevo slice crítico por language=ca.
  3. Corrige el trace_id faltante y vuelve a ejecutar.
  4. Ejecuta la variante del alumno:
python3 ops/run_final_review.py \
  --data data/final_project_events_student.csv \
  --output-dir output/student \
  --write

cat output/student/final_decision.md
cat output/student/technical_decision_memo.md
cat output/student/source_evidence_review.md
python3 -m json.tool output/student/data_release_ci_gate.json

La variante student corrige trazabilidad y campos obligatorios. Si lo has entendido, deberías ver que desaparece el bloqueo, pero no desaparece la revisión: siguen abiertos test, latencia y slices críticos. Esa diferencia es justo la lectura profesional.

Reto 2: diseñar una mejora medible sin confundir predicción con intervención

Contexto

El equipo propone una plantilla guiada para casos de prácticas en inglés. Los datos muestran que ese segmento falla. Pero no sabemos si la plantilla cambiará el resultado o si solo estamos identificando casos difíciles.

Objetivo

Diseñar un experimento aplicable y conectado con los hallazgos del reto 1.

Enunciado

Usa el kit del capítulo 07 desde la raíz del repositorio. Este reto no vive dentro de kit descargable: reutiliza el material experimental de kit descargable para que quede claro qué parte del facsímil estás poniendo en juego.

python3 kit/ops/validate_experiment_design.py --write
python3 kit/ops/analyze_ab_experiment.py --write
python3 kit/ops/analyze_rag_experiment.py --write
python3 kit/ops/summarize_metric_maturation.py --write
python3 kit/ops/analyze_cluster_interference.py --write
python3 kit/ops/ci_experiment_gate.py --write
cat kit/output/experiment_design_validation.md
cat kit/output/experiment_decision.md
cat kit/output/rag_experiment_decision.md
cat kit/output/metric_maturation_decision.md
cat kit/output/cluster_interference_decision.md
cat kit/output/ci_gate_decision.md

Diseña una mejora para el segmento segment=practicas y language=en:

  1. Unidad de asignación.
  2. Tratamiento y control.
  3. Métrica primaria.
  4. Guardrails.
  5. Exposure event.
  6. MDE y política de peeking.
  7. Rollout.
  8. Plan de análisis.
  9. Catálogo de métricas.
  10. Riesgo de interferencia por equipo, cola u operador.
  11. Qué harías si el resultado queda en review.

Resolución paso a paso

La unidad debe ser el caso académico, no una fila suelta de log. Si una misma decisión aparece en varios eventos, la unidad de asignación sigue siendo el caso. Si varios casos comparten operador o cola, hay que preguntarse si existe interferencia y si conviene asignar por clúster.

El tratamiento puede ser una plantilla guiada más recuperación documental revisada para prácticas internacionales. El control es el flujo actual. La métrica primaria puede ser resolución correcta a 7 días. Los guardrails deben incluir cita válida, latencia, coste y feedback negativo.

El exposure event debe registrar que el caso realmente recibió la plantilla y la versión del RAG. Si el sistema cae a fallback, esa unidad no se analiza igual. Para no engañarnos, calculamos MDE antes de empezar y fijamos una política de peeking: una sola lectura al cerrar ventana o análisis secuencial explícito.

El plan de análisis se escribe antes de mirar resultados. Debe decir hipótesis, población, tratamiento, control, métrica primaria, ventanas, exclusiones y regla de decisión. El catálogo de métricas evita que resolved_day_7, citation_valid o latency_ms cambien de significado entre personas.

La parte importante: el resultado del kit puede quedar en review. Eso no es fracaso. Significa que hay señal, pero falta precisión, muestra, maduración o robustez por slice. En ingeniería, review es una salida útil si explica qué medir después.

Respuesta modelo

PiezaDiseño
Unidadcase_id.
TratamientoPlantilla guiada + retriever revisado para prácticas internacionales.
ControlFlujo actual.
Métrica primariaresolved_day_7.
Guardrailscitation_valid, latency_ms, cost_eur, negative_feedback.
Exposure eventexperiment_exposure con case_id, variante, versión de prompt, versión de retriever y trace.
MDEDefinido antes de iniciar; si se busca 0.05, hace falta mucha más muestra que un ejemplo de aula.
PeekingNo decidir antes de la ventana final sin regla secuencial.
RolloutA/A, A/B, 5%, 25%, 50%, 100% con rollback por guardrail.
Plan de análisisHipótesis, población, unidad, ventanas, exclusiones y regla pass/review/block antes de mirar.
Catálogo de métricasPrimaria, guardrails y diagnósticas con unidad, ventana y dirección.
InterferenciaRevisar si operador, equipo o cola comparten aprendizaje; si ocurre, considerar cluster_id.
Salida si queda reviewAmpliar muestra, repetir ventana, limitar rollout o corregir instrumentación.

Por qué funciona

Porque no usa el modelo predictivo como prueba de intervención. El diseño pregunta si una acción cambia el resultado, registra exposición real y protege guardrails. Además, conecta con el reto 1: no actúa sobre todo el sistema, sino sobre el segmento que la auditoría mostró como problemático.

También funciona porque separa tres cosas que suelen mezclarse:

CosaQué preguntaArtefacto
Auditoría¿Dónde falla el sistema actual?Reto 1.
Intervención¿Qué cambio concreto proponemos?Tratamiento/control.
Evidencia causal¿Ese cambio modifica el resultado?Experimento, exposure event, ATE/CATE y guardrails.

Cómo explicarlo a otra persona

“Primero encontramos dónde falla el sistema. Luego diseñamos una intervención concreta para ese segmento y la medimos como experimento, no como intuición. Si mejora resolución sin romper citas, latencia ni coste, podemos plantear rollout. Si no, aprendimos sin publicar a ciegas.”

Variaciones

  1. Cambia la unidad de asignación a student_id y explica qué mejora o empeora.
  2. Añade una métrica de satisfacción a 14 días.
  3. Diseña el mismo experimento como bandit y explica qué perderías en interpretación.

Entrega profesional esperada

next-experiment-plan/
  analysis_plan.json
  metric_catalog.json
  feature_flag_contract.json
  warehouse_schema.sql
  experiment_decision.md
  rollout_plan.md

La entrega debe defender una decisión concreta: publicar nada, medir más, limitar a un slice, repetir el experimento o pasar a rollout controlado. No basta con escribir un diseño bonito; hay que decir qué evidencia lo haría avanzar y qué evidencia lo frenaría.

Validar la entrega

Para que el laboratorio no se quede en prosa, el kit incluye un checker:

# Descomprime el ZIP del capítulo y ejecuta estos comandos dentro de esa carpeta
python3 ops/check_student_submission.py --submission-dir solutions/reference --write
cat output/student_submission_report.md

Una entrega propia debería tener esta forma:

solutions/mi-equipo/
  decision_memo.md
  correction_plan.md
  next_experiment_plan.md
  residual_data_risk.md
  data_release_ci_gate.json
  traceability_policy.md
  data_quality_contract.json
  slice_remediation_plan.md
  experiment_exposure_contract.json

El checker no sustituye la revisión humana. Solo evita entregas vacías: comprueba que hay decisión, plan de corrección, plan experimental, riesgo residual, salida CI y evidencias de trazabilidad, calidad, slices y exposición.

Rúbrica de evaluación

CriterioPesoQué espero ver
Lectura del contrato15Identifica columnas, SLOs, splits y slices críticos antes de mirar resultados.
Decisión de release20Defiende block, review o pass con checks y evidencia.
Corrección de datos20Corrige trazabilidad y campos sin relajar umbrales.
Análisis por slices15Explica por qué la media global no basta y qué slice priorizaría.
Plan experimental15Conecta la intervención con case_id, exposure event, métrica primaria y guardrails.
Gate CI10Produce una salida máquina y entiende cuándo debe fallar.
Claridad profesional5El memo puede leerlo ingeniería, datos, producto u operación.

Una entrega excelente no intenta maquillar el resultado. Enseña qué se puede defender, qué no, qué dato se corrige, qué slice se prioriza y qué experimento mediría el siguiente cambio.

Vocabulario aprendido

TérminoQué significa aquíCómo lo usarías en una entrega
Decisión de release de datosDictamen técnico sobre si los datos y sus derivados permiten automatizar, revisar o bloquear.Lo escribes como pass, review o block, con checks y evidencia.
Evidencia reproducibleReportes, hashes, manifests, trazas, contratos y salidas que otra persona puede regenerar.La adjuntas al memo para que la revisión no dependa de confianza verbal.
Gate de datosRegla ejecutable que impide publicar si fallan calidad, split, trazabilidad, slices o SLOs.Lo conectas a CI o a la revisión de release.
Corrección sin relajar umbralesArreglar datos, trazas o contratos sin bajar el listón después de ver el fallo.Mantienes el contrato y corriges la causa, no la métrica incómoda.
Siguiente experimentoIntervención medible para aprender si una acción mejora el sistema en un slice concreto.Diseñas unidad, exposición, métrica primaria, guardrails y criterio de parada.

Dónde solía tropezar yo

TropiezoPor qué ocurreAntídoto
Querer publicar por una métrica globalLa media resume demasiado.Mirar contrato, test, slices y operación.
Arreglar el modelo antes de arreglar datosParece la parte más interesante.Revisar trazabilidad y calidad primero.
Diseñar experimentos sin exposure eventLa asignación parece suficiente.Registrar exposición real y versión exacta.
Ignorar ventanas de maduraciónQueremos decidir rápido.Declarar day_1, day_7 o la ventana que toque.

Antes de pasar página

Antes de cerrar el facsímil, deberías poder responder:

  1. ¿Qué diferencia hay entre contrato de datos y contrato de experimento?
  2. ¿Por qué un dataset con schema correcto puede quedar bloqueado?
  3. ¿Qué hace que un split sea honesto?
  4. ¿Por qué los slices críticos pueden cambiar una decisión?
  5. ¿Qué SLI de DataOps bloquearía una publicación?
  6. ¿Qué diferencia hay entre asignación y exposición?
  7. ¿Por qué un experimento en review no es necesariamente un fracaso?
  8. ¿Qué entregarías como evidencia reproducible de una decisión?
  9. ¿Por qué no deberías cambiar umbrales después de mirar el resultado?
  10. ¿Qué diferencia hay entre corregir trazabilidad y mejorar el modelo?
  11. ¿Qué comprobaría un gate de CI de datos?

En resumen

IdeaQué te llevas
Los datos son sistema.No son entrada pasiva del modelo.
La evaluación es una promesa.Si el split o los slices fallan, la métrica no basta.
La operación decide.Sin trazas, SLOs y runbooks, no hay publicación responsable.
La causalidad cambia la pregunta.Predecir no prueba que una acción funcione.
El laboratorio junta todo.La salida profesional es una decisión reproducible, no una impresión.

Para saber más

Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML test score: A rubric for ML production readiness and technical debt reduction. 2017 IEEE International Conference on Big Data, 1123-1132. https://doi.org/10.1109/BigData.2017.8258038

Gebru, T. et al. (2021). Datasheets for datasets. Communications of the ACM, 64(12), 86-92. https://doi.org/10.1145/3458723

Kohavi, R., Longbotham, R., Sommerfield, D. y Henne, R. M. (2009). Controlled experiments on the web: Survey and practical guide. Data Mining and Knowledge Discovery, 18(1), 140-181. https://doi.org/10.1007/s10618-008-0114-1

Mitchell, M. et al. (2019). Model cards for model reporting. Proceedings of the Conference on Fairness, Accountability, and Transparency, 220-229. https://doi.org/10.1145/3287560.3287596

National Institute of Standards and Technology. (2023). Artificial Intelligence Risk Management Framework (AI RMF 1.0). https://doi.org/10.6028/NIST.AI.100-1

Sambasivan, N. et al. (2021). “Everyone wants to do the model work, not the data work”: Data cascades in high-stakes AI. Proceedings of CHI 2021, 1-15. https://doi.org/10.1145/3411764.3445518

Sculley, D. et al. (2015). Hidden technical debt in machine learning systems. Advances in Neural Information Processing Systems 28. https://papers.nips.cc/paper/5656-hidden-technical-debt-in-machine-learning-systems

Notas

  1. Gebru, T. et al. (2021). Datasheets for datasets. Communications of the ACM, 64(12), 86-92. https://doi.org/10.1145/3458723

  2. Mitchell, M. et al. (2019). Model cards for model reporting. Proceedings of the Conference on Fairness, Accountability, and Transparency, 220-229. https://doi.org/10.1145/3287560.3287596

  3. Breck, E., Cai, S., Nielsen, E., Salib, M. y Sculley, D. (2017). The ML test score: A rubric for ML production readiness and technical debt reduction. 2017 IEEE International Conference on Big Data, 1123-1132. https://doi.org/10.1109/BigData.2017.8258038