MÓDULO 15 · MLOPS: PIPELINES CON ZENML · 25 MIN

Reproducibilidad: repetir un entrenamiento

Reproducible no significa «documentado»: significa que si vuelves a lanzar el mismo entrenamiento dentro de seis meses obtienes exactamente el mismo modelo. Para eso hacen falta cuatro cosas a la vez — los mismos datos, el mismo código, los mismos parámetros y la misma aleatoriedad—, y basta con que falte una para que el resultado se convierta en una anécdota que no se puede defender.
01 — El modelo huérfano
El fallo que este módulo viene a evitar

El escenario del material es reconocible: alguien entrena un modelo, se va de la empresa, y meses después nadie consigue reproducir su precisión. No porque el código se perdiera —está en el repositorio— sino porque el código no era suficiente.

Lo que faltabaPor qué no estaba en el repositorio
La versión exacta de los datosSe cargaban de una ruta que hoy tiene otro contenido
Los hiperparámetros usados de verdadSe ajustaron a mano en la última ejecución
Las semillas aleatoriasNadie las fijó
Variables de entornoVivían en la máquina de esa persona

Y hay un contexto que lo convierte en algo más que una molestia: en sectores regulados, poder recrear el modelo exacto es un requisito. Hay que ser capaz de explicar por qué el sistema tomó una decisión, y eso empieza por poder reconstruir el modelo que la tomó.

02 — Las cuatro condiciones
Qué tiene que quedar fijado
CondiciónCómo se consigueQué la rompe
Mismos datosArtifacts versionados: cada dataset es inmutable y tiene identidadLeer de una ruta o una consulta que cambia
Mismo códigoEl pipeline registra qué versión del código produjo cada ejecuciónLógica fuera de los steps, en el cuaderno o en el shell
Mismos parámetrosPasarlos como parámetros del step, no como constantes editadas a manoCambiar un número «solo para probar»
Misma aleatoriedadFijar la semilla en todos los pasos que la usenUn solo componente aleatorio sin semilla

La cuarta es la que más se subestima, y el matiz está en «todos». El reparto entre entrenamiento y prueba usa aleatoriedad; el modelo también; a veces la inicialización de una red y el barajado de un lote, además. Fijar la semilla en el entrenador y olvidarla en el split ya rompe la reproducibilidad, y el síntoma —resultados que varían un poco entre ejecuciones— es lo bastante pequeño como para atribuirlo al azar y seguir adelante.

// una sola fuente de azar sin fijar basta para que nada sea repetible
03 — El modelo como artifact
Devolver el objeto, no los pesos

Cuando un step de entrenamiento devuelve el modelo, el framework detecta de qué biblioteca es y lo serializa en el formato adecuado, junto a sus metadatos: cuándo se ejecutó, con qué código, con qué entradas y con qué métricas asociadas. Eso convierte el modelo en algo que se puede auditar y desplegar sin volver a entrenar.

De ahí dos consejos que parecen menores y no lo son. El primero: devuelve el objeto modelo completo, no solo los pesos — un objeto entrenado se puede cargar y usar; un array de pesos necesita que alguien recuerde la arquitectura. El segundo: si la salida no se puede serializar, el paso falla, y esa es una restricción sana. Obliga a que la frontera entre pasos sean datos y no objetos vivos.

Auditoría Cuidado con el ejemplo de «puerta de calidad» de este material, porque enseña el antipatrón con el nombre del patrón. El texto promete un step de validación que «detiene el pipeline ante datos erróneos», y el código detecta los nulos, imprime la palabra «Error», hace dropna() y continúa — con un comentario que reconoce que en un caso real convendría lanzar una excepción. Un print no es una señal: en un pipeline desatendido no lo ve nadie. Peor: su propia tabla de troubleshooting dice que un AssertionError significa «el validador falló, como se esperaba», y no hay ningún assert en ese código. La pregunta que desmonta cualquier validador: si el dato es malo, ¿qué pasa exactamente? Si la respuesta es «se imprime un mensaje», no hay puerta.
Para hacer
La prueba de las dos ejecuciones

Ejecuta tu entrenamiento dos veces seguidas, sin cambiar nada, y compara la métrica con todos los decimales que tengas. Si no son idénticas, tienes una fuente de azar sin fijar — y encontrarla es el ejercicio: ve poniendo semillas de una en una hasta que las dos ejecuciones coincidan.

Cuando coincidan, apunta cuántas semillas hicieron falta. Ese número suele sorprender, y es la medida honesta de cuántos sitios de tu código eran no deterministas sin que lo supieras.