10 · Inicialización de pesos: Xavier y He
Cómo inicializas los pesos determina si los gradientes se desvanecen, explotan o entrenan de forma limpia — Xavier para sigmoid/tanh, He para ReLU.
Cómo inicializas los pesos determina si los gradientes se desvanecen, explotan o entrenan de forma limpia — Xavier para sigmoid/tanh, He para ReLU.
Sin esto:
La inicialización aleatoria desde N(0, 1) hace explotar una red de 10 capas en un solo batch.
La inicialización de pesos es uno de esos temas que parece una nota al pie hasta que ves tu red de 10 capas producir NaN en el primer forward pass. El problema es engañosamente simple: si los pesos iniciales son demasiado grandes, las activaciones crecen de forma exponencial capa por capa. Si son demasiado pequeños, las señales se reducen a cero y los gradientes desaparecen antes de llegar a las capas tempranas.
La idea clave es la preservación de varianza: queremos que la varianza de la señal de activación permanezca aproximadamente constante al fluir por cada capa. Si la capa l tiene n_in conexiones entrantes y tomamos pesos de una distribución con desviación estándar σ, la varianza de salida escala como n_in × σ². Para mantener varianza de salida ≈ varianza de entrada, necesitamos σ = sqrt(1/n_in).
Ese razonamiento lleva directamente a los dos esquemas que todo profesional usa:
- Xavier / Glorot (2010) — diseñado para sigmoid y tanh:
W ~ N(0, sqrt(1/n_in)) - He / Kaiming (2015) — diseñado para ReLU:
W ~ N(0, sqrt(2/n_in))
El factor 2 en He init existe porque ReLU pone a cero aproximadamente la mitad de todas las activaciones (la mitad negativa), lo que reduce a la mitad la varianza efectiva. Duplicar la varianza de inicialización compensa exactamente esto.
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Derivando Xavier vs He: ¿por qué el factor 2?
Read-along de PyTorch: kaiming_normal_ (He) y xavier_uniform_ (Xavier)
¿Por qué usar He init para capas ReLU en lugar de Xavier?
- Una mala inicialización (N(0,1)) hace explotar las activaciones en pocas capas; la solución es escalar los pesos por sqrt(1/n_in) o sqrt(2/n_in).
- Xavier (Glorot): sigma = sqrt(1/n_in) — diseñado para sigmoid y tanh, preserva la varianza a través de activaciones simétricas.
- He (Kaiming): sigma = sqrt(2/n_in) — diseñado para ReLU; el factor 2 compensa que ReLU pone a cero ~50% de las activaciones.
- Nunca inicialices todos los pesos a cero — la simetría nunca se rompe, todas las neuronas en una capa aprenden de manera idéntica.
Toda red profunda que entrenes usa Kaiming/He init para capas ocultas y Xavier para capas de salida — `nn.Linear` y `nn.Conv2d` usan estas por defecto en PyTorch.
Si lo quitas: Usa inicialización aleatoria N(0,1) y tu red de 10 capas o explota a NaN en el paso 1 (pesos grandes) o se paraliza con gradiente cero (pesos pequeños) — ambas son no entrenables.