¿Qué palabras anteriores importan para esta?
La atención es el paso de un transformer en el que cada token mira a los demás tokens y toma de ellos lo que necesita. Gracias a ella, un modelo de lenguaje une «él» con el nombre correcto, varias palabras atrás.
En «el tren va lleno», la palabra lleno habla del tren. La atención es la forma en que el modelo lo descubre con números.
Al final de esta lección
Nota
Puedo calcular a mano la salida de la atención para un token.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Consulta | un vector que dice qué busca un token (query en inglés) | |
| Clave | un vector que dice qué ofrece un token (key en inglés) | |
| Valor | un vector que lleva lo que un token transmite (value en inglés) | |
| Puntuación | cuánto encaja una consulta con una clave | 2 |
| Softmax | convierte puntuaciones en partes que suman 1 | |
| Peso | la parte de un valor que entra en la salida | 0,665 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Consulta, clave y valor para cada token
En álgebra lineal, una tabla de números multiplica un vector. La atención multiplica cada vector de entrada por tres tablas aprendidas, y salen tres vectores nuevos.
La consulta dice qué busca este token. La clave dice qué ofrece a los demás. El valor es lo que transmite si lo eligen. Abajo partimos de los tres vectores ya calculados.
Ejemplo resuelto: puntuar la consulta de lleno
| Token | Clave | Consulta de lleno por clave | Puntuación |
|---|---|---|---|
| tren | 2, 1 | 1x2 + 0x1 | 2 |
| va | 0, 2 | 1x0 + 0x2 | 0 |
| lleno | 1, 1 | 1x1 + 0x1 | 1 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Softmax convierte las puntuaciones en pesos
Las puntuaciones pueden tener cualquier tamaño, incluso por debajo de 0. El softmax las convierte en pesos todos positivos que suman 1.
Primero se calcula e elevado a cada puntuación, la tecla exp de una calculadora. Cada número se vuelve positivo, y una puntuación grande crece mucho más. Luego se divide cada uno por el total. Los modelos reales también dividen antes cada puntuación por un número fijo. Aquí nos saltamos ese paso.
Ejemplo resuelto: softmax de 2, 0 y 1
| Token | Puntuación | e elevado a la puntuación | Peso: dividir por 11,11 |
|---|---|---|---|
| tren | 2 | 7,39 | 0,665 |
| va | 0 | 1,00 | 0,090 |
| lleno | 1 | 2,72 | 0,245 |
| Total | 11,11 | 1,000 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Puntuaciones y pesos con NumPy
docker exec jupyter python3 -c "import numpy as np; K = np.array([[2, 1], [0, 2], [1, 1]]); s = K @ np.array([1, 0]); w = np.exp(s) / np.exp(s).sum(); print(s.tolist(), w.round(3).tolist())"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
La salida mezcla los valores con pesos
El valor de cada token se multiplica por su peso, y luego se suman los resultados. Esa suma es el nuevo vector de lleno.
Lleno toma unos dos tercios (0,665) del valor de tren, así que ahora lleva una parte del sentido de tren. Cada token hace lo mismo con su propia consulta, al mismo tiempo.
Ejemplo resuelto: mezclar los valores
| Token | Peso | Valor | Peso por valor |
|---|---|---|---|
| tren | 0,665 | 10, 0 | 6,65, 0 |
| va | 0,090 | 0, 10 | 0, 0,90 |
| lleno | 0,245 | 5, 5 | 1,22, 1,22 |
| Salida | unos 7,88, 2,12 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
La atención para un token en Python
import math
keys = [[2, 1], [0, 2], [1, 1]] # tren, va, lleno
values = [[10, 0], [0, 10], [5, 5]]
query = [1, 0] # la consulta de lleno
scores = []
for key in keys:
scores.append(query[0] * key[0] + query[1] * key[1])
powers = []
for s in scores:
powers.append(math.exp(s))
total = sum(powers)
weights = []
for p in powers:
weights.append(p / total)
mix = [0, 0]
for i in range(len(values)):
for j in range(2):
mix[j] = mix[j] + weights[i] * values[i][j]
print("puntuaciones:", scores)
print("pesos:", [round(w, 3) for w in weights])
print("salida:", [round(m, 2) for m in mix])
# Cambia la consulta por [0, 1] y pulsa Ejecutar.
# ¿Qué token recibe ahora más peso?
Un error frecuente
Advertencia
Mucha gente piensa que la atención elige un token e ignora los demás. Toma una parte del valor de cada token. Un peso está cerca de 0 solo cuando la clave encaja mal con la consulta, y los pesos siempre suman 1.
La atención de los tres tokens
docker exec jupyter python3 -c "import numpy as np; Q = np.array([[0, 1], [1, 1], [1, 0]]); K = np.array([[2, 1], [0, 2], [1, 1]]); V = np.array([[10, 0], [0, 10], [5, 5]]); S = Q @ K.T; W = np.exp(S) / np.exp(S).sum(axis=1, keepdims=True); print(W.round(3).tolist()); print((W @ V).round(2).tolist())"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.