English · Español
05 — Cálculo completo de attention: secuencia de longitud 4 con valores numéricos¶
Hacemos toda la atención de cabeza única para una secuencia de longitud 4 con números reales.
Q,K,Vsalen de un embedding §A13. Cada paso —QK^T, escalado, máscara, softmax, multiplicación porV— lo escribimos con valores concretos. Después calculamos∂L/∂Qpor la regla de la cadena. Esto convierte la sección §02 (derivación general) en algo numérico que cabe en una hoja.Anclas:
LYNX_CORTEX.md§4 / PHASE 15; theory §02 scaled dot-product; lab §00 attention by hand; Fase 27 (Flash attention reutilizará esta misma aritmética).
Planteamiento — tensores concretos¶
Secuencia: ["I", "will", "work", "."]. Embebida a d_model = 4. Usaremos attention single-head, single-layer con d_k = d_v = 4.
import numpy as np
np.set_printoptions(precision=3, suppress=True)
X = np.array([
[ 0.50, 0.30, -0.20, 0.10], # "I"
[-0.10, 0.40, 0.20, -0.30], # "will"
[ 0.20, -0.10, 0.50, 0.10], # "work"
[ 0.00, 0.00, 0.00, 0.20], # "."
])
# Tiny W_Q, W_K, W_V (identity-ish for clarity)
W_Q = np.eye(4) * 0.5
W_K = np.eye(4) * 0.5
W_V = np.eye(4) * 1.0
Calcula Q, K, V:
Así que Q = K = 0.5 · X, V = X. (Elegir pesos identidad hace la aritmética legible.)
Paso 1 — Q K^T¶
Calcula X X.T (una matriz 4×4 de productos escalares):
I will work .
I | 0.39 -0.04 -0.01 0.02 |
will| -0.04 0.30 0.04 -0.06 |
work| -0.01 0.04 0.31 0.02 |
. | 0.02 -0.06 0.02 0.04 |
(Comprobación de sanidad: X[0] · X[0] = 0.25 + 0.09 + 0.04 + 0.01 = 0.39 ✓.)
Q K^T = 0.25 · X X.T:
I will work .
I | 0.098 -0.010 -0.003 0.005 |
will| -0.010 0.075 0.010 -0.015 |
work| -0.003 0.010 0.078 0.005 |
. | 0.005 -0.015 0.005 0.010 |
Paso 2 — Escalar por sqrt(d_k) = 2¶
I will work .
I | 0.049 -0.005 -0.002 0.003 |
will| -0.005 0.038 0.005 -0.008 |
work| -0.002 0.005 0.039 0.003 |
. | 0.003 -0.008 0.003 0.005 |
Estos son los logits pre-softmax. Como usamos pesos identidad y embeddings pequeños, están todos cerca de 0. (El modelo real de la Fase 17 tendrá una dispersión mayor.)
Paso 3 — Máscara causal¶
Pon el triángulo superior a -∞:
I will work .
I | 0.049 -inf -inf -inf |
will| -0.005 0.038 -inf -inf |
work| -0.002 0.005 0.039 -inf |
. | 0.003 -0.008 0.003 0.005 |
Esto hace que el softmax en el paso 4 dé 0 para las posiciones enmascaradas.
Paso 4 — Softmax por filas¶
Para cada fila, resta el máximo de la fila (por estabilidad), exponencia, normaliza.
Fila 0 ("I"): Solo una entrada sin enmascarar, 0.049. Softmax = [1, 0, 0, 0].
Fila 1 ("will"):
logits = [-0.005, 0.038, -inf, -inf]
shifted = logits - 0.038 = [-0.043, 0, -inf, -inf]
exp = [exp(-0.043), 1, 0, 0] = [0.958, 1.0, 0, 0]
sum = 1.958
softmax = [0.489, 0.511, 0, 0]
Fila 2 ("work"):
logits = [-0.002, 0.005, 0.039, -inf]
shifted = logits - 0.039 = [-0.041, -0.034, 0, -inf]
exp = [0.960, 0.967, 1.0, 0]
sum = 2.927
softmax = [0.328, 0.330, 0.342, 0]
Fila 3 ("."):
logits = [0.003, -0.008, 0.003, 0.005]
shifted = logits - 0.005 = [-0.002, -0.013, -0.002, 0]
exp = [0.998, 0.987, 0.998, 1.0]
sum = 3.983
softmax = [0.250, 0.248, 0.250, 0.251]
(Aproximadamente uniforme — las diferencias en los logits pre-softmax son demasiado pequeñas para hacer la distribución afilada. El §02 de la Fase 15 deriva por qué: en init, attention es aproximadamente uniforme; el aprendizaje la afila.)
Matriz de atención A:
Paso 5 — A @ V¶
V = X. Calcula Y = A V:
Fila 0 ("I"): Y[0] = 1.0 · X[0] = X[0] = [0.50, 0.30, -0.20, 0.10]. Ella misma.
Fila 1 ("will"): suma ponderada de X[0] y X[1]:
Y[1] = 0.489·X[0] + 0.511·X[1]
= 0.489·[0.5, 0.3, -0.2, 0.1] + 0.511·[-0.1, 0.4, 0.2, -0.3]
= [0.2445 - 0.0511, 0.1467 + 0.2044, -0.0978 + 0.1022, 0.0489 - 0.1533]
≈ [0.194, 0.351, 0.004, -0.104]
Fila 2 ("work"):
Y[2] ≈ 0.328·X[0] + 0.330·X[1] + 0.342·X[2]
≈ [0.164, 0.099, -0.066, 0.033] + [-0.033, 0.132, 0.066, -0.099] + [0.068, -0.034, 0.171, 0.034]
≈ [0.199, 0.197, 0.171, -0.032]
Fila 3 ("."): promedio aproximado de las cuatro filas de X.
Paso 6 — Proyección de salida y pérdida¶
Supón que el objetivo es predecir el siguiente token (LM). La cabeza de LM da logits sobre el vocab; la pérdida es entropía cruzada. No la expandiremos aquí — la Fase 17 lo hace — pero asume ∂L/∂Y[3] = g_3 (el gradiente en la última posición).
Gradiente backward — a través del softmax¶
Queremos ∂L/∂Q. La cadena completa es:
Y = A V, así que∂L/∂A = (∂L/∂Y) V^Ty∂L/∂V = A^T (∂L/∂Y).A = softmax(S)(por filas). El jacobiano del softmax por filaiesdiag(A_i) - A_i A_i^T. Así que∂L/∂S = A ⊙ (∂L/∂A - (∂L/∂A · A^T) · ⊙_rows)— la fórmula estándar del backward del softmax.S = (Q K^T) / sqrt(d_k), así que∂L/∂Q = (∂L/∂S) K / sqrt(d_k).
La aritmética de formas para nuestro caso T = 4, d_k = 4:
∂L/∂Y : (4, 4) [from cross-entropy]
∂L/∂A : (4, 4) = (∂L/∂Y) V.T = (4,4) @ (4,4)
∂L/∂V : (4, 4) = A.T @ (∂L/∂Y) = (4,4) @ (4,4)
∂L/∂S : (4, 4) = softmax_backward(A, ∂L/∂A)
∂L/∂Q : (4, 4) = (∂L/∂S) @ K / sqrt(d_k)
∂L/∂K : (4, 4) = (∂L/∂S).T @ Q / sqrt(d_k)
Crítico: el /sqrt(d_k) sobrevive al backward — aparece en ∂L/∂Q y ∂L/∂K. Si te olvidas de escalar en el forward, pierdes este factor también en el backward — el /break de la Fase 15 lo expone.
Lo que muestra el ejemplo numérico¶
- En init, attention es aproximadamente uniforme. Cada fila de
Atiene entradas en[0.24, 0.51]. El patrón "mírame" no existe todavía. - La máscara causal pone a cero las contribuciones futuras. La fila 0 solo atiende a sí misma; la fila 1 a las posiciones 0–1; etc.
- El modelo puede hacer cualquier cosa ajustando
W_Q,W_K. Con init aleatorio, attention es uniforme; el entrenamiento la afilará en los patrones que vemos en modelos pre-entrenados (el lab de la Fase 17 los visualiza). - El softmax preserva la forma
(T, T). Las dimensiones no cambian dentro de attention — solo en el pasoA Vdonde contraemos sobre el ejeT(de keys).
Presupuesto de cómputo para attention de longitud 4¶
Q K^T : 4 · 4 · 4 = 64 muls
scale : 16 ops
softmax (per row): 4 exp + 4 sum + 4 div = ~32 ops per row × 4 = 128
mask : 6 sets to -inf
A V : 4 · 4 · 4 = 64 muls
Total : ~270 muls + ~150 small ops + 4 exponentials per row
Para longitud-32 (una frase realista del §A13): T^2 d_k = 1024 · 4 = 4096 muls por matriz — manejable en CPU. Para longitud-2048 (una historia pequeña): 2048^2 · 64 = 268M muls — necesita la GPU de la Fase 23. Aquí es donde la KV cache de la Fase 22 y Flash attention de la Fase 27 se vuelven críticos.
Citas¶
- Vaswani, A. et al. 2017. "Attention is All You Need." arXiv:1706.03762. La sección 3.2 deriva attention; la §3.2.1 explica el escalado
sqrt(d_k). - El ejemplo numérico trabajado sigue el patrón en "The Annotated Transformer" de Sasha Rush (https://nlp.seas.harvard.edu/2018/04/03/attention.html) pero se calcula de forma independiente para el §A13.
Recapitulación en un párrafo¶
Un pase de attention single-head de longitud 4 sobre embeddings §A13 calcula Q K^T / sqrt(d_k), aplica una máscara causal, toma softmax por filas para obtener A, luego Y = A V. Con init identidad la matriz de atención es aproximadamente uniforme a lo largo de las posiciones permitidas: fila 0 = self; fila 1 = 50/50; fila 3 = ~uniforme sobre 4. El gradiente backward ∂L/∂Q = (∂L/∂S) K / sqrt(d_k) preserva el factor de escalado — olvidarlo en el forward también rompe el backward. El coste de cómputo es O(T² d) para el bloque de attention; en T = 4 son unos pocos cientos de ops, en T = 2048 es el cuello de botella que abordan la Fase 22 y la Fase 27.
Anterior: 04-masking.md
Siguiente: Fase 16 (codificaciones posicionales).