Descrito, el Transformer ya está entero. La lección anterior, sobre el encoder, el decoder y las
máscaras, cerró la última operación que quedaba suelta, y con ella el modelo sabe leer una frase,
escribir otra y no mirar lo que todavía no ha escrito. Construido no está. Lo que hay escrito son
letras —dk, dff, h, N—, y un programa no reserva memoria para una letra: hasta
que cada una no valga un número, no hay ni una matriz que crear.
Los números del artículo son cinco, y ponerlos encima del dibujo es lo que cierra el bloque. Cinco y
no quince: fijados ésos, todas las formas del modelo quedan determinadas —incluidas un par que
parecen libres y no lo son—, y de ellos sale el recuento entero de parámetros y, con él, el reparto,
que no está donde el dibujo sugiere. Antes hay que cerrar la caja que ninguna lección construyó, la
que corona la columna del decoder, y su respuesta viene de mucho más atrás que el resto del bloque:
es la tabla de embeddings de la lección sobre las representaciones densasBlock 1 · Lesson 6 · In SpanishRepresentaciones densas: la idea centralDar a cada entrada del vocabulario unas pocas coordenadas reales, todas compartidas y ninguna reservada, rompe la equidistancia del one-hot y deja la tabla de la representación en una matriz que sí cabe. Los 15 millones de números que la llenan no los escribe nadie a mano: la hipótesis distribucional dice de dónde salen., leída
al revés.
Pincha cualquiera de las quince cajas: el panel dice qué hace y en qué lección se construyó. Sólo una nombra a ésta, y es la de arriba del todo.
La figura del artículo está en inglés y este bloque la ha ido construyendo en español, así que lo
primero es la correspondencia, rótulo por rótulo:
Rótulo en la figura
Qué caja es
Dónde se construyó
Input Embedding, Output Embedding
la tabla E, la misma en las dos
la lección sobre las representaciones densasBlock 1 · Lesson 6 · In SpanishRepresentaciones densas: la idea centralDar a cada entrada del vocabulario unas pocas coordenadas reales, todas compartidas y ninguna reservada, rompe la equidistancia del one-hot y deja la tabla de la representación en una matriz que sí cabe. Los 15 millones de números que la llenan no los escribe nadie a mano: la hipótesis distribucional dice de dónde salen.
Outputs (shifted right)
lo ya escrito, corrido una posición
la lección anterior, sobre el decoder y su máscara
Positional Encoding
PE, sumada una sola vez abajo del todo
la lección sobre la codificación posicionalBlock 5 · Lesson 5 · In SpanishCada posición, un puñado de relojesLa capa de atención está terminada y sigue leyendo la frase como un montón de vectores sin orden, así que lo que hay que arreglar es la entrada: cada fila tiene que llegar sabiendo dónde estaba. Meter el número de la posición rompe la escala, dividirlo entre la longitud de la frase hace que la misma coordenada signifique cosas distintas en textos distintos, y aprender un vector por posición deja la 7 y la 8 sin relación ninguna. Los senos y cosenos del artículo resuelven las tres: acotados por construcción, con una longitud de onda por pareja de coordenadas, y con una propiedad que se demuestra en tres líneas —moverse k posiciones es girar un ángulo fijo dentro de cada pareja, con la misma matriz en toda la frase, y el producto escalar entre dos posiciones sólo depende de la distancia que las separa.
Multi-Head Attention (izquierda)
la auto-atención del encoder
auto-atenciónBlock 5 · Lesson 2 · In SpanishAuto-atención: la secuencia se mira a sí mismaSin decoder no hay quien fabrique las consultas, y la salida es que las fabrique la propia frase. Pero usar los vectores tal cual no vale: con las tres listas iguales, lo que más se parece a un vector es él mismo, la diagonal gana todas las filas y la capa devuelve lo que le entró, sin un solo parámetro que entrenar. Lo que arregla eso son tres proyecciones de la misma X —una para preguntar, otra para ser preguntado, otra para mezclarse—, y con ellas la rejilla se vuelve cuadrada, deja de ser simétrica y cuesta un número de pesos donde la longitud de la frase no aparece., producto interno escaladoBlock 5 · Lesson 3 · In SpanishLa raíz que faltaba en la atenciónDe la fórmula de la atención queda un solo símbolo sin justificar, y no se justifica midiendo: se cuenta. Una puntuación es una suma de d_k términos, y lo que crece al añadir sumandos no es su tamaño sino cuánto se aleja del cero la suma, que va con la raíz de d_k. Lo que ese tamaño le hace al softmax es lo que el curso ya vio dos veces con otra ropa: la fila se cierra sobre una posición, las dos derivadas del softmax se apagan a la vez y las dos únicas matrices que hay antes de las puntuaciones dejan de recibir gradiente. Dividir entre la raíz devuelve las puntuaciones a una escala que no menciona la anchura del modelo, y con ellas el reparto y el gradiente. y cabezasBlock 5 · Lesson 4 · In SpanishVarias cabezas, varios repartosUna posición tiene una fila y en esa fila cabe una sola manera de mirar la frase. La atención multi-head monta h atenciones en paralelo sobre la misma X, cada una con sus tres proyecciones y su propio mapa, y las junta concatenando y proyectando. Lo que cambia no son las puntuaciones sino dónde se normaliza: cada grupo de coordenadas con su propio softmax, en vez de todas sumadas antes de uno solo, que es lo que deja a una regla tapar a otra sin dejar rastro. Y de repartir la anchura, d_k = d_model/h, sale que el coste no depende de h: los mismos parámetros y las mismas multiplicaciones con una cabeza que con dieciséis.
Masked Multi-Head Attention
la misma, con M sumada a las puntuaciones
la lección anterior, sobre las máscaras
Multi-Head Attention (centro de la derecha)
la atención encoder-decoder
la lección anterior, sobre la subcapa que junta las dos columnas
Add & Norm, cinco veces
LayerNorm(X+Sublayer(X))
la lección sobre los residuales y el layer normBlock 5 · Lesson 6 · In SpanishApilar sin perder lo de abajoLa capa de atención ya está completa, y el artículo pone seis una encima de otra. Componer seis funciones multiplica seis derivadas, que es exactamente la cuenta con la que se estrelló el bloque 3, así que apilar no es repetir: hace falta algo alrededor de cada subcapa. Son dos cosas y las dos caben en una línea. La suma —la subcapa devuelve lo que ha calculado más lo que le entró— abre un camino de la salida a la entrada que no atraviesa ningún peso, y de paso obliga a que d_model sea un solo número en todo el modelo, que es para lo que estaba la proyección de salida de multi-head. El layer norm centra cada fila con sus propias coordenadas, sin mirar a las demás posiciones ni a las demás frases del batch. Y entre las dos subcapas del bloque está el perceptrón por posiciones, que parece fontanería y lleva el doble de parámetros que la atención.
Feed Forward, dos veces
el perceptrón por posiciones
la lección sobre los residuales y el layer normBlock 5 · Lesson 6 · In SpanishApilar sin perder lo de abajoLa capa de atención ya está completa, y el artículo pone seis una encima de otra. Componer seis funciones multiplica seis derivadas, que es exactamente la cuenta con la que se estrelló el bloque 3, así que apilar no es repetir: hace falta algo alrededor de cada subcapa. Son dos cosas y las dos caben en una línea. La suma —la subcapa devuelve lo que ha calculado más lo que le entró— abre un camino de la salida a la entrada que no atraviesa ningún peso, y de paso obliga a que d_model sea un solo número en todo el modelo, que es para lo que estaba la proyección de salida de multi-head. El layer norm centra cada fila con sus propias coordenadas, sin mirar a las demás posiciones ni a las demás frases del batch. Y entre las dos subcapas del bloque está el perceptrón por posiciones, que parece fontanería y lleva el doble de parámetros que la atención.
Nx
N bloques apilados
esta lección
Linear, Softmax
la proyección al vocabulario
esta lección
La caja de arriba lee la tabla del bloque 1 al revés
De lo que sale del último bloque del decoder, la fila t es un vector de dmodel
coordenadas, xtdec, y lo que hace falta en esa posición es una probabilidad por
cada entrada del vocabulario. El artículo dibuja dos cajas para ese salto: una matriz que lleva de
dmodel a ∣V∣ coordenadas y el reparto de siempre. Esa matriz podría ser
suya, y no lo es:
y^t=softmax(Extdec)∈R∣V∣,
donde E∈R∣V∣×dmodel es la tabla de
embeddings del bloque 1, la misma que abajo del todo cambia cada token por su vector. La
coordenada que le toca a la entrada w dentro del softmax es
ew⊤xtdec: el producto escalar entre la fila de esa entrada y
lo que el decoder lleva calculado. La entrada más probable es la que más apunta en la dirección que
la posición pide.
Es la tabla leída en la otra dirección. Abajo se entra con una entrada y se sale con su vector;
aquí se entra con un vector y se sale con una puntuación por entrada. Las Ty posiciones salen a
la vez del mismo producto, como todo en este bloque:
XdecE⊤∈RTy×∣V∣,
con el softmax por filas. Una fila por posición escrita, una columna por entrada del vocabulario,
y ni un parámetro nuevo en toda la caja.
La misma tabla en tres sitios
El artículo va más lejos que eso y usa esa matriz tres veces: en el embedding de entrada, en
el de salida y en la proyección al vocabulario. Eso exige un vocabulario común a los dos idiomas, y
lo tiene: sus 37000 entradas salen de un BPE (byte-pair encoding) entrenado sobre los dos
textos a la vez, la técnica de la lección sobre la tokenizaciónBlock 1 · Lesson 2 · In SpanishTokenización: palabras, caracteres, subpalabrasAntes de decidir qué vector le corresponde a una unidad hay que decidir cuál es la unidad. Esa elección fija el tamaño del vocabulario, la longitud de las secuencias y qué significa que una palabra sea nueva.. Una tabla de
37000×512 son 18944000 parámetros, y lo que se compra compartiéndola es no pagarla
tres veces.
Queda un factor que la lección sobre la codificación posicionalBlock 5 · Lesson 5 · In SpanishCada posición, un puñado de relojesLa capa de atención está terminada y sigue leyendo la frase como un montón de vectores sin orden, así que lo que hay que arreglar es la entrada: cada fila tiene que llegar sabiendo dónde estaba. Meter el número de la posición rompe la escala, dividirlo entre la longitud de la frase hace que la misma coordenada signifique cosas distintas en textos distintos, y aprender un vector por posición deja la 7 y la 8 sin relación ninguna. Los senos y cosenos del artículo resuelven las tres: acotados por construcción, con una longitud de onda por pareja de coordenadas, y con una propiedad que se demuestra en tres líneas —moverse k posiciones es girar un ángulo fijo dentro de cada pareja, con la misma matriz en toda la frase, y el producto escalar entre dos posiciones sólo depende de la distancia que las separa. dejó fuera. Allí
la entrada de la primera capa se escribió xt=ewt+PEt; el
artículo multiplica el primer sumando:
xt=dmodelewt+PEt.
Con los números delante se ve para qué. Todas las filas de PE miden lo mismo,
256=16 —es la cuenta PEpos⊤PEpos=dmodel/2 de aquella lección—, mientras que una fila de E recién inicializada,
con coordenadas pequeñas alrededor de cero, mide alrededor de 1. Sumados así, el contenido queda
debajo de la posición; multiplicar por 512≈22.6 los pone en el mismo orden de
magnitud. El artículo escribe la multiplicación y no la justifica: ésta es la razón que se le suele
dar, no una que él dé.
Cinco números fijan todas las formas
La tabla 3 del artículo tiene una fila por cada modelo que entrenaron. La primera, la que llaman
base, es la que ha ido apareciendo suelta a lo largo del bloque:
Número
Valor
Qué fija
N
6
cuántos bloques se apilan en cada columna
dmodel
512
la anchura que entra y sale de toda subcapa
h
8
cuántas cabezas tiene cada capa de atención
dff
2048
la anchura interior del perceptrón por posiciones
∣V∣
37000
cuántas filas tiene E
Todo lo demás sale de esos cinco. El reparto de la lección sobre la atención
multi-headBlock 5 · Lesson 4 · In SpanishVarias cabezas, varios repartosUna posición tiene una fila y en esa fila cabe una sola manera de mirar la frase. La atención multi-head monta h atenciones en paralelo sobre la misma X, cada una con sus tres proyecciones y su propio mapa, y las junta concatenando y proyectando. Lo que cambia no son las puntuaciones sino dónde se normaliza: cada grupo de coordenadas con su propio softmax, en vez de todas sumadas antes de uno solo, que es lo que deja a una regla tapar a otra sin dejar rastro. Y de repartir la anchura, d_k = d_model/h, sale que el coste no depende de h: los mismos parámetros y las mismas multiplicaciones con una cabeza que con dieciséis. da dk=dv=dmodel/h=64, y con él WiQ, WiK y
WiV miden 512×64 y WO mide
(h⋅dv)×dmodel=512×512; el perceptrón por posiciones sube a
2048 y vuelve a bajar; cada normalización aporta dos vectores de 512. Lo que no está en la
lista tampoco está en ninguna forma: ni T, ni el tamaño del batch. Esa tabla tiene además dos
columnas que esta lección no toca, dropout y label smoothing: son del entrenamiento y no de la
arquitectura, y quedan fuera del curso.
Un tercio del modelo es una tabla de búsqueda
Un bloque del encoder pesa 3150336 parámetros —la cuenta de la lección sobre
los residuales y el layer normBlock 5 · Lesson 6 · In SpanishApilar sin perder lo de abajoLa capa de atención ya está completa, y el artículo pone seis una encima de otra. Componer seis funciones multiplica seis derivadas, que es exactamente la cuenta con la que se estrelló el bloque 3, así que apilar no es repetir: hace falta algo alrededor de cada subcapa. Son dos cosas y las dos caben en una línea. La suma —la subcapa devuelve lo que ha calculado más lo que le entró— abre un camino de la salida a la entrada que no atraviesa ningún peso, y de paso obliga a que d_model sea un solo número en todo el modelo, que es para lo que estaba la proyección de salida de multi-head. El layer norm centra cada fila con sus propias coordenadas, sin mirar a las demás posiciones ni a las demás frases del batch. Y entre las dos subcapas del bloque está el perceptrón por posiciones, que parece fontanería y lleva el doble de parámetros que la atención., con sus sesgos y sus vectores de normalización dentro—. Uno del
decoder lleva exactamente una atención y una normalización más:
3150336+1048576+1024=4199936.
El modelo entero son seis de cada, más la tabla que las dos columnas comparten:
6⋅3150336+6⋅4199936+37000⋅512=63045632.
Ahí está el reparto que el dibujo esconde. Son 18.9 millones de encoder, 25.2 de decoder y
18.9 de tabla: un 30, un 40 y un 30 por ciento. Lo que más pesa de una sola pieza no es
ninguna de las quince cajas, es la tabla de búsqueda, que ella sola supera a las seis capas del
encoder juntas —18944000 frente a 18902016—. Y de ahí que el artículo la comparta: las
dos copias que se ahorra suman 37888000 parámetros, casi tanto como las doce capas.
Esa cuenta es una reconstrucción a partir de la figura, no la contabilidad del artículo, y conviene
decir en qué se separan. El artículo declara 65 millones y aquí salen 63.0. Los dos que faltan
caben enteros en dos detalles que la figura no muestra: el tamaño exacto del vocabulario —con
41000 entradas la cifra cuadraría— y dónde pone cada implementación sus sesgos. La misma receta
aplicada a la otra fila de la tabla 3, la que llaman big (dmodel=1024, h=16,
dff=4096), da 214.2 millones frente a los 213 declarados.
El recuento en una función
Toda la sección anterior cabe en ocho líneas de aritmética con números enteros. Mira tres cosas: los
tres porcentajes, la diferencia entre la tabla y el encoder entero, y qué le pasa al total si cada
caja tuviera su propia tabla.
def parametros(N, d_model, h, d_ff, V): d_k = d_v = d_model // h # no se eligen: salen de h atencion = 3 * h * d_model * d_k + h * d_v * d_model # las tres por cabeza, y W^O ffn = 2 * d_model * d_ff + d_ff + d_model # dos capas y sus dos sesgos norm = 2 * d_model # gamma y beta enc = N * (atencion + ffn + 2 * norm) # dos subcapas, dos normalizaciones dec = N * (2 * atencion + ffn + 3 * norm) # tres y tres return enc, dec, V * d_model # la tabla, una para tres cajas
enc, dec, tabla = parametros(N=6, d_model=512, h=8, d_ff=2048, V=37000) total = enc + dec + tabla
for nombre, valor in (("encoder", enc), ("decoder", dec), ("tabla E", tabla)): print(f"{nombre:>8} {valor:>12,} {100 * valor / total:5.1f} %") print(f"{'total':>8} {total:>12,}")
print("\nla tabla menos el encoder entero:", tabla - enc) print("sin compartirla, dos copias mas :", total + 2 * tabla)
grande = parametros(N=6, d_model=1024, h=16, d_ff=4096, V=37000) print("\nla fila big de la tabla 3 :", sum(grande))
The first run downloads the Python interpreter (~15 MB). After that it stays in the browser cache and is reused across every lesson.
Los tres porcentajes salen 30.0, 40.0 y 30.0, y el decoder pesa más que el encoder por lo
único en lo que se diferencian: una subcapa de atención más, seis veces. La tabla le saca al encoder
41984 parámetros, que sobre dieciocho millones es empatar. Y sin compartirla el modelo se iría a
100933632, de 63 millones a 101 por una decisión que no cambia ni una operación del
dibujo.
La última línea cambia los cinco argumentos por los de la fila big y da 214171648.
Lo que no vas a poder
cambiar es la longitud del texto, porque T no aparece en ninguna línea de la función: no es que se
haya quedado fuera de la cuenta, es que no hay ninguna matriz cuya forma dependa de ella.
Comprueba tu intuición
Cinco preguntas: qué forma no fijan los cinco números, qué costaría no compartir la tabla, qué vas a
encontrarte al abrir la figura, si un texto más largo pide más parámetros y qué sale por arriba del
decoder.
Con los cinco números del artículo puestos —N, dmodel, h, dff y ∣V∣—, ¿cuál de estas formas sigue sin quedar determinada?
El artículo usa la misma matriz E en los tres sitios que la necesitan. Si cada uno tuviera la suya, ¿cuántos parámetros más tendría el modelo base?
parámetros
A margin of ±0 is accepted.
Abres la figura 1 del artículo. Marca lo que vas a encontrarte.
Select every correct option. This is graded all-or-nothing: there is no partial credit.
Pasas de traducir frases de 50 tokens a traducir textos de 1000. El modelo base necesita más parámetros.
Ésta es la caja de arriba del todo, con la tabla compartida y cuatro posiciones escritas. ¿Qué imprime?
import numpy as np# E es la tabla compartida; X_dec sale del ultimo bloqueV, d_model, T_y = 37000, 512, 4rng = np.random.default_rng(0)E = rng.normal(size=(V, d_model))X_dec = rng.normal(size=(T_y, d_model))O = X_dec @ E.TP = np.exp(O - O.max(axis=1, keepdims=True))P /= P.sum(axis=1, keepdims=True)print(P.shape, np.allclose(P.sum(axis=1), 1.0))
Ya no queda nada que describir. Las quince cajas tienen su operación, sus formas y sus números, y
eso es justo lo que hace falta para escribir el modelo entero y ver qué contesta. Lo que no cabe es
el tamaño: sesenta y tres millones de parámetros no se mueven dentro de un navegador, así que lo que
se construye es la arquitectura con anchuras de juguete —las mismas fórmulas, dos capas en lugar de
seis, dos cabezas en lugar de ocho— y una frase corta que se pueda seguir a ojo.
Eso es la lección siguiente, el proyecto: un Transformer desde cero. Casi todas las piezas
están escritas ya, cada una en el desafío de su lección —el softmax por filas, la atención con su
máscara, el layer norm, el perceptrón por posiciones, la codificación posicional—, y lo que queda
es ensamblarlas y hacer una pasada hacia delante de principio a fin: de una frase de tokens a una
probabilidad por entrada del vocabulario, con los mapas de atención a la vista por el camino.
Entrenar de verdad pide una máquina que un navegador no tiene, y eso tiene su sitio más adelante en
el bloque.
Further reading2 sources · 2 papers
Where this lesson comes from, and where to go next. None of it is needed to carry on with the course.
paper·Vaswani, Shazeer, Parmar y otros, 2017·arXiv:1706.03762EN
Su §3.4 comparte la tabla E entre las dos entradas y la salida y la multiplica por √d_model; su tabla 3, fila «base», da tus cinco números. Los 65 millones los reconstruyes tú, y no cuadran al detalle con lo que declara.
El Transformer lo cita para leer E al revés en la salida. Aquí está el porqué: atar la matriz de entrada con la de salida baja la perplejidad y reduce el modelo a menos de la mitad. Es sobre LSTM; la cuenta de parámetros es tuya.