2 · Reproducibilidad y estructura del proyecto
Si no puedes reconstruir exactamente el mismo modelo mañana, en realidad no tienes un modelo. Una estructura de proyecto disciplinada, dependencias fijadas, semillas aleatorias fijas y un único artefacto serializado son lo que hace reproducible al ML.
La reproducibilidad significa que cualquiera (incluido tu yo futuro) puede recrear exactamente el mismo modelo desde cero — lograda con una estructura de proyecto limpia, versiones de dependencias FIJADAS, semillas aleatorias FIJAS y un único artefacto serializado (`joblib`) que viaja con su propio preprocesamiento.
Sin esto:
Sin reproducibilidad, un modelo que funcionó el mes pasado no puede reconstruirse — una dependencia se actualizó silenciosamente, nunca se fijó una semilla, el script vivía solo en un notebook — y nunca puedes explicar ni arreglar lo que producción está haciendo.
En un notebook, "funciona" a menudo significa "funcionó una vez, en mi máquina, en esta sesión exacta". Producción exige más: cualquiera debe poder reconstruir el modelo idéntico. Cuatro hábitos te llevan ahí.
1. Una estructura de proyecto disciplinada. El código, los datos y las salidas viven en carpetas separadas y predecibles en lugar de mezclados en un solo notebook:
my-model/
├── src/ # el código: train.py, predict.py, data.py
├── data/ # datasets (versionados con DVC — capítulo 5)
├── models/ # el artefacto serializado: model.joblib
├── config.yaml # todas las perillas: rutas, hiperparámetros, la semilla
├── requirements.txt # versiones de dependencias FIJADAS
└── README.md
Cualquiera puede clonar esto, leer config.yaml, ejecutar python src/train.py y obtener models/model.joblib — sin estado oculto de notebook.
2. Dependencias fijadas (pinned). scikit-learn no es una cosa fija — cambia entre versiones. Un modelo entrenado con scikit-learn==1.3.0 puede que ni siquiera se cargue con 1.5.0, y los resultados numéricos pueden variar. Así que no escribes scikit-learn en requirements.txt; escribes scikit-learn==1.3.2 con una versión exacta. "Fijar" (pin) congela cada dependencia para que una reconstrucción meses después use las mismas librerías, no lo más nuevo de ese día.
3. Semillas aleatorias fijas. Las divisiones train/test, la inicialización de pesos y los internos del modelo usan aleatoriedad. Fija la semilla (np.random.seed(42), random_state=42) y las elecciones "aleatorias" se vuelven deterministas y repetibles — la misma división, el mismo modelo, en cada ejecución. Sin una semilla, dos ejecuciones del mismo script producen dos modelos distintos.
4. Un solo artefacto serializado. Como demostraste en bc-py-59, joblib.dump del Pipeline ajustado completo guarda el preprocesamiento (medias del escalador, categorías del codificador) junto con el modelo. Ese único archivo es el entregable desplegable — recárgalo y predice sobre filas crudas por sí mismo, sin preprocesamiento manual que se pueda hacer mal. La celda ejecutable de abajo prueba que ese artefacto hace un round-trip de extremo a extremo.
Un `config.yaml` que centraliza la semilla, las rutas de datos, los hiperparámetros y la ruta de salida — cada perilla que cambia el resultado, en un archivo bajo control de versiones.
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
¿Por qué fijar versiones exactas de dependencias (`scikit-learn==1.3.2`) en lugar de solo listar el nombre del paquete?
- Un proyecto reproducible separa código (`src/`), datos (`data/`) y artefactos (`models/`), con todas las perillas en `config.yaml` y versiones exactas en `requirements.txt`.
- Versiones de dependencias fijadas + una semilla aleatoria fija hacen determinista una reconstrucción: las mismas librerías y la misma aleatoriedad producen el mismo modelo cada vez.
- `joblib.dump` del Pipeline ajustado completo es el único artefacto desplegable; recargado, predice sobre filas crudas por sí mismo y coincide con el original exactamente.
Todo repo serio de ML tiene este esqueleto — `src/`, `config.yaml`, un `requirements.txt` fijado, un artefacto guardado — porque la reproducibilidad es la precondición de todo lo demás en este track (Docker, CI/CD, despliegue).
Si lo quitas: Desplegarías un modelo que nadie (ni siquiera tú) puede reconstruir — cuando producción se comporta mal no podrías recrear el modelo exacto para depurarlo, el peor lugar donde estar en operaciones de ML.