Transformers — Módulo 4: la arquitectura completa — el bloque Transformer
Cuarto módulo del Curso de Transformers y cierre del bloque básico: cómo se ensambla el bloque Transformer completo. Multi-head attention, conexiones residuales, layer normalization y la red feed-forward; el positional encoding que devuelve el orden que a la atención le falta; por qué residuales y norm estabilizan el entrenamiento, y cómo se apilan N bloques.
☰ Índice del contenido
En el Módulo 3 terminamos la pieza estrella: multi-head attention, con la misma forma de entrada y salida —lista para apilarse—. Pero una atención suelta no es un Transformer. Faltan tres cosas: darle estabilidad para que se pueda entrenar en profundidad, darle capacidad de cómputo más allá de mezclar vectores, y —el pendiente que arrastramos desde el Módulo 1— devolverle la noción de orden. Hoy ensamblamos todo eso en el bloque Transformer completo y lo apilamos. Con esto cerramos el bloque básico: entenderás de punta a punta la arquitectura de “Attention is All You Need”.
La tesis del módulo
El bloque Transformer es una receta de cuatro ingredientes que se repite N veces. Atención para mezclar contexto, feed-forward para procesar cada token, y —envolviendo a ambos— conexiones residuales y layer norm que hacen posible apilar decenas de capas sin que el entrenamiento colapse. Apila el bloque, súmale la posición, y tienes un Transformer.
Primero, el pendiente: positional encoding
La atención, por sí sola, es ciega al orden (lo vimos en el Módulo 1). “el perro mordió al hombre” y “el hombre mordió al perro” le llegan como el mismo conjunto de vectores. Hay que inyectarle la posición.
El positional encoding (codificación posicional) es una señal que se suma a cada embedding e indica en qué posición va el token. Hay dos familias:
- Sinusoidal (la original del paper): la posición se codifica con senos y cosenos de distintas frecuencias. No tiene parámetros, y tiene una gracia: permite al modelo generalizar a posiciones que no vio en entrenamiento.
- Aprendido (learned): una tabla de vectores de posición que se ajusta como cualquier otro parámetro, igual que la matriz de embeddings. Simple y efectivo; lo usan muchos modelos.
import numpy as np
def positional_encoding(n_pos, d_model):
# Codificación sinusoidal del paper original.
pos = np.arange(n_pos)[:, None] # (n_pos, 1)
i = np.arange(d_model)[None, :] # (1, d_model)
ang = pos / np.power(10000, (2 * (i // 2)) / d_model)
pe = np.zeros((n_pos, d_model))
pe[:, 0::2] = np.sin(ang[:, 0::2]) # dims pares -> seno
pe[:, 1::2] = np.cos(ang[:, 1::2]) # dims impares -> coseno
return pe
# Se SUMA a los embeddings antes del primer bloque.
# embeddings: (n_tokens, d_model)
# entrada = embeddings + positional_encoding(n_tokens, d_model)
Ojo: el positional encoding se suma, no se concatena. Cada embedding ya viene con su posición mezclada dentro del mismo vector. La atención sigue sin “saber” de orden; simplemente ahora los vectores que compara ya traen la posición horneada.
Los cuatro ingredientes del bloque
Con la posición ya sumada, entramos al bloque. Tiene dos sub-capas, cada una envuelta en el mismo patrón.
1. Multi-head attention (Módulo 3): mezcla el contexto entre tokens.
2. Feed-forward network (FFN): una pequeña red de dos capas que se aplica a cada token por separado (por eso se llama “position-wise”, por posición). Mientras la atención mezcla tokens entre sí, la FFN procesa cada token hacia adentro, dándole al modelo capacidad de cómputo no lineal. Típicamente expande a 4× d_model y vuelve a comprimir:
import torch.nn as nn
class FeedForward(nn.Module):
def __init__(self, d_model, d_ff=None):
super().__init__()
d_ff = d_ff or 4 * d_model # expansión típica: 4x
self.net = nn.Sequential(
nn.Linear(d_model, d_ff), # expande
nn.GELU(), # no linealidad
nn.Linear(d_ff, d_model), # comprime de vuelta
)
def forward(self, x):
return self.net(x) # se aplica igual a cada token
Envolviendo a esas dos sub-capas, el patrón que las hace entrenables:
3. Conexión residual (residual connection): en vez de reemplazar la entrada por la salida de la sub-capa, se suma la entrada a la salida: x + Sub(x). Así el gradiente tiene siempre una “autopista” directa hacia atrás, y apilar decenas de capas no lo apaga. Es la misma idea que ResNet revolucionó en visión por computador: sin residuales, las redes muy profundas simplemente no entrenaban.
4. Layer normalization (normalización por capa): re-escala el vector de cada token para que sus valores tengan media 0 y varianza controlada. Mantiene los números en un rango sano capa tras capa, evitando que exploten o se desvanezcan. Estabiliza y acelera el entrenamiento.
El bloque completo, ensamblado
Juntando los cuatro ingredientes, un bloque Transformer se ve así (versión “post-norm” del paper original; muchos modelos modernos usan “pre-norm”, con la norm antes de cada sub-capa):
entrada (embeddings + posición)
│
┼───────────────┐ (guarda la entrada)
▼ │
┌─────────────────┐ │
│ multi-head attn │ │
└────────┬────────┘ │
▼ │
suma ◄────────┘ residual: x + attn(x)
│
▼
┌─────────────────┐
│ layer norm │
└────────┬────────┘
│
┼───────────┐ (guarda otra vez)
▼ │
┌─────────────────┐ │
│ feed-forward │ │
└────────┬────────┘ │
▼ │
suma ◄────────┘ residual: x + ffn(x)
│
▼
┌─────────────────┐
│ layer norm │
└────────┬────────┘
▼
salida (misma forma que la entrada)
Y como la salida tiene la misma forma que la entrada, se apilan N bloques idénticos uno sobre otro:
embeddings + positional encoding
│
▼
┌─────────────────┐
│ bloque 1 │
└────────┬────────┘
▼
┌─────────────────┐
│ bloque 2 │
└────────┬────────┘
▼
... (N bloques: 12, 24, 96...)
│
▼
┌─────────────────┐
│ bloque N │
└────────┬────────┘
▼
representación final por token
Cada bloque refina un poco más la representación: los primeros captan patrones locales y de superficie; los últimos, relaciones abstractas y de largo alcance. La “profundidad” (N) es una de las palancas que definen el tamaño del modelo, junto con d_model y el número de cabezas (más sobre esto en Parámetros de los modelos).
Quién hace qué, de un vistazo
| Componente | Qué hace | Analogía |
|---|---|---|
| Positional encoding | Inyecta el orden de los tokens | Numerar las páginas de un libro |
| Multi-head attention | Mezcla contexto entre tokens | Cada palabra consulta a las demás |
| Feed-forward (FFN) | Procesa cada token por separado | Pensar sobre lo que acabo de escuchar |
| Conexión residual | Autopista para el gradiente | Un atajo que nunca se corta |
| Layer norm | Mantiene los números a raya | Recalibrar el instrumento cada paso |
Cuidado: el orden exacto (post-norm vs pre-norm) parece un detalle menor, pero importa para entrenar modelos profundos. El paper original usó post-norm; casi todos los LLM modernos usan pre-norm (layer norm antes de cada sub-capa) porque estabiliza mejor con muchas capas. La idea de fondo es la misma.
”Attention is All You Need” y lo que viene
Todo esto salió del paper de 2017 “Attention is All You Need”, que propuso la arquitectura original encoder-decoder: un encoder que lee toda la entrada (para tareas como traducción) y un decoder que genera la salida token a token. Nosotros armamos el bloque genérico que ambos comparten.
Aquí viene el giro del curso: los LLM que usas a diario (la familia GPT) tiran a la basura el encoder y se quedan solo con el decoder —son decoder-only—. En el próximo módulo veremos exactamente qué cambia: la atención causal (cada token solo mira hacia atrás, nunca al futuro) y cómo eso convierte al Transformer en una máquina de predecir la siguiente palabra.
Errores comunes
- Creer que el positional encoding se concatena. Se suma al embedding. El vector no crece; la posición queda mezclada dentro.
- Pensar que la FFN mezcla tokens. No: la atención mezcla tokens entre sí; la FFN procesa cada token por separado. Son roles complementarios.
- Subestimar las conexiones residuales. No son un adorno: sin ellas, un Transformer profundo no entrena. Son la razón de que se puedan apilar 96 capas.
- Confundir layer norm con batch norm. Layer norm normaliza dentro de cada token, independiente del resto del lote; es la que funciona bien en secuencias de largo variable.
- Creer que todos los bloques hacen lo mismo. Comparten la estructura, pero cada uno tiene sus propios pesos y aprende a refinar en un nivel de abstracción distinto.
Cierre del bloque básico
Ya tienes el Transformer completo por dentro: del texto a los vectores (M1), la atención que da contexto (M2), las múltiples cabezas que ven distintas relaciones (M3) y el bloque ensamblado y apilado que hoy cerramos (M4). Todo lo que viene —GPT, pretraining, fine-tuning, RLHF— se apoya en esta arquitectura.
La frase para llevarse
“Un Transformer es un solo bloque —atención, feed-forward, residual, norm— repetido con disciplina decenas de veces. La inteligencia no está en la complejidad de la pieza, sino en la profundidad con que se apila.”
Qué viene
Arranca el bloque intermedio (Módulo 5): del Transformer al GPT. Dejamos la arquitectura genérica y nos metemos en la variante decoder-only: atención causal, predicción del siguiente token y cómo un Transformer se convierte en el motor generativo detrás de ChatGPT y Claude.
Material relacionado
Preguntas sobre este curso
Regístrate gratis para hacer preguntas y guardar tu progreso.
✉ Entérate de lo nuevo
Recibe un aviso cuando publique nuevos cursos, workshops o investigaciones. Sin spam.