El transformer completo
¿Qué hay dentro de un LLM, bloque por bloque?
Lección completa
Si quieres:
Ya conoces las piezas: tokens, embeddings, atención y la predicción de la siguiente palabra. Hoy las armamos en una sola máquina: el transformer, la que está dentro de GPT.
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
- Seguir el camino completo de una frase dentro de un transformer: tokens, números, embeddings, bloques, puntajes, softmax y la siguiente palabra.
- Explicar qué hace cada pieza de un bloque (atención, red, conexión residual y normalización de capa) y por qué hacen falta la codificación de posición y la máscara causal.
- Calcular cuántos parámetros tiene cada parte de un transformer pequeño y reconocer dónde está casi todo el tamaño de un modelo real como GPT-3.
Ideas clave
- Un transformer recorre siempre el mismo camino: tokens, números, embeddings más posición, una pila de bloques y, con la lista del último token, doce puntajes (uno por palabra) que softmax vuelve probabilidades.
- Cada bloque tiene dos partes: la atención, el único camino por el que un token recibe información de los demás, y una red que procesa cada token por separado.
- Ninguna parte reemplaza la lista de un token: le suma su aporte (conexión residual). Antes de cada parte, la normalización de capa le resta su promedio y la divide entre su desviación estándar.
- La atención sola no sabe el orden: por eso se suma la codificación de posición. La máscara causal impide mirar el futuro; sin ella, el modelo aprende a copiar y no sirve para escribir.
- Los parámetros se cuentan por tablas. En un modelo grande casi todos están en la atención y en la red de los bloques: en GPT-3, el embedding es menos del uno por ciento.
Lo que mucha gente cree
Creencia común Un transformer lee el texto de izquierda a derecha, palabra por palabra, como una persona.
Lo correcto Todos los tokens entran a la vez y cada bloque los procesa en paralelo. El orden se lo da la codificación de posición, y es la máscara causal la que impide que cada token mire hacia delante. Lo que sí va palabra por palabra es la escritura: un pase completo por cada token nuevo.
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.
El pase completo, ecuación por ecuación
Para una secuencia de tokens con números , una tabla de embeddings (una fila de números por palabra del vocabulario) y bloques, en la variante «con normalización previa» de GPT-2, que es la de nuestro juguete (, ):
y, en cada bloque, con la normalización de capa:
Esas dos sumas son las conexiones residuales: cada parte suma su aporte a . Al salir del último bloque, la lista del último token da los puntajes (en inglés, logits) y softmax las probabilidades:
«Comparar con cada palabra del vocabulario» es exactamente esto: un producto punto con cada fila de , la misma tabla de la entrada. Reutilizarla ahorra parámetros; ya lo hacía el artículo de 2017 (sección 3.4) y la técnica se estudia en Press y Wolf (2017). Al entrenar se usan las posiciones a la vez: cada una predice el token siguiente.
La atención con máscara
Con , y como en la lección 21 y la máscara si y si :
Como , el futuro recibe peso cero. Así lo describe el artículo original para el decodificador: se pone en toda entrada de softmax que corresponda a una conexión «ilegal», para preservar la propiedad autorregresiva (sección 3.2.3). Nuestro juguete tiene dos cabezas de números por bloque; la tabla de la escena es una cabeza del segundo bloque.
El experimento. Entrenamos dos modelos idénticos (misma semilla, mismos datos, 4 000 pasos) y a uno le quitamos la máscara. Con frases nuevas, el modelo con máscara tiene una pérdida de 0.527 nats por palabra, casi la entropía de la gramática (0.526, el mínimo posible). El modelo sin máscara baja su pérdida de entrenamiento a 0.059 copiando, pero usado como se usa al escribir (con máscara, sin futuro) da 3.088, peor que repartir por igual entre doce palabras: .
La red de cada bloque
, con de y de , la misma para todas las posiciones del bloque («aplicada a cada posición por separado y de forma idéntica», sección 3.3 del artículo). El artículo original usaba ReLU; GPT-1 y GPT-2 usan GELU (Hendrycks y Gimpel, 2016), una ReLU suave: , con la distribución normal acumulada.
Normalización de capa
Sobre los números de una lista (Ba, Kiros y Hinton, 2016):
y son los «dos ajustes que también se aprenden» (ganancia y sesgo, parámetros por normalización). El artículo de 2017 normalizaba después de sumar, ; GPT-2 la movió a la entrada de cada parte y añadió una más tras el último bloque. Xiong y colegas (2020) muestran que, con la normalización previa, los gradientes están bien comportados desde el inicio y se puede entrenar sin la fase de calentamiento de la tasa de aprendizaje. En la escena, la lista de «come» al entrar al segundo bloque tiene promedio 1.10 y desviación estándar 0.78.
Codificación de posición
La del artículo de 2017 (sección 3.5), con el lugar e el índice del par de números:
Las longitudes de onda van de a . Los autores probaron también posiciones aprendidas y obtuvieron resultados casi idénticos; GPT-1 aprende las suyas. «La atención sola no sabe el orden» es exacto para la atención sin máscara: si se permutan los tokens, sus salidas se permutan igual. Con máscara causal la cosa es más sutil: Haviv y colegas (2022) muestran que un modelo de lenguaje causal sin codificación de posición aprende una noción implícita de posición, gracias a la propia máscara. Aun así, casi todos los modelos usan alguna. En la escena, el cálculo «sin posición» usa una cabeza real de nuestro modelo sobre los embeddings solos y sin máscara.
Contar parámetros
Con palabras, números por lista, bloques, posiciones aprendidas y una red de :
| Parte | Parámetros | Juguete (, , ) |
|---|---|---|
| Embeddings (y posiciones aprendidas) | 96 (posición con ondas: 0) | |
| Atención | 576 | |
| Red | 1 104 | |
| Normalizaciones | 80 | |
| Total | si es grande | 1 856 |
La aproximación es la de Kaplan y colegas (2020, ecuación 2.1), sin contar embeddings. Con el vocabulario de GPT-2 (50 257) y , la tabla da 125 226 240 para 12 bloques con y 174 604 259 328 para 96 bloques con ; el artículo de GPT-3 (tabla 2.1) lista 125 millones para «GPT-3 Small» y 175.0 mil millones para GPT-3. El reparto por partes de la escena es nuestro cálculo con esta tabla. Para GPT-2 pequeño (contexto 1 024) da 124 439 808, lo mismo que cuenta la biblioteca Hugging Face Transformers (comprobado en train_tiny.py); el artículo de GPT-2 decía 117 millones.
En código
import numpy as np
def softmax(z):
e = np.exp(z - z.max(-1, keepdims=True))
return e / e.sum(-1, keepdims=True)
def causal_attention(Q, K, V):
T, d = Q.shape
scores = Q @ K.T / np.sqrt(d)
scores[np.triu_indices(T, k=1)] = -np.inf # máscara causal: nada de mirar al futuro
w = softmax(scores)
return w, w @ V
def layer_norm(x, g, b, eps=1e-5):
return g * (x - x.mean(-1, keepdims=True)) / np.sqrt(x.var(-1, keepdims=True) + eps) + b
def n_params(d, L, V, ctx, ff=None):
ff = ff or 4 * d
return V*d + ctx*d + L*(4*d*d + 4*d) + L*(2*d*ff + ff + d) + (4*L + 2)*d
rng = np.random.default_rng(0)
Q = K = V = rng.normal(size=(3, 4))
w, out = causal_attention(Q, K, V)
print(np.round(w, 2))
x = rng.normal(2.0, 3.0, size=8)
y = layer_norm(x, np.ones(8), np.zeros(8))
print(round(y.mean(), 3), round(y.std(), 3))
print(n_params(8, 2, 12, 0), n_params(12288, 96, 50257, 2048))
# [[1. 0. 0. ]
# [0.25 0.75 0. ]
# [0.17 0.13 0.7 ]]
# 0.0 1.0
# 1856 174604259328
El modelo de la lección está completo en model.ts y se entrena con train_tiny.py (PyTorch, en CPU, menos de un minuto): ambos viven junto a esta lección, y verify-forward.mts comprueba que el pase en TypeScript coincide con PyTorch (diferencia máxima de 7·10⁻⁶).
Lo que viene
Un modelo con esta arquitectura empieza con parámetros al azar. La lección 23 muestra qué aprende al entrenarlo para predecir la siguiente palabra con texto a escala de internet, y la 24, cuánto cuesta. Cómo se sirve (la caché KV, que evita recalcular los tokens anteriores) llega en la lección 26.
Lente de decisión
Qué significa esta idea si tu trabajo es decidir, no programar.
- Casi todos los modelos de lenguaje de uso general comparten este esqueleto. Decir «usamos un transformer» casi no informa: pregunta por el tamaño (número de bloques y largo de las listas), por cuánto texto puede leer de una vez y por los datos con que se entrenó.
- El tamaño crece con el cuadrado del largo de las listas y con el número de bloques: duplicar el largo cuadruplica los parámetros de cada bloque. Compara los dos números, no solo el total.
- Cada token que el modelo escribe exige un pase por todos los bloques. Las respuestas largas cuestan más tiempo y dinero, y un modelo más profundo tarda más por token.
- Hay modelos que escriben (solo decodificador, como GPT) y modelos que solo leen (solo codificador, como BERT). Para clasificar o buscar documentos no siempre hace falta uno que escriba: puede ser más barato y más fácil de evaluar.
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.
- Vocabulario Lista de todas las piezas (tokens) que un tokenizador puede producir, cada una con su número. Los reales tienen de unas treinta y dos mil a unas doscientas mil; el de juguete de la lección, 656.
- 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.
- Modelo de lenguaje Modelo que, dado un texto (el contexto), da una probabilidad a cada palabra o pieza que puede seguir. Escribe agregando una pieza a la vez.
- Autorregresión Escribir una pieza a la vez usando como entrada lo ya escrito: cada palabra producida pasa a formar parte del contexto de la siguiente.
- Softmax Función que convierte puntajes cualesquiera en probabilidades positivas que suman uno: aplica la exponencial a cada puntaje y divide entre la suma.
- 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.
- 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.
- ReLU Unidad lineal rectificada: función de activación que devuelve cero si la suma es negativa y la propia suma si es positiva, máx(0, z). Una bisagra con una sola esquina.
- No linealidad Propiedad de una función que no es una recta. Es lo que impide que apilar capas colapse en una sola y lo que permite doblar el espacio.
- Pase hacia delante Cálculo de la salida de una red: los números avanzan capa por capa, de la entrada a la salida.
- Conexión residual (atajo) Suma de la entrada de un bloque a su salida: y = x + F(x). Da al gradiente un camino directo hacia atrás y permitió apilar muchas más capas.
- Parámetro Cada uno de los números que un modelo ajusta al entrenarse y en los que guarda lo aprendido.
- 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.
- Sesgo (b) El término que se suma al final del modelo: la predicción cuando la entrada vale cero, es decir, la altura a la que la recta corta el eje vertical. No es el sesgo de los datos o de un modelo injusto, que es otro concepto.
- Función de pérdida Un único número que resume qué tan equivocado está un modelo con sus datos. Entrenar es buscar los parámetros que lo hacen lo más pequeño posible.
Transcripción completa
Fuentes
- Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł., Polosukhin, I. (2017). Attention Is All You Need
- Radford, A., Narasimhan, K., Salimans, T., Sutskever, I. (2018). Improving Language Understanding by Generative Pre-Training (GPT-1)
- Radford, A., Wu, J., Child, R., Luan, D., Amodei, D., Sutskever, I. (2019). Language Models are Unsupervised Multitask Learners (GPT-2)
- Brown, T. B., Mann, B., Ryder, N., Subbiah, M., et al. (2020). Language Models are Few-Shot Learners (GPT-3)
- Kaplan, J., McCandlish, S., Henighan, T., Brown, T. B., et al. (2020). Scaling Laws for Neural Language Models
- Ba, J. L., Kiros, J. R., Hinton, G. E. (2016). Layer Normalization
- He, K., Zhang, X., Ren, S., Sun, J. (2015). Deep Residual Learning for Image Recognition
- Xiong, R., Yang, Y., He, D., Zheng, K., et al. (2020). On Layer Normalization in the Transformer Architecture
- Hendrycks, D., Gimpel, K. (2016). Gaussian Error Linear Units (GELUs)
- Press, O., Wolf, L. (2017). Using the Output Embedding to Improve Language Models
- Haviv, A., Ram, O., Press, O., Izsak, P., Levy, O. (2022). Transformer Language Models without Positional Encodings Still Learn Positional Information
- Touvron, H., Martin, L., Stone, K., et al. (2023). Llama 2: Open Foundation and Fine-Tuned Chat Models
- Devlin, J., Chang, M.-W., Lee, K., Toutanova, K. (2018). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
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