English · Español
Lab 01 — Ablación de inicialización: el experimento estrella de las tres curvas¶
Objetivo: mostrar que la inicialización (init) por sí sola — mismos datos, misma arquitectura, mismo optimizador — convierte una red de "entrena" a "no entrena".
Tiempo estimado: 90–120 minutos.
Prerrequisito: lab 00 commiteado.
Qué produces¶
Un directorio experiments/10-init-matters/ que contiene:
train.py— tu script de entrenamiento.losses.json— tres trayectorias de pérdida (uniforme, Xavier, Kaiming).loss_curves.png— tres curvas en los mismos ejes.manifest.json— estándar.README.md(3–4 párrafos) explicando qué entrenaste y qué pasó.
El montaje¶
Un MLP de 12 capas con activaciones ReLU, dimensión oculta 256, entrenado durante 1000 pasos sobre el problema de clasificación de juguete de la Fase 9 (o generado sintéticamente aquí — ver abajo).
Tres ejecuciones idénticas que difieren sólo en la inicialización:
- Uniforme
[-0.5, 0.5]. - Xavier
N(0, 1/n_in). - Kaiming
N(0, 2/n_in).
Resultado esperado:
- Uniforme: explosión del paso hacia adelante → NaN en ~20 pasos, o ReLU saturada → la pérdida se estanca al azar.
- Xavier: entrena, pero lento. La curva de pérdida desciende perezosamente.
- Kaiming: entrena como se espera. Descenso suave.
La figura estrella son las tres curvas en los mismos ejes, claramente diferenciadas.
Datos de juguete¶
Si no construiste ya el dataset "safe/unsafe token" de juguete de la Fase 9, genera uno sintético:
- 1000 ejemplos de entrenamiento, 200 de validación.
- Entrada: vectores gaussianos de 256 dimensiones.
- Etiqueta: 0 si la suma de los primeros 10 elementos es negativa, 1 en caso contrario (determinista, linealmente separable en las primeras 10 dimensiones).
Esto es trivialmente aprendible por una red de 1 capa. El punto del experimento no es la dificultad de la tarea — es que una mala inicialización convierte una tarea trivialmente aprendible en irresoluble.
TODOs¶
Bloque A — escribe el bucle de entrenamiento¶
- MLP de 12 capas, oculta 256, activaciones ReLU entre capas, sin norm, sin residual.
- Usa
minitorch.nn.Linear+minitorch.nn.ReLUde la Fase 9. - Pérdida: entropía cruzada.
- Optimizador: SGD con momentum 0.9, LR 1e-3.
- Tamaño de batch 64.
- 1000 pasos en total.
- Registra la pérdida en cada paso.
Bloque B — tres ejecuciones¶
- Ejecución con init = uniforme[-0.5, 0.5]. Guarda la trayectoria de pérdida.
- Ejecución con init = Xavier. Guarda.
- Ejecución con init = Kaiming. Guarda.
- Misma semilla para el barajado de datos entre ejecuciones (para que las tres vean secuencias de batches idénticas).
- Semilla distinta para el muestreo de pesos de cada inicialización (para que las inicializaciones en sí sean draws independientes).
Bloque C — gráfico¶
- matplotlib. eje x: paso (0 a 1000). eje y: pérdida (lineal o logarítmica — prueba ambas, elige la más informativa).
- Tres curvas con colores distintos y leyenda.
- Anota: marcadores de NaN si alguna ejecución diverge; marcadores de estancamiento si alguna se atasca en la pérdida aleatoria.
- Guarda como
loss_curves.png.
Bloque D — interpreta¶
En README.md, responde:
- ¿En qué paso produjo la inicialización uniforme su primer NaN (o saturación)?
- ¿Cuál es la pérdida final de Xavier vs la de Kaiming?
- ¿Está Xavier entrenando o casi sin entrenar? Calcula la pendiente de su curva de pérdida sobre los últimos 200 pasos.
- Predice, sin ejecutar: si aumentaras la profundidad de 12 a 24 capas, ¿cómo cambiaría cada una de las tres curvas? Justifica brevemente.
Bloque E — manifest¶
Estándar. results_summary debería incluir {steps_to_nan_uniform, final_loss_xavier, final_loss_kaiming}.
Restricciones¶
- Sin normalización. El lab 02 es para eso.
- Sin residuales. El lab 03 es para eso.
- Misma semilla para datos, semillas independientes para pesos. No los confundas.
- Ejecuta con el governor
performance. La variación en tiempo por paso ruidearía la comparación.
Condiciones de parada¶
Hecho cuando:
- El directorio tiene los cinco archivos.
- El gráfico de tres curvas está commiteado y visualmente nítido.
- La ejecución uniforme diverge o se estanca; la de Kaiming entrena; la de Xavier está en algún punto intermedio.
- El README responde las cuatro preguntas del Bloque D.
Trampas¶
- Las tres curvas se ven idénticas. Probablemente no estés re-inicializando entre ejecuciones. Comprueba que haces
model = build_mlp(init=...)cada vez, no sólooptimizer.zero_grad(). - Las tres curvas divergen. Tu LR es demasiado alto. Bájalo a 1e-4 e inténtalo de nuevo.
- Las tres curvas entrenan bien. Tu profundidad es demasiado superficial. Súbela a 24 capas.
- La uniforme no hace NaN, sólo se estanca. Podría ser que la ReLU está saturando (todo cero) — el gradiente es cero en todas partes, sin NaN, pero sin aprendizaje. Anótalo en el README; es un modo de fallo distinto a la explosión pero con la misma causa subyacente.
Pista de último recurso¶
Si llevas 90 minutos y la inicialización uniforme aún entrena: imprime np.var(model.layers[0].weight.data) tras la inicialización. Debería ser 1/12 ≈ 0.083. Si por accidente extrajiste uniforme [-0.05, 0.05], la varianza es ≈ 0.0008 — básicamente tipo Xavier. Revisa los límites de tu inicialización.
Cuándo consultar solutions/¶
Tras commitear los cinco archivos. Solución: solutions/01-init-ablation-ref.md (fase abierta).
Siguiente lab: lab/02-norm-ablation.md.