Lección 2 de 10 · El mecanismo de atención · 22 min
Scaled dot-product attention: Q, K, V y el misterioso √d_k
Derivamos la operación central del Transformer, entendemos queries, keys y values como una búsqueda difusa y demostramos por qué hay que dividir por √d_k.
Notebook del episodio
El código de esta lección, para correrlo y modificarlo en Google Colab, gratis y con tu cuenta. Para guardar tus cambios: Archivo → Guardar una copia en Drive.
La ecuación que vale un paper
Todo el Transformer gira alrededor de una sola línea:
Vamos a desarmarla con calma, porque cada símbolo tiene una razón de ser.
Queries, keys y values: una búsqueda difusa
La metáfora más útil es la de una base de datos. En un diccionario de Python haces d[query] y obtienes el valor cuya clave coincide exactamente. La atención es una versión suave y diferenciable de esa búsqueda:
- Cada posición emite una query (): "¿qué estoy buscando?"
- Cada posición expone una key (): "esto es lo que ofrezco para que me encuentren".
- Cada posición guarda un value (): "esto es lo que entrego si me eligen".
En vez de elegir una única clave, comparas la query contra todas las keys, obtienes un puntaje de similitud para cada una, conviertes esos puntajes en una distribución de probabilidad y devuelves el promedio ponderado de los values.
En self-attention, , y salen de la misma secuencia de entrada mediante tres proyecciones lineales aprendidas:
con y . Que sean proyecciones distintas importa: lo que una palabra busca no tiene por qué parecerse a lo que ofrece. Un verbo puede buscar su sujeto (query) mientras ofrece información de tiempo verbal (value).
Paso a paso con las formas de los tensores
Supongamos una secuencia de tokens.
- Puntajes: , con forma . La entrada mide cuánto le interesa la posición a la posición .
- Escalado: . Ya veremos por qué.
- Softmax por fila: cada fila se convierte en una distribución que suma 1. La fila son los pesos de atención de la posición sobre todas las demás.
- Mezcla: multiplicas por () y obtienes una salida : cada posición es ahora una combinación convexa de los values.
Todo son multiplicaciones de matrices. No hay bucles sobre posiciones, no hay dependencias secuenciales: la GPU calcula las interacciones de una vez.
import math
import torch
import torch.nn.functional as F
def scaled_dot_product_attention(q, k, v, mask=None):
# q: (..., n_q, d_k) k: (..., n_k, d_k) v: (..., n_k, d_v)
d_k = q.size(-1)
scores = q @ k.transpose(-2, -1) / math.sqrt(d_k) # (..., n_q, n_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, float("-inf"))
weights = F.softmax(scores, dim=-1) # cada fila suma 1
return weights @ v, weights # (..., n_q, d_v)
Softmax y temperatura
Antes de hablar del escalado, conviene tener intuición sobre softmax. Dado un vector de puntajes :
convierte una lista de puntajes en porcentajes que suman 1: cada dividido por la suma de todos. El más alto se lleva la mayor parte
Softmax es sensible a la escala de sus entradas. Si multiplicas todos los puntajes por una constante grande, la distribución se vuelve casi one-hot: el máximo se lleva todo. Si los multiplicas por una constante chica, la distribución se aplana hacia uniforme. Juega con la temperatura en el widget y mira qué pasa con los pesos y con su entropía:
Dividir por es exactamente ajustar esa temperatura. La pregunta es por qué ese valor.
El argumento de varianza
Supón que las componentes de y son variables aleatorias independientes con media 0 y varianza 1 (algo razonable con una buena inicialización y normalización). El producto punto es:
el producto punto: multiplicar componente a componente y sumar los resultados
Cada término tiene media y varianza . Como los términos son independientes, las varianzas se suman:
en promedio da cero, pero su dispersión (la varianza) crece igual que : con más dimensiones, puntajes más extremos
La desviación estándar del producto punto crece como . Con (el valor del paper), los puntajes típicos andan en el orden de ; con dimensiones más grandes, peor. Puntajes así de grandes empujan al softmax a su régimen saturado: un elemento cerca de 1, el resto cerca de 0.
¿Y por qué es malo? Porque en la saturación los gradientes del softmax son minúsculos. La derivada se anula cuando todas las probabilidades son 0 o 1. El modelo deja de aprender a redistribuir su atención.
Dividiendo por :
dividir por devuelve la dispersión a 1, sea cual sea la dimensión
Los puntajes vuelven a tener varianza unitaria, independientemente de la dimensión, y el softmax opera en su zona sana.
“We suspect that for large values of d_k, the dot products grow large in magnitude, pushing the softmax function into regions where it has extremely small gradients.”
Comprueba tu comprensión
Si las componentes de q y k son independientes con media 0 y varianza 1, ¿cuál es la varianza del producto punto q·k en dimensión d_k?
Por qué producto punto y no atención aditiva
El paper discute explícitamente la alternativa: la atención aditiva de Bahdanau, que usa una pequeña red feed-forward para calcular la compatibilidad. Ambas tienen complejidad teórica similar, pero el producto punto es mucho más rápido y eficiente en memoria en la práctica, porque se reduce a multiplicaciones de matrices altamente optimizadas.
Un detalle interesante: el paper observa que para chico ambas funcionan parecido, pero sin escalado la aditiva supera al producto punto con grande. El escalado es lo que permite quedarse con la opción rápida sin perder calidad.
Juega con la atención
En el widget de abajo puedes escribir una oración y ver la matriz de atención resultante. Cada fila es una query; cada columna, una key. El color indica el peso tras el softmax. Prueba cambiar la oración y fíjate cómo las filas siempre suman 1:
Comprueba tu comprensión
En la matriz de pesos de atención softmax(QKᵀ/√d_k), ¿qué propiedad cumple cada fila?
Una sutileza: la matriz no es simétrica
Como , en general . Que "el" atienda mucho a "gato" no implica que "gato" atienda mucho a "el". Esta asimetría es deseable: las relaciones lingüísticas (modificador → modificado, pronombre → antecedente) son direccionales.
Resumen
- , , son proyecciones lineales de la entrada que implementan una búsqueda suave.
- calcula todas las similitudes en paralelo; softmax las convierte en pesos.
- El factor normaliza la varianza de los puntajes y evita la saturación del softmax.
- El costo es : cuadrático en la longitud de la secuencia.
En la próxima lección vamos a ver por qué una sola atención no alcanza y cómo el paper la multiplica en varias cabezas.
¿Qué tal esta lección?
Sé el primero en calificarla
¿Terminaste la lección?
Márcala para sumar +50 XP y mantener tu racha.
Tutor IA
Contexto: Scaled dot-product attention: Q, K, V y el misterioso √d_k
Conectando con el tutor…