Skip to content

English · Español

Lab 00 — Paseo de la varianza: ver activaciones explotar/colapsar

Objetivo: observar empíricamente lo que predice la teoría 01 — la varianza del paso hacia adelante evoluciona capa a capa en función de σ_W².

Tiempo estimado: 45–60 minutos.

Prerrequisito: theory/00-motivation.md y theory/01-initialization.md leídos.


Qué produces

Un directorio experiments/10-variance-walk/ que contiene:

  • walk.py — tu script de medición.
  • results.json — varianza de activación por inicialización (init) y por capa.
  • variance.png — gráfico semilog-y de varianza de activación vs índice de capa, tres curvas (uniforme, Xavier, Kaiming).
  • manifest.json{seed, versions, config, hardware} según LYNX_CORTEX.md §5.
  • README.md (2–3 párrafos) explicando lo observado y cómo encaja (o no) con la fórmula Var(y) = n_in · σ_W² · Var(x).

El montaje

Un MLP de 20 capas, dimensión oculta 256, sin activación (sólo lineal). Estás aislando el comportamiento de varianza de la capa lineal de cualquier efecto de activación.

Toma un vector (o batch) de entrada fijo con varianza unidad. Propaga hacia adelante por 20 capas lineales. En cada capa, registra la varianza empírica de las activaciones.

Tres ejecuciones, idénticas salvo por el esquema de inicialización:

  1. Uniforme [-0.5, 0.5] (mala — varianza 1/12 ≈ 0.083, no escala con n_in).
  2. Xavier N(0, 1/n_in).
  3. Kaiming N(0, 2/n_in).

El paseo de varianza de la Fase 10 es sólo lineal — sin activación. Esto aísla el efecto de la inicialización del efecto de la activación (añadiremos la activación en el lab 01).

TODOs

Bloque A — escribe el caminante de varianza

  • MLP de 20 capas, oculta 256. Usa np.empty + np.dot directamente, o constrúyelo sobre módulos Linear de minitorch. Ambas opciones valen; la segunda ejercita el stack de la Fase 9.
  • Inicializa según los tres esquemas. Siembra cada inicialización por separado para que las tres ejecuciones sean reproducibles.
  • Propaga un batch de 64 muestras, cada una un gaussiano de 256 dimensiones con varianza 1.
  • En la salida de cada capa, registra: layer_idx, var_empirical, var_theoretical_prediction. var_theoretical = varianza de la capa anterior × n_in × σ_W².
  • Guarda como results.json.

Bloque B — gráfico

  • matplotlib. eje x: índice de capa (0 a 20). eje y: varianza, escala logarítmica.
  • Tres curvas: uniforme, Xavier, Kaiming.
  • En los mismos ejes: las curvas teóricas como líneas discontinuas. La empírica debería seguir a la teórica dentro de ~10%.
  • Guarda variance.png.

Bloque C — interpreta

En README.md, responde:

  1. ¿Qué hace la curva de inicialización uniforme? ¿Decae o explota? ¿Por qué factor por capa? Encaja con la fórmula.
  2. ¿Qué hace la curva de Xavier? Debería rondar 1.0 a lo largo de las capas. La tuya también (dentro del ruido de la varianza del batch).
  3. ¿Por qué la curva de Xavier no es exactamente 1.0? Cae/desvía un poco. ¿Por qué? (Pista: la fórmula asume el límite de batch infinito; tú usas 64 muestras.)
  4. ¿Qué cambiaría si usaras activación ReLU entre capas? Predice las curvas de Xavier y Kaiming con ReLU. Bonus: re-ejecuta con ReLU como experimento secundario y confirma.

Bloque D — manifest

{
  "experiment": "10-variance-walk",
  "date": "YYYY-MM-DD",
  "seed": 42,
  "versions": { "python": "3.11.x", "numpy": "...", "minigrad": "..." },
  "hardware": { ... },
  "config": {
    "depth": 20,
    "hidden_dim": 256,
    "batch_size": 64,
    "input_variance": 1.0,
    "inits": ["uniform[-0.5, 0.5]", "xavier N(0, 1/n)", "kaiming N(0, 2/n)"]
  },
  "results_summary": {
    "uniform_final_layer_variance": null,
    "xavier_final_layer_variance": null,
    "kaiming_final_layer_variance": null
  }
}

Restricciones

  • Sin activación entre capas lineales. Esto aísla la inicialización de la activación. El lab 01 añadirá la activación.
  • Sin norm. Misma razón.
  • Sin paso hacia atrás. Sólo hacia adelante. La varianza del paso hacia atrás es la otra mitad de la teoría 01 — lo cubriremos numéricamente en un lab futuro si hace falta.
  • Un único hilo. No hace falta paralelismo aquí; el cómputo es barato.

Condiciones de parada

Has terminado cuando:

  1. El directorio tiene los cinco archivos.
  2. variance.png muestra: uniforme explotando un orden de magnitud por capa, Xavier manteniéndose cerca de 1.0, Kaiming manteniéndose cerca de 2.0 (porque está sintonizado para ReLU, no para lineal).
  3. README responde las cuatro preguntas del Bloque C.
  4. Puedes re-derivar la fórmula de varianza en papel sin mirar la teoría 01.

Trampas (lee antes de depurar)

  • Varianza calculada mal. np.var(activations) calcula la varianza escalar sobre todos los elementos; tú quieres semántica por batch por feature. Comprueba el eje. La varianza de eje por defecto sobre (B, d) = (64, 256) vale para nuestro propósito, ya que las features son i.i.d. por inicialización.
  • La curva uniforme queda plana en vez de explotar. Comprueba los límites. uniform[-0.5, 0.5] tiene varianza 1/12 ≈ 0.083. Multiplicado por n_in = 256 → ratio por capa ≈ 21×. En la capa 20 → 21^20 ≈ 10^26. Si tu curva es plana, probablemente estés normalizando en algún sitio.
  • La curva de Xavier se desvía hacia arriba. Puede ser un off-by-one en el fan-in (usando n_out en lugar de n_in). Revisa.
  • Desbordamiento de coma flotante en la capa ~7 en la ejecución uniforme. Esperado. Tu script debe capturar el inf/nan y no caerse. Registra un marcador "saturated" y sigue.

Pista de último recurso

Si llevas 60 minutos y no consigues estabilizar Xavier: comprueba np.random.seed(seed); W = np.random.randn(n_out, n_in) * np.sqrt(1 / n_in). Eso es Xavier. Si (n_out, n_in) está invertido, la varianza sigue funcionando hacia adelante por accidente, pero la forma del matmul no.

Cuándo consultar solutions/

Tras commitear los cinco archivos. Solución: solutions/00-variance-walk-ref.md (fase abierta).


Siguiente lab: lab/01-init-ablation.md.