Atención
¿Cómo decide una palabra a cuáles otras mirar?
Lección completa
Si quieres:
Lee esta frase: «Me senté en el banco de mi jardín». Aquí, un banco es un asiento.
Sin voz: la lección avanza sola con subtítulos.
La voz de esta lección está en preparación: por ahora avanza sola con subtítulos.
Modo revisiónComentar este pasoTerminé la lección
Qué lograrás
- Explicar por qué un token necesita mirar a los demás para tener sentido, y cómo la atención decide a quién mirar y cuánto.
- Calcular a mano, con vectores de dos números, un producto punto, los pesos de atención con softmax y la mezcla de valores.
- Reconocer qué resume la fórmula softmax(QKᵀ/√d)V, para qué sirven varias cabezas y qué ganan y cuestan todos los tokens a la vez.
Ideas clave
- Una palabra puede significar cosas distintas («banco»), pero entra al modelo con un solo vector. Para entenderla hay que mirar las demás: eso hace la atención.
- Cada token produce una consulta (lo que busca), una clave (cómo se deja encontrar) y un valor (lo que entrega). El producto punto dice qué tanto coinciden una consulta y una clave.
- Softmax convierte las puntuaciones en pesos de atención que suman cien por ciento, y el nuevo vector de cada token es la mezcla de los valores con esos pesos.
- Todo se resume en softmax(QKᵀ/√d)·V. Se divide entre √d para que, con vectores largos, softmax no le dé todo el peso a un solo token.
- Varias cabezas miran cosas distintas a la vez, y todos los tokens se calculan al mismo tiempo: rápido en una GPU, pero el costo crece con el cuadrado de la longitud del texto.
Lo que mucha gente cree
Creencia común Un mapa de atención muestra por qué el modelo respondió lo que respondió: lo que «miró» es su razón.
Lo correcto Muestra cómo reparte sus pesos una cabeza, en una capa. Es una pista de por dónde fluye la información, pero la respuesta depende de muchas cabezas y capas, y pesos muy distintos pueden dar la misma respuesta. Si eso cuenta como explicación sigue en debate.
Compruébalo
Cuatro preguntas. Sin nota ni cuenta: sirven para ver si la idea quedó.
Por dentroPara quien quiere las fórmulas y el código. No hace falta para seguir el curso.
La fórmula
Para tokens, se apilan sus consultas y claves (de números) y sus valores (de ) en matrices y :
Fila por fila: la puntuación del token sobre el es ; el peso es (cada fila suma 1) y la salida es . Es la «atención de producto punto escalado» de Vaswani et al. (2017), que la describen como una función que lleva una consulta y un conjunto de pares clave-valor a una salida: una suma ponderada de los valores.
En la escena, la consulta de «banco» es y la clave de «jardín» : . Las puntuaciones dan , , y ; la suma es , y los pesos, , , y . La escena no divide entre para que las cuentas se sigan de cabeza; con la división, los pesos serían , , y , y el vector nuevo, en vez de : el mismo lado, menos marcado. Todos los números del ejemplo están escritos a mano (ver data.ts).
De dónde salen Q, K y V
Si es la matriz de vectores de entrada (embeddings; en un transformer, más la posición), , y . Esas tres matrices son los parámetros que se aprenden; los pesos no: se calculan de nuevo para cada frase. En la autoatención, , y salen de la misma . En la atención de Bahdanau et al. (2014), para traducir, las consultas venían del decodificador y las claves y valores del codificador, y la puntuación era una red pequeña, , en lugar de un producto punto; los pesos eran el mismo softmax y el resultado, la misma suma ponderada . Los autores lo dicen así: el decodificador decide a qué partes de la frase de origen prestar atención.
Por qué
Si las componentes de y son independientes, con media 0 y varianza 1, el producto tiene media 0 y varianza (nota 4 de Vaswani et al., 2017): su tamaño típico es , ocho con . Dividir entre devuelve la varianza a 1. Sin ello, el softmax se satura: si , entonces , que tiende a 0 cuando un peso se acerca a 1 y los demás a 0. Es la «pendiente casi nula» de la narración. Con ocho claves al azar y , el peso mayor promedia sin dividir y dividiendo (100 sorteos; el sorteo de la escena da y ).
Varias cabezas
Según Vaswani et al. (2017), varias cabezas permiten atender a la vez a información de distintos «subespacios» de representación; con una sola, el promedio lo impide. En su modelo base, y , así que ocho cabezas cuestan casi lo mismo que una grande. BERT base tiene 12 capas de 12 cabezas (144) con 768 dimensiones, es decir, por cabeza (Devlin et al., 2018).
Los mapas reales de la lección
Se calcularon con real-attention.py (en la carpeta de la lección; corre en CPU): bert-base-uncased para el inglés y bert-base-multilingual-cased para el español, ambos con licencia Apache-2.0 y revisión fijada. Son los pesos de una sola cabeza tras softmax, sin promediar; las piezas de una palabra se suman. La cabeza de «banco» se eligió así: entre las cabezas en las que el mayor peso de «banco» cae en la palabra que decide su sentido en las dos frases (jardín y dinero), la de mayor suma de esos dos pesos. Solo 4 de 144 cumplen esa condición en español (capa 1, cabeza 4: 44 % y 65 %) y 6 de 144 en inglés (capa 3, cabeza 11: 93 % y 60 %). En cambio, el mayor peso de «banco» cae en una marca ([CLS], [SEP] o el punto) en 58 de 144 cabezas en español y en 113 de 144 en inglés. Las otras tres son las de mayor peso promedio en la palabra anterior, en la siguiente y en las marcas. Clark et al. (2019) describen estos mismos tipos de cabeza en BERT: las que miran a los delimitadores, las que miran a una posición fija y las que miran a toda la frase.
Costo
La matriz de pesos es : el cómputo por capa crece como . Una capa recurrente cuesta , pero necesita pasos uno tras otro, y la información entre dos posiciones recorre un camino de longitud ; en la autoatención, ambos son (tabla 1 de Vaswani et al., 2017). Por eso la atención aprovecha bien una GPU, y por eso los contextos largos son caros.
En código
import numpy as np
def softmax(x):
e = np.exp(x - x.max(axis=-1, keepdims=True))
return e / e.sum(axis=-1, keepdims=True)
def attention(Q, K, V, scale=True):
d = K.shape[-1]
scores = Q @ K.T # productos punto: qué tanto coincide cada consulta con cada clave
if scale:
scores = scores / np.sqrt(d) # la pieza que la escena deja para el final
weights = softmax(scores) # cada fila suma 1
return weights @ V, weights # mezcla ponderada de los valores
# «Me senté en el banco de mi jardín»: los números de la escena (d = 2)
K = np.array([[-1.6, 0], [-0.3, 1], [-0.8, -0.8], [-0.8, -0.8],
[0.5, -0.5], [-0.8, -0.8], [-0.8, -0.8], [1, 0.8]])
V = np.array([[0, 0], [0.5, 0], [0, 0], [0, 0],
[0.5, 0.5], [0, 0], [0, 0], [1, 0]]) # (asiento, dinero)
q = np.array([[1.0, 1.0]]) # la consulta de «banco»
out, w = attention(q, K, V, scale=False)
print(np.round(w, 2), np.round(out, 2))
out, w = attention(q, K, V) # con la división entre √2
print(np.round(w, 2), np.round(out, 2))
# [[0.02 0.2 0.02 0.02 0.1 0.02 0.02 0.6 ]] [[0.75 0.05]]
# [[0.04 0.21 0.04 0.04 0.13 0.04 0.04 0.46]] [[0.63 0.06]]
Y la comprobación de : la desviación típica de crece como ; al dividir, queda en 1.
rng = np.random.default_rng(0)
for d in (1, 2, 64, 512):
q = rng.standard_normal((20000, d))
k = rng.standard_normal((20000, d))
s = (q * k).sum(axis=1) # 20 000 productos punto q·k
print(d, round(s.std(), 1), round((s / np.sqrt(d)).std(), 2))
# 1 1.0 1.0
# 2 1.4 1.0
# 64 8.0 1.0
# 512 22.6 1.0
Lo que viene
Falta lo que la atención sola no hace: no sabe el orden de las palabras (si se barajan, cada token reparte lo mismo entre los mismos tokens), y al escribir texto cada token solo puede mirar hacia atrás (antes del softmax se pone en las puntuaciones que miran al futuro). Con una codificación de posición, esa máscara, una red por token, conexiones residuales y normalización, se apilan bloques: el transformer, en la lección 22.
Lente de decisión
Qué significa esta idea si tu trabajo es decidir, no programar.
- Cada token se compara con todos los demás: el costo de la atención crece con el cuadrado del contexto. Duplicar el texto cuesta unas cuatro veces más comparaciones; es una de las razones por las que los contextos largos son caros (lecciones 26 y 30).
- Un mapa de atención no es una explicación. Si un proveedor muestra «a qué miró el modelo» como justificación de una respuesta, pide además pruebas con casos tuyos y medidas de calidad (lecciones 33 y 34).
- Todo lo que está en el contexto puede influir en todo lo demás: la arquitectura no distingue por sí sola entre una instrucción tuya y un documento ajeno. De ahí el riesgo de inyección de instrucciones: separa y valida lo que entra (lección 35).
- Más contexto no garantiza más comprensión: con más tokens, la atención se reparte entre más candidatos. Prueba con tus documentos largos y no supongas que el modelo usa todo por igual (lección 30).
Términos de la lección
- Token Pieza de texto (una palabra, un trozo de palabra, un signo o un código básico) tomada del vocabulario. Es la unidad que el modelo lee y genera, y por la que se cobra.
- Embedding Vector de números, aprendido de los datos, que representa algo (una palabra, una frase, una imagen) de modo que lo parecido quede cerca. Cada palabra tiene una fila en una tabla de embeddings.
- Vector Lista ordenada de números. En aprendizaje automático, cada ejemplo llega al modelo como un vector.
- Similitud coseno Coseno del ángulo entre dos vectores: 1 si apuntan igual, 0 si son perpendiculares, −1 si se oponen. Ignora la longitud y mide solo la dirección.
- Softmax Función que convierte puntajes cualesquiera en probabilidades positivas que suman uno: aplica la exponencial a cada puntaje y divide entre la suma.
- Peso (w) En un modelo lineal, el número que multiplica a la entrada: la pendiente de la recta. Indica cuánto sube la predicción por cada unidad que aumenta la entrada.
- Capa Grupo de neuronas que reciben las mismas entradas y calculan a la vez. Una red es una cadena de capas: entrada, una o más ocultas, y salida.
- Gradiente La lista de las pendientes del error, una por cada peso. Vista como flecha, apunta hacia donde el error sube más rápido.
- Red recurrente (RNN) Red que procesa una secuencia paso a paso con la misma celda: en cada paso recibe la entrada actual y el estado oculto anterior, y produce un estado nuevo.
- GPU Unidad de procesamiento gráfico: un chip con cientos o miles de núcleos sencillos, creado para dibujar gráficos y muy eficiente para multiplicar matrices en paralelo, la operación central del entrenamiento.
- Atención Mecanismo con el que cada token decide cuánto mirar a los demás: compara su consulta con las claves de todos, convierte las puntuaciones en pesos con softmax y arma su nuevo vector como la mezcla de los valores con esos pesos.
- Consulta, clave y valor (Q, K, V) Los tres vectores que produce cada token: la consulta dice qué busca, la clave cómo se le encuentra y el valor qué entrega. Salen de multiplicar su vector por tres matrices de pesos aprendidas.
- Autoatención Atención en la que consultas, claves y valores salen de la misma secuencia: cada token mira a los demás tokens de su propio texto, y a sí mismo.
- Atención de varias cabezas Varias atenciones en paralelo, cada una (una cabeza) con sus propias matrices para Q, K y V y su propio mapa. Sus resultados se juntan y se combinan con una última matriz.
Transcripción completa
Fuentes
- Bahdanau, D., Cho, K., Bengio, Y. (2014). Neural Machine Translation by Jointly Learning to Align and Translate
- Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł., Polosukhin, I. (2017). Attention Is All You Need
- Devlin, J., Chang, M.-W., Lee, K., Toutanova, K. (2018). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
- Google; Hugging Face (2018). bert-base-uncased (ficha del modelo; Apache-2.0)
- Google; Hugging Face (2018). bert-base-multilingual-cased (ficha del modelo; Apache-2.0)
- Clark, K., Khandelwal, U., Levy, O., Manning, C. D. (2019). What Does BERT Look At? An Analysis of BERT’s Attention
- Jain, S., Wallace, B. C. (2019). Attention is not Explanation
- Wiegreffe, S., Pinter, Y. (2019). Attention is not not Explanation
ComentariosConversación pública de esta lección: dudas, datos por revisar, ideas.
Los comentarios viven en GitHub Discussions, en el repositorio público del curso; para escribir se necesita una cuenta de GitHub. Se cargan desde giscus.app al abrir esta sección. Las personas que revisan el curso los leen, y si un cambio se acepta, se aplica en los dos idiomas. Abrir el hilo en GitHub