Lección 10

Atención de una cabeza

La atención es el mecanismo que le permite a un token "mirar" a los tokens anteriores y decidir cuáles son relevantes. Aquí lo hacemos con números reales, paso a paso.

1. El detective y sus pistas

Un detective examina una escena del crimen. No lee todo el expediente de principio a fin — tiene una pregunta específica: "¿quién estaba aquí a las 9pm?". Compara esa pregunta con cada pista disponible: el testimonio de un vecino, las huellas en el suelo, el registro de la cámara. Algunos se ajustan bien a su pregunta, otros no. Las pistas más relevantes tienen más peso en su conclusión.

🔍 La atención funciona exactamente así:
Query (Q): la pregunta del token actual — "¿qué contexto necesito para predecir el siguiente carácter?"
Key (K): lo que cada token anterior "ofrece" — su etiqueta de identidad
Value (V): el contenido real de cada token anterior — la información que aporta
Score: qué tan bien coincide la pregunta (Q) con cada oferta (K) — producto punto escalado

2. Los cuatro pasos de la atención

Pipeline · Atención de una cabeza
Los cuatro pasos de la atención: Q K V, scores, softmax, suma ponderada Tokens k a r predict →? Proyección Q,K,V Q 1.0 0.4 0.9 K 0.9 0.3 0.8 V 0.5 1.1 0.7 Scores Q·Kᵀ / √d 0.90 -∞ -∞ 0.61 0.12 -∞ 0.92 0.84 0.71 -∞ = máscara causal Softmax → pesos 1.00 0.62 0.38 0.38 0.34 0.28 output Σ pesos × V 16 nums

Cada token de salida es una mezcla ponderada de los Values anteriores. Los pesos de la mezcla vienen de qué tan bien coincide la Query del token actual con las Keys de los tokens anteriores.

3. Cálculo completo con números reales

✍️ Atención para el token 'r' en "kar" — dimensión 4 para simplificar
Tenemos 3 tokens: k(pos 0), a(pos 1), r(pos 2)
Embeddings de entrada (simplificados a 4 dimensiones):
  x_k = [1.2,  0.3, -0.5,  0.8]
  x_a = [0.4,  1.1,  0.7, -0.2]
  x_r = [0.9, -0.4,  1.3,  0.6]  ← el token activo

Paso 1: Proyectamos en Q, K, V con matrices entrenadas
  (simplificamos: cada proyección es una combinación lineal)
  Q_r = [1.0,  0.5, 0.2, 0.8]   ← "la pregunta de r"
  K_k = [0.9,  0.4, 0.1, 0.7]   ← "lo que ofrece k"
  K_a = [0.3,  1.2, 0.6, 0.2]   ← "lo que ofrece a"
  K_r = [0.8,  0.3, 0.9, 0.5]   ← "lo que ofrece r"
  V_k = [0.5, -0.3, 0.8,  0.1]
  V_a = [1.1,  0.2, 0.4, -0.5]
  V_r = [0.7,  0.9, 0.3,  0.6]

Paso 2: Scores = Q_r · K / √d  (dividimos por √4 = 2)
  score(r,k) = (1.0×0.9 + 0.5×0.4 + 0.2×0.1 + 0.8×0.7) / 2
             = (0.9 + 0.2 + 0.02 + 0.56) / 2 = 1.68 / 2 = 0.84
  score(r,a) = (1.0×0.3 + 0.5×1.2 + 0.2×0.6 + 0.8×0.2) / 2
             = (0.3 + 0.6 + 0.12 + 0.16) / 2 = 1.18 / 2 = 0.59
  score(r,r) = (1.0×0.8 + 0.5×0.3 + 0.2×0.9 + 0.8×0.5) / 2
             = (0.8 + 0.15 + 0.18 + 0.4) / 2 = 1.53 / 2 = 0.77

Paso 3: Softmax de los scores
  exp(0.84) = 2.316,  exp(0.59) = 1.804,  exp(0.77) = 2.160
  suma = 6.280
  pesos = [2.316/6.280, 1.804/6.280, 2.160/6.280]
        = [0.369, 0.287, 0.344]    ← suman 1.000 ✅

Paso 4: Suma ponderada de los Values
  output_r = 0.369 × V_k + 0.287 × V_a + 0.344 × V_r
  dimensión 0: 0.369×0.5 + 0.287×1.1 + 0.344×0.7 = 0.185+0.316+0.241 = 0.742
  dimensión 1: 0.369×(-0.3) + 0.287×0.2 + 0.344×0.9 = -0.111+0.057+0.310 = 0.256
  ... (y así para las 4 dimensiones)

output_r = [0.742, 0.256, ...]  ← vector de 4 dims con contexto mezclado
      
🔑 Por qué dividir por √d: si los vectores Q y K tienen dimensión 4, los productos punto tienden a ser grandes en valor absoluto. Al dividir por √4 = 2, los scores quedan en un rango más manejable antes del softmax. Sin esto, el softmax se vuelve muy "puntiagudo" y el aprendizaje se dificulta.

4. La máscara causal

Un detalle importante: durante el entrenamiento, el modelo procesa toda la secuencia a la vez. Pero cada token solo puede mirar hacia atrás, no hacia adelante. Si estamos prediciendo el carácter en posición 3, no podemos usar la información de la posición 4 — eso sería "hacer trampa".

La máscara causal pone -∞ en los scores de posiciones futuras. Después del softmax, exp(-∞) = 0, así que esas posiciones tienen peso 0 en la suma ponderada.

Máscara causal · matriz de atención para "kar" (3 tokens)
Matriz de atención causal 3x3 para los tokens k, a, r Triángulo inferior lleno con valores de atención. Triángulo superior con -infinito que representa la máscara causal. k a r k a r 1.00 -∞ -∞ 0.62 0.38 -∞ 0.37 0.29 0.34 → atiende a (columna)

Cada fila representa un token. Los -∞ (triángulo superior) bloquean la atención hacia el futuro. El token 'k' solo se ve a sí mismo; 'a' ve a 'k' y a sí misma; 'r' ve a los tres.

🎮 Pruébalo: pesos de atención

Selecciona qué token es el "activo" y ve sus pesos de atención sobre los anteriores:

5. Lo que aprendiste

En esta lección:
  • La atención tiene 4 pasos: proyectar en Q/K/V → calcular scores (Q·Kᵀ/√d) → softmax → suma ponderada de V.
  • La máscara causal asegura que cada token solo mira hacia atrás (posiciones anteriores).
  • Los pesos de atención salen del softmax y siempre suman 1 para cada token.
  • El output es una mezcla de los Values anteriores, ponderada por la relevancia de sus Keys para la Query actual.