PASO 7 / 10

Residual Connections + LayerNorm

Las dos piezas "humildes" que hacen posible apilar muchas capas. Sin ellas, los Transformers profundos no funcionarían — los gradientes desaparecerían y las señales se distorsionarían entre capas.

🎯 De un vistazo

Este paso introduce dos operaciones (Residual y LayerNorm) que se aplican alrededor de cada sub-bloque del Transformer. Si solo leés esta sección, ya entendiste el 80%:

PROPÓSITO

¿Para qué sirve este paso?

Hacer posible apilar muchas capas. Son dos "pegamentos":

Residual = sumar el input original al output del sub-bloque.
LayerNorm = normalizar el vector a media 0 y desviación estándar 1.

APORTE

¿Qué le da al modelo?

Residual aporta un "canal libre" por donde la información original y los gradientes fluyen sin distorsionarse a través de las capas.

LayerNorm aporta una escala estable y predecible: no importa qué pasó antes, cada vector sale "calibrado".

NECESIDAD

¿Por qué es indispensable?

Sin estas dos piezas, apilar 96 capas sería imposible:

Sin residual → la info original se pierde y los gradientes se desvanecen (no se puede entrenar profundo).
Sin LayerNorm → los valores explotan o se desvanecen entre capas.

La fórmula completa de un bloque Transformer:
x' = LayerNorm( x + Attention(x) )      ← residual + norm alrededor de atención
x'' = LayerNorm( x' + FFN(x') )         ← residual + norm alrededor de FFN
Eso es todo el bloque Transformer. Atención y FFN ya los entendés; Residual y LayerNorm los explicamos ahora.

↓ A continuación, el detalle de cada pieza con ejemplos y visualizaciones ↓

1. El problema: redes muy profundas son difíciles de entrenar

GPT-3 tiene 96 bloques apilados. Cada bloque transforma el vector que recibe. Sin las dos piezas de este paso, hay dos problemas serios que aparecen al apilar tantas capas:

Problema A: la información original se pierde. Si cada capa transforma completamente el vector, después de 96 capas no queda casi nada del input original. El modelo "olvida" lo que vino al principio.
Problema B: los valores explotan o se desvanecen. Cada operación puede multiplicar los valores. Después de muchas capas, los números pueden volverse astronómicos (overflow) o microscópicos (underflow). En ambos casos, el modelo no puede aprender.
Residual ataca el problema A (preservar info). LayerNorm ataca el problema B (controlar escala). Juntos hacen que apilar muchas capas sea posible.

2. Residual Connections (conexiones residuales)

¿Qué es exactamente?

Imaginá que tenés un sub-bloque (atención o FFN) que toma un vector x y produce un nuevo vector sublayer(x). Una conexión residual hace algo trivial:

output = sublayer(x) + x

Es decir: en lugar de quedarte con la salida del sub-bloque, le sumás el input original. Eso es todo. No hay matemática complicada.

Visualmente: un "atajo" alrededor del sub-bloque

x (input)
↓ (sigue por el camino normal)
Sub-bloque (atención o FFN)
↓ produce sublayer(x)
SUMA: sublayer(x) + x
↑ Una copia de x "saltó" por encima del sub-bloque y se sumó al output.
Esa flecha es la "conexión residual" o "skip connection".

¿Por qué funciona? Tres razones

1. Preserva la información original

Si sublayer(x) = 0 (sub-bloque no aporta nada), el output sigue siendo x. La información del input nunca se pierde, en el peor caso pasa intacta.

2. Cada capa aprende "refinamientos", no reemplazos

Pensalo así: si la salida es output = x + sublayer(x), entonces sublayer(x) aprende a producir la "diferencia" o "cambio" que se le aplica a x. La capa no tiene que reconstruir todo desde cero — solo tiene que aprender qué agregar.

Es mucho más fácil aprender "qué pequeña corrección hacer" que "cómo reconstruir todo el vector desde cero".

3. Los gradientes pueden viajar hacia atrás sin obstáculos

Durante el entrenamiento, los "gradientes" (las señales que dicen cómo ajustar los pesos) tienen que viajar desde la salida hacia los pesos de cada capa. En redes muy profundas sin residual, los gradientes se debilitan al pasar por muchas capas y desaparecen (esto se llama "vanishing gradients").

Las conexiones residuales son como una autopista que permite a los gradientes saltearse capas y llegar limpios hasta atrás. Hace posible entrenar redes de 100+ capas.

Analogía: editar un documento

Sin residual: cada revisor reescribe el documento entero. Después de 96 revisores, no queda nada del original.

Con residual: cada revisor mira el documento original, decide qué cambios proponer, y los anota como "diferencias" sobre el documento (track changes). Después de 96 revisores, el documento original sigue siendo la base, refinado con muchas mejoras incrementales.

Ejemplo concreto

Imaginá que el input al sub-bloque es:
  x = [+0.50, +1.15, +0.78, +0.88]

Y el sub-bloque (digamos, atención) produce:
  sublayer(x) = [+0.30, -0.20, +0.15, +0.45]

Con conexión residual, el output es la SUMA:
  output = sublayer(x) + x
         = [+0.30+0.50, -0.20+1.15, +0.15+0.78, +0.45+0.88]
         = [+0.80, +0.95, +0.93, +1.33]

Notá que el output conserva mucho del "perfil" del input original (x),
solo modificado por la pequeña contribución del sub-bloque.

3. 📐 Repaso: media y desviación estándar

Antes de explicar LayerNorm necesitás dos conceptos básicos de estadística. Tranquilo, son simples.

Media (promedio)

La media es el promedio aritmético: sumás todos los números y dividís por la cantidad.

Ejemplo: vector = [2, 4, 6, 8]
  suma = 2 + 4 + 6 + 8 = 20
  cantidad = 4
  media = 20 / 4 = 5

Ejemplo 2: vector = [+0.80, +0.95, +0.93, +1.33]
  suma = 0.80 + 0.95 + 0.93 + 1.33 = 4.01
  media = 4.01 / 4 = 1.0025

Desviación estándar (std)

La desviación estándar mide qué tan dispersos están los valores alrededor de la media. Si todos están cerca de la media → std bajo. Si están muy dispersos → std alto.

Receta para calcularla:

  1. Calculá la media.
  2. Para cada valor, calculá (valor − media)² (la diferencia al cuadrado).
  3. Calculá el promedio de esas diferencias al cuadrado (esto se llama "varianza").
  4. Tomá la raíz cuadrada de la varianza. Eso es la desviación estándar.
Ejemplo: vector = [+0.80, +0.95, +0.93, +1.33]
  media = 1.0025

  Diferencias al cuadrado:
    (0.80 - 1.0025)² = (-0.2025)² = 0.0410
    (0.95 - 1.0025)² = (-0.0525)² = 0.0028
    (0.93 - 1.0025)² = (-0.0725)² = 0.0053
    (1.33 - 1.0025)² = (+0.3275)² = 0.1073

  Varianza = (0.0410 + 0.0028 + 0.0053 + 0.1073) / 4 = 0.0391

  Desviación estándar = √0.0391 = 0.198

🎮 Calculadora interactiva

Ingresá 4 números y mirá cómo cambian la media y la desviación estándar:

Para entender LayerNorm solo necesitás esto: la media te dice "alrededor de qué valor están concentrados los números", y la desviación estándar te dice "cuánto se desvían de ese valor". Vamos a usar las dos para "normalizar" un vector.

4. Layer Normalization (normalización por capa)

¿Qué problema resuelve?

Después de pasar por muchas operaciones (atención, FFN, suma residual, otra capa, otra...), los valores de los vectores pueden quedar en escalas muy distintas. Algunos vectores pueden tener valores enormes (ej. todos entre +50 y +100), otros casi todos chiquititos (entre −0.001 y +0.001). Esto hace muy difícil entrenar el modelo.

LayerNorm fuerza que cada vector tenga media 0 y desviación estándar 1. Así, no importa qué pasó antes — la salida siempre tiene una escala predecible y manejable.

La fórmula paso a paso

LayerNorm(x) = γ ⊙ (x − μ) / σ + β

📖 Diccionario

  • μ (mu) = la media de los valores de x (calculada como vimos arriba).
  • σ (sigma) = la desviación estándar de x.
  • γ (gamma) y β (beta) = vectores aprendibles (uno por dimensión). El modelo los entrena.
  • = multiplicación elemento por elemento.

La operación en 3 fases

Fase 1: restar la media → centrar en cero

A cada elemento del vector le restamos la media. El nuevo vector tiene media 0.

x = [0.80, 0.95, 0.93, 1.33]
media μ = 1.0025

x - μ = [0.80-1.0025, 0.95-1.0025, 0.93-1.0025, 1.33-1.0025]
      = [-0.2025, -0.0525, -0.0725, +0.3275]

Verificación: la media de estos nuevos valores es ≈ 0 ✓

Fase 2: dividir por la desviación estándar → escalar a std 1

Dividimos cada elemento por la desviación estándar. El nuevo vector tiene std 1.

std σ = 0.198

(x - μ) / σ = [-0.2025/0.198, -0.0525/0.198, -0.0725/0.198, +0.3275/0.198]
            = [-1.023, -0.265, -0.366, +1.654]

Verificación: la media sigue siendo 0, y la desviación estándar ahora es 1 ✓

Fase 3: aplicar γ y β → permitir que el modelo "des-normalice" si conviene

Si el modelo decide que NO quiere media 0 y std 1 para cierta dimensión, los parámetros γ y β le permiten escalar y desplazar el resultado:

γ = [1.2, 0.8, 1.0, 1.1]   (vector aprendido)
β = [0.1, 0.0, -0.2, 0.3]  (vector aprendido)

resultado = γ ⊙ (x normalizado) + β

         = [1.2*(-1.023)+0.1, 0.8*(-0.265)+0.0, 1.0*(-0.366)+(-0.2), 1.1*(+1.654)+0.3]
         = [-1.128, -0.212, -0.566, +2.119]

γ escala cada dimensión (multiplica). β la desplaza (suma). Si γ = 1 y β = 0, el resultado es exactamente el normalizado. Pero al ser aprendidos, el modelo puede ajustarlos si conviene.

¿Por qué existen γ y β si "deshacen" la normalización?

Pregunta natural. La respuesta: queremos que el modelo tenga la opción de no normalizar si encuentra que cierta escala es útil. Sin γ y β, le estaríamos imponiendo media 0 / std 1 a todas las capas — y eso podría ser una restricción demasiado fuerte.

Con γ y β aprendibles: el modelo arranca normalizando (lo cual estabiliza el entrenamiento al principio), y después aprende si le conviene mantener esa normalización o ajustarla en cada dimensión.

🎮 Visualización: antes vs después de LayerNorm

Movés los sliders y mirás cómo se normaliza el vector en tiempo real:

5. El bloque Transformer completo

Ahora que entendés residual y LayerNorm, podés ver el bloque completo del Transformer. Cada bloque tiene dos sub-bloques (atención y FFN), y alrededor de cada uno hay residual + LayerNorm.

Input al bloque (3 vectores · dim 4)
↓ (también guardamos una copia para sumar después)
Multi-Head Attention
↓ producir sublayer1(x)
SUMA: sublayer1(x) + x_original
↓ vector con info preservada
LayerNorm (normalizar)
↓ (otra copia se guarda para sumar después)
Feed-Forward Network
↓ producir sublayer2(x')
SUMA: sublayer2(x') + x'
LayerNorm (normalizar)
Output del bloque (3 vectores · dim 4)
El patrón se repite 2 veces por bloque: "(sub-bloque + residual + norm)" alrededor de atención, después "(sub-bloque + residual + norm)" alrededor de FFN. Eso es UN bloque.

Este bloque entero se apila N veces en el modelo (12 veces en GPT-2 small, 96 veces en GPT-3). Sin residual y LayerNorm, apilar 96 bloques sería un infierno: gradientes que desaparecen, valores que explotan, entrenamiento que diverge. Residual + LayerNorm son las dos piezas que hacen viable el "deep" en deep learning.

Variante moderna: Pre-LN vs Post-LN

El paper original ("Attention is All You Need", 2017) usaba Post-LN: normalizar DESPUÉS de sumar el residual. Esa es la versión que mostré arriba.

Post-LN (original):
  x' = LayerNorm( x + sublayer(x) )

Pre-LN (moderno, usado en GPT-2, GPT-3, LLaMA, etc.):
  x' = x + sublayer( LayerNorm(x) )

La diferencia: en Pre-LN, primero normalizamos, después aplicamos el sub-bloque, y la suma residual usa el x sin normalizar. Empíricamente, Pre-LN es más fácil de entrenar para modelos muy profundos (resulta menos sensible a hiperparámetros). Pero la idea conceptual es la misma.

🎮 Demo interactivo: el flujo completo

Click "Siguiente paso" para ver cómo se aplica residual + LayerNorm al vector de "perro" después de la atención.

0. Input + salida de atención
1. Residual (suma)
2. Calcular media y std
3. Normalizar
4. Aplicar γ y β
Listo para comenzar
Apretá "Siguiente paso" para arrancar.

✅ Resumen: el bloque Transformer está completo

Con los pasos 4 a 7 ya tenés todas las piezas de UN bloque del Transformer:

  1. Paso 4-5: Multi-Head Attention (mezcla info entre tokens).
  2. Paso 6: Feed-Forward Network (procesa cada token internamente, no-linealidad).
  3. Paso 7: Residual + LayerNorm (preserva información + estabiliza escalas).

En el Paso 8: Stacking de bloques vamos a ver cómo se apilan muchos de estos bloques (12, 24, 96...) para formar el Transformer completo. Vas a entender por qué más capas = más capacidad de razonamiento abstracto, y cómo emergen patrones jerárquicos a medida que subís de capa.