Saltar al contenido
← Attention Is All You Need

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:

Attention(Q,K,V)=softmax ⁣(QK⊤dk)V\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right) V

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 (qq): "¿qué estoy buscando?"
  • Cada posición expone una key (kk): "esto es lo que ofrezco para que me encuentren".
  • Cada posición guarda un value (vv): "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, QQ, KK y VV salen de la misma secuencia de entrada X∈Rn×dmodelX \in \mathbb{R}^{n \times d_{\text{model}}} mediante tres proyecciones lineales aprendidas:

Q=XWQ,K=XWK,V=XWVQ = X W^Q, \quad K = X W^K, \quad V = X W^V

con WQ,WK∈Rdmodel×dkW^Q, W^K \in \mathbb{R}^{d_{\text{model}} \times d_k} y WV∈Rdmodel×dvW^V \in \mathbb{R}^{d_{\text{model}} \times d_v}. 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 nn tokens.

  1. Puntajes: S=QK⊤S = QK^\top, con forma n×nn \times n. La entrada Sij=qi⋅kjS_{ij} = q_i \cdot k_j mide cuánto le interesa la posición jj a la posición ii.
  2. Escalado: S/dkS / \sqrt{d_k}. Ya veremos por qué.
  3. Softmax por fila: cada fila se convierte en una distribución que suma 1. La fila ii son los pesos de atención de la posición ii sobre todas las demás.
  4. Mezcla: multiplicas por VV (n×dvn \times d_v) y obtienes una salida n×dvn \times d_v: 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 n2n^2 interacciones de una vez.

python
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 zz:

softmax(z)i=ezi∑jezj\text{softmax}(z)_i = \frac{e^{z_i}}{\sum_j e^{z_j}}

convierte una lista de puntajes en porcentajes que suman 1: cada ezie^{z_i} 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 dk\sqrt{d_k} es exactamente ajustar esa temperatura. La pregunta es por qué ese valor.

El argumento de varianza

Supón que las componentes de qq y kk son variables aleatorias independientes con media 0 y varianza 1 (algo razonable con una buena inicialización y normalización). El producto punto es:

q⋅k=∑i=1dkqikiq \cdot k = \sum_{i=1}^{d_k} q_i k_i

el producto punto: multiplicar componente a componente y sumar los dkd_k resultados

Cada término qikiq_i k_i tiene media E[qi]E[ki]=0\mathbb{E}[q_i]\mathbb{E}[k_i] = 0 y varianza E[qi2]E[ki2]=1⋅1=1\mathbb{E}[q_i^2]\mathbb{E}[k_i^2] = 1 \cdot 1 = 1. Como los dkd_k términos son independientes, las varianzas se suman:

E[q⋅k]=0,Var(q⋅k)=dk\mathbb{E}[q \cdot k] = 0, \qquad \text{Var}(q \cdot k) = d_k

en promedio da cero, pero su dispersión (la varianza) crece igual que dkd_k: con más dimensiones, puntajes más extremos

La desviación estándar del producto punto crece como dk\sqrt{d_k}. Con dk=64d_k = 64 (el valor del paper), los puntajes típicos andan en el orden de ±8\pm 8; 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 ∂ softmaxi/∂zj=softmaxi(δij−softmaxj)\partial\, \text{softmax}_i / \partial z_j = \text{softmax}_i(\delta_{ij} - \text{softmax}_j) se anula cuando todas las probabilidades son 0 o 1. El modelo deja de aprender a redistribuir su atención.

Dividiendo por dk\sqrt{d_k}:

Var ⁣(q⋅kdk)=dkdk=1\text{Var}\!\left(\frac{q \cdot k}{\sqrt{d_k}}\right) = \frac{d_k}{d_k} = 1

dividir por dk\sqrt{d_k} 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.”
— Sección 3.2.1

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 dkd_k chico ambas funcionan parecido, pero sin escalado la aditiva supera al producto punto con dkd_k 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 WQ≠WKW^Q \neq W^K, en general qi⋅kj≠qj⋅kiq_i \cdot k_j \neq q_j \cdot k_i. 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

  • QQ, KK, VV son proyecciones lineales de la entrada que implementan una búsqueda suave.
  • QK⊤QK^\top calcula todas las similitudes en paralelo; softmax las convierte en pesos.
  • El factor 1/dk1/\sqrt{d_k} normaliza la varianza de los puntajes y evita la saturación del softmax.
  • El costo es O(n2d)O(n^2 d): 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

Entra para calificar

¿Terminaste la lección?

Márcala para sumar +50 XP y mantener tu racha.