Skip to content

English · Español

00 — Motivación: attention como enrutamiento diferenciable de información

El pipeline de attention, de principio a fin

Attention no es "magia"; es un mecanismo de enrutamiento diferenciable. Cada token de salida es una combinación ponderada de todos los tokens de entrada, donde los pesos los aprende el modelo. Eso resuelve los dos problemas que la Fase 14 dejó abiertos: gradiente largo (cada par token-token tiene un camino directo) y paralelismo (el cálculo se hace de golpe sobre toda la secuencia).

Este archivo responde a: ¿qué problema resuelve attention?


Los dos problemas que la Fase 14 dejó abiertos

Al final de la Fase 14 teníamos dos fallos precisos de los modelos recurrentes:

  1. Gradiente que se desvanece/explota a través del tiempo. El gradiente desde una pérdida en el paso \(T\) hacia atrás a una entrada en el paso \(t\) fluye a través de \((T - t)\) multiplicaciones por la matriz \(W_{hh}\). El producto se desvanece o explota geométricamente.
  2. Cómputo serial sobre el eje de la secuencia. Calcular \(h_t\) requiere \(h_{t-1}\). La cadena es inherentemente secuencial; no hay paralelismo posible a lo largo del eje temporal.

GRU/LSTM parchean el problema 1 (camino aditivo) pero no hacen nada por el problema 2. Attention resuelve ambos, reemplazando la recurrencia por completo.

El reencuadre: enrutamiento, no recurrencia

El paradigma recurrente dice: "para producir la salida \(y_t\), resumir el prefijo en un estado de tamaño fijo \(h_{t-1}\), luego combinar con \(x_t\)".

Attention dice: "para producir la salida \(y_t\), mirar a cada token previo \(x_1, \ldots, x_t\), y decidir cuánto contribuye cada uno".

Concretamente: \(y_t\) es una suma ponderada de representaciones (transformadas) de tokens previos. Los pesos \(\alpha_{t,j}\) para \(j = 1, \ldots, t\) nos dicen cuánto contribuye la posición \(j\) a la salida en la posición \(t\). Los pesos los calcula el modelo — son aprendidos — así que attention es una búsqueda diferenciable, direccionada por contenido.

En forma de ecuación (la derivaremos cuidadosamente en theory/02-scaled-dot-product.md):

\[ y_t = \sum_{j=1}^{t} \alpha_{t,j} \cdot v_j \]

donde \(v_j\) es el "value" asociado con la posición de entrada \(j\), y \(\alpha_{t,j}\) es el peso de atención de la posición \(t\) a la posición \(j\).

Los pesos \(\alpha_{t,j}\) suman 1 sobre \(j\) (forman una distribución de probabilidad), y se calculan mediante una pequeña red separada sobre la marcha. El truco es que esta pequeña red está ella misma parametrizada por unas pocas matrices aprendibles, y sus salidas dependen del contenido — prefijos diferentes producen pesos diferentes.

Por qué esto arregla el problema 1 (gradiente)

La retropropagación (backpropagation) desde \(y_t\) hasta la entrada \(x_j\) fluye a través de un peso de softmax \(\alpha_{t,j}\). No 50 multiplicaciones de matrices. Una sola decisión suave de enrutamiento.

Por esto los transformers pueden manejar longitudes de contexto de miles de tokens que las RNN no pueden. El gradiente desde el token 1000 hasta el token 1 pasa por los pesos de atención de una sola capa — cada par tiene un camino directo. No hay desvanecimiento.

Por qué esto arregla el problema 2 (paralelismo)

Para calcular \(y_1, y_2, \ldots, y_T\), calculas todos los \(\alpha_{t,j}\) de golpe: eso es una matriz \(T \times T\). Luego calculas las sumas ponderadas: eso es un matmul \(T \times T\) por \(T \times d_v\).

Ningún paso depende de la salida del paso anterior. Al hardware moderno le encanta esto — son dos multiplicaciones grandes de matrices, paralelizables a través de núcleos, GPUs o TPUs trivialmente.

El bucle de entrenamiento de la RNN es un for t in range(T) sobre el eje de la secuencia. El bucle de entrenamiento del transformer es un matmul sobre el eje de la secuencia. Para \(T = 1000\) y una GPU con 10000+ núcleos, esa es la diferencia entre 1000 micro-operaciones secuenciales y 1 matmul gordo.

Cómo se ve attention en nuestro ejemplo trabajado

El ejemplo canónico de la Fase 15 es la secuencia de 8 tokens:

position:  0    1     2    3      4     5    6    7
token:     I    work  ,    you    work  ,    he   ___

La tarea es predecir el token en la posición 7. La respuesta correcta es works (3ª persona singular del present simple de work, concordando con he).

¿Cómo debería verse la atención desde la posición 7? Piensa mecánicamente:

  • Para elegir la forma verbal correcta, el modelo necesita conocer el pronombre sujeto. Ese es he en la posición 6.
  • El modelo también necesita conocer la raíz verbal. La raíz verbal más reciente es work en la posición 4 (o 1 — ambas son plantillas válidas).
  • El modelo necesita conocer el patrón temporal. De la ausencia de will / is going to y la presencia de pronombres seguidos de verbos desnudos, esto es present simple.

Así que una cabeza de atención ideal dedicada a "predecir la siguiente forma verbal" debería producir, en la posición 7, una distribución de pesos que ponga la mayor masa en las posiciones 6 (he) y 4 (work), con quizás algo de masa en 1 (el work anterior). Los pesos en las posiciones 2, 3, 5 (separadores y el pronombre redundante you) deberían ser más bajos.

Eso es lo que hace attention. Una distribución de pesos sobre posiciones previas, aprendida para destacar las relevantes para la predicción que toca.

Advertencia crítica: la atención no entrenada es aleatoria. La Fase 15 solo verifica el mecanismo. La Fase 18 lo entrena. La Fase 18 mostrará que este patrón aprendido realmente emerge.

Múltiples cabezas = múltiples especialistas

Una sola cabeza de atención produce un promedio ponderado. Para una predicción compleja, el modelo a menudo necesita combinar varios tipos de contexto — p. ej.:

  • Una cabeza que atiende al pronombre sujeto (para la concordancia de persona).
  • Una cabeza que atiende al token auxiliar (para la identificación de tiempo).
  • Una cabeza que atiende al alineamiento inglés↔español (I work / yo → predice trabajo).

Multi-head attention corre \(H\) cálculos de attention en paralelo, cada uno con sus propias proyecciones Q, K, V, y luego concatena sus salidas. El modelo puede usar diferentes cabezas para diferentes patrones de enrutamiento.

En la Fase 17, el Mini-GPT usará \(H = 4\) cabezas. Observaremos en la Fase 18 (post-entrenamiento) si las cabezas se especializan naturalmente como se describe, o si la asignación es más difusa. (Spoiler: a esta escala, la especialización de cabezas es parcial — la interpretación limpia cabeza-por-cabeza es un tema de investigación, no un resultado garantizado.)

El puente a la Fase 16

Attention tiene una propiedad crucial que necesitará ser parcheada en la Fase 16:

Attention es equivariante bajo permutación.

Esto es: si permutas los tokens de entrada, la salida queda permutada por la misma permutación. El modelo no conoce el orden, porque el cálculo de atención no tiene noción de qué posición \(j\) es en relación con la posición \(t\) — solo de qué hay en la posición \(j\) (el value \(v_j\)) y cuánto coincide con el query en \(t\).

Para nuestra tarea de gramática verbal, esto es un desastre. I work, you work, he ___ y , he , you work I work son el mismo conjunto de tokens, solo en un orden diferente. Attention sin información de posición no puede distinguirlos.

La Fase 16 añade codificación posicional para arreglar esto. La Fase 15 construye el núcleo ciego a la posición. Ambas son necesarias.

Por qué "búsqueda diferenciable en diccionario" es la intuición correcta

Una búsqueda regular en diccionario: dada una key, devolver el value en esa key. La búsqueda es discreta — las keys coinciden exactamente o no.

Una búsqueda diferenciable: dado un query, calcular un score de similitud entre el query y cada key. Convertir los scores en una distribución de probabilidad (softmax). Devolver un promedio ponderado de los values.

Esto es lo que hace attention:

  • Cada token de entrada recibe una key (qué es, para fines de coincidencia).
  • Cada token de entrada recibe un value (qué devolver si hay coincidencia).
  • La posición actual emite un query (qué está buscando).
  • El query se compara con cada key (producto escalar). Los scores pasan por softmax para convertirse en una distribución. La salida es la suma ponderada de los values.

La búsqueda discreta en diccionario es el caso límite donde un \(\alpha\) es 1 y el resto son 0. La versión diferenciable interpola suavemente entre "atender a una posición" y "atender a todas las posiciones uniformemente".

La "suavidad" es lo que la hace aprendible: los gradientes fluyen a través del softmax para ajustar tanto las keys (para que coincidan con los queries correctos) como los values (para que la información correcta esté en cada key).

Lo que esta fase no te enseñará

Para mayor claridad, lo siguiente está fuera de alcance en la Fase 15:

  • Entrenar attention. Fase 18. Aquí solo verificamos el forward y la corrección de las formas.
  • Comparar con PyTorch. Anti-objetivo §10 (no PyTorch antes de la Fase 24); en su lugar contrastamos con un ejemplo de 2 tokens derivado a mano. La verificación cruzada con PyTorch se mueve a la Fase 25.
  • Flash attention, paged attention, sparse attention. Fase 27. Implementamos la forma ingenua \(O(T^2)\) a propósito para que las optimizaciones de la Fase 27 tengan un objetivo.
  • Cross-attention. Mencionada en una línea ("misma ecuación, Q de una secuencia, K/V de otra"). Estamos construyendo un modelo decoder-only; cross-attention no aparecerá en otra parte del currículo.
  • Codificación posicional. Fase 16.

Lo que deberías sentir al final de la fase

Tres sensaciones:

  1. La ecuación como operación de enrutamiento. \(\text{softmax}(QK^\top / \sqrt{d_k}) V\) debería leerse, cuando la miras, como: "calcular similitudes por pares, normalizarlas, usarlas como pesos para los values". Cada pieza hace un trabajo.
  2. El argumento de varianza para \(\sqrt{d_k}\). Esta es la única pieza de matemáticas en attention que sorprende a todo el mundo la primera vez. Una vez que la has derivado, la pregunta "¿por qué hay una raíz cuadrada?" desaparece para siempre.
  3. Multi-head como capacidad de especialización. Sin multi-head, attention solo puede atender en un patrón a la vez. Con multi-head, el modelo tiene \(H\) patrones. Si se especializan como te gustaría es una cuestión de entrenamiento, pero la capacidad de especializarse está construida.

El camino a través de la Fase 15

  • Theory 01 hace Q, K, V desde la analogía de búsqueda en diccionario. Por qué tres matrices.
  • Theory 02 deriva la ecuación completa. El argumento de \(\sqrt{d_k}\). Estabilidad del softmax.
  • Theory 03 hace multi-head. La visión de "múltiples especialistas".
  • Theory 04 hace el enmascarado. Máscara causal, máscara de padding, aditivo-vs-multiplicativo.
  • Labs 00–03 implementan todo en NumPy y verifican la corrección contra referencias derivadas a mano.

Detente aquí si

Estás tentado a leer la Fase 15 por encima. No lo hagas. Cada fase posterior importa de attention.py. Cada fase posterior asume que puedes derivar las matemáticas. Una lectura por encima ahora son dos semanas de confusión en las Fases 17–22. La profundidad aquí es el punto.

La pregunta que tienes que poder responder al salir de esta fase: "¿por qué exactamente attention reemplazó a las RNN?". Si tu respuesta no incluye los dos puntos (gradiente directo + paralelismo sobre la secuencia), la fase no ha aterrizado. Vuelve a leer.


Siguiente: theory/01-query-key-value.md.