Attention e o bloque transformer, derivados dunha media
Parte do resumo máis barato dun context — a media — mide onde falla e deixa que a fórmula de attention saia da reparación.
Nesta páxina
Chegas aquí cun tokenizer do Capítulo 7, unha táboa de embedding do Capítulo 8 e o obxectivo que vai con eles: dados os tokens ata agora, poñer unha probabilidade no seguinte.
O que falta é o medio. Para predicir o token o modelo precisa un vector que resuma todo o anterior, e nada do que construíches produce un. O embedding do token non o é: iso é un modelo de bigramas, e non pode saber que a frase empezou cunha pregunta. Unha concatenación de todos os embeddings anteriores tampouco o é: o seu número cambia en cada paso, e unha matriz de pesos fixa non pode aceptar unha entrada de lonxitude variable.
Así que: un vector de tamaño fixo, que resume un número variable de vectores. Ese é todo o problema, e attention é o que obtés ao resolvelo da maneira máis preguiceira posible e logo reparar as dúas cousas que rompen.
A resposta que tiña o campo, e por que non a imos construír
Ligazón á sección: A resposta que tiña o campo, e por que non a imos construírDe 1997 ata arredor de 2017 o resumo era un estado recorrente: manter un vector e actualizalo en cada token, . Tamaño fixo, entrada variable, exactamente a forma axeitada.
Fallaba de tres maneiras, e a arquitectura deste capítulo responde ás tres. Facer backpropagation a través de pasos multiplica xacobianas, polo que o gradient desaparece ou estoupa: a doenza que o Capítulo 5 mediu dentro dun único nodo . A LSTM1 foi deseñada exactamente contra iso e levou o rango útil de decenas de pasos a centos, sen cambiar o feito de que a información do token 5 chega ao token 500 só se sobrevive a 495 actualizacións secuenciais. Toda a fonte tiña que caber nun vector: na tradución sequence-to-sequence2, un codificador comprime a entrada no seu estado final. Bahdanau, Cho e Bengio puxéronlle nome a ese pescozo de botella e arranxárono en 2014, tres anos antes do transformer, deixando que o decodificador tomase unha suma ponderada de todos os estados do codificador con pesos calculados por el mesmo.3 Todo o que segue é esa idea, aplicada por unha secuencia a si mesma, coa recorrencia eliminada. E a actualización é secuencial por construción: precisa , e unha GPU con dez mil núcleos non pode facer nada con iso. A arquitectura que gañou non é obviamente máis intelixente; é aquela cuxo paso caro é unha multiplicación de matrices.
O outro sesgo indutivo clásico, a convolución — deslizar un filtro pequeno sobre toda a entrada, de xeito que unha característica detectada en calquera lugar se detecta en todas partes — tampouco se constrúe aquí; é case exactamente o correcto para imaxes e déixase para un curso de visión. Nin a recorrencia nin a convolución volven aparecer despois desta páxina, por iso ningunha recibe un capítulo: o Capítulo 1 prometeu que as omisións se declararían en vez de deixalas en silencio.
O resumo máis barato que existe
Ligazón á sección: O resumo máis barato que existeA función máis obvia dun número variable de vectores que devolve un vector é a media:
Calquera número de entradas, tamaño de saída fixo, diferenciable, gratis. Unha táboa de embedding máis esta media máis unha capa lineal ao vocabulario é un modelo de linguaxe completo en quince liñas. Tamén é terrible, e como é terrible é toda a derivación.
O corpus de abaixo é un megabyte de Shakespeare, 1.115.394 caracteres, a través dun tokenizer BPE a nivel de byte do tipo construído no Capítulo 7 cun vocabulario de 1024: 459.760 tokens a 2,43 caracteres cada un, dividido 90/10. Todos os modelos teñen ancho 128, ven 128 tokens e adéstranse durante 3000 pasos de AdamW a cun batch de 64. A perplexity mídese na partición reservada.4
| modelo | parámetros | perplexity de validación |
|---|---|---|
| só o token actual, sen context ningún | 263,168 | 59.71 |
| máis a media uniforme de todo o anterior | 263,168 | 248.07 |
| máis embeddings de posición aprendidos | 279,552 | 245.93 |
| media uniforme engadida ao token en vez de substituílo | 263,168 | 60.45 |
Le a segunda fila dúas veces. Mediar o context non axuda un pouco; fai que o modelo sexa catro veces peor que ignorar o context por completo. Hai dúas razóns, ambas demostrables máis que empíricas.
A media non pode ver a orde. A suma conmuta, así que barallar a xanela deixa o resumo sen cambios; non aproximadamente:
A = torch.tril(torch.ones(T, T))
A = A / A.sum(1, keepdim=True) # rows of the averaging matrix
y = x[torch.randperm(T)] # the same tokens, shuffled
print((A[-1] @ x - A[-1] @ y).abs().max().item())2.9802322387695312e-08Ruído de coma flotante nunha suma reordenada: os dous resumos son o mesmo vector. Un modelo cuxa única vista do context é unha media non pode distinguir o can mordeu o home de o home mordeu o can. A terceira fila demostra que isto non se arranxa engadindo posicións ás entradas: un embedding de posición aprendido en cada token antes de facer a media comprou 2,14 puntos de 188. As posicións entran na suma, e a suma esquéceas.
E a media afoga o presente. Na posición 100, o token actual é unha centésima parte do resumo. Iso ten unha reparación barata que xa tes: conservar o token e engadirlle o resumo: unha conexión residual, do Capítulo 6, e a cuarta fila mostra o que fai. Coa dilución reparada, a media uniforme non achega absolutamente nada: 60.45 fronte a unha liña base de 59.71. Todos os tokens están aí, ponderados por igual, e a ponderación igual é o mesmo que ningunha información.
O problema non é facer medias. Son os pesos.
A media é unha multiplicación de matrices, e a máscara é un softmax
Ligazón á sección: A media é unha multiplicación de matrices, e a máscara é un softmaxMediar sobre un prefixo crecente parece un bucle. É unha multiplicación por unha matriz triangular inferior cuxas filas suman un e tamén, exactamente, un softmax:
loop = torch.stack([x[:t + 1].mean(0) for t in range(T)]) # the obvious version
A = torch.tril(torch.ones(T, T))
A = A / A.sum(1, keepdim=True)
mat = A @ x # the same thing
S = torch.zeros(T, T).masked_fill(torch.tril(torch.ones(T, T)) == 0, float("-inf"))
soft = F.softmax(S, dim=-1) @ x # and the same thing againloop vs matmul max |diff| = 5.960464477539063e-08
loop vs softmax max |diff| = 5.960464477539063e-08
the averaging matrix A (rows sum to 1, upper triangle is zero):
1.000 0.000 0.000 0.000 0.000 0.000
0.500 0.500 0.000 0.000 0.000 0.000
0.333 0.333 0.333 0.000 0.000 0.000
0.250 0.250 0.250 0.250 0.000 0.000
0.200 0.200 0.200 0.200 0.200 0.000
0.167 0.167 0.167 0.167 0.167 0.167Tres compoñentes con nome dun transformer están agora na pantalla. O triángulo é a máscara causal, obrigada polo obxectivo: se a posición puidese ver a posición , a resposta estaría na entrada: a fuga que o Capítulo 6 che mandou auditar, agás dentro da arquitectura. O softmax é como se implementa a máscara: poñer as entradas prohibidas a mándaas exactamente a cero e normaliza o que queda, así que enmascarar e normalizar son unha soa operación. (Usa , non -1e9: é o valor que a máscara significa, sobrevive a unha conversión a float16 como , e afórrache decidir se a constante que escolliches é o bastante grande para o rango no que resulta que estás, que é a caixa de coma flotante do Capítulo 2 facendo unha pregunta que non tes que responder.) E as puntuacións son o parámetro libre. A media uniforme é o que obtés cando cada puntuación permitida é o mesmo número; pon aí calquera número e o softmax convérteo en pesos válidos.
O resto deste capítulo é unha pregunta: de onde saen eses números?
Query, key, value
Ligazón á sección: Query, key, valueNon poden ser parámetros simples. Unha matriz aprendida sería idéntica para cada frase: podería codificar «mira catro tokens atrás», pero nunca «mira o substantivo ao que se refire este pronome». O peso que liga a posición coa posición debe depender do que hai en ambas posicións, porque a relevancia é unha relación, non unha propiedade: a palabra it non é intrinsecamente relevante, é relevante para algo.
A función máis barata de dous vectores que devolve un número é o produto escalar do Capítulo 1. Puntúa a posición para a posición como e o mecanismo funciona, mal, de dúas maneiras que obrigan todo o demais. O produto escalar dun vector consigo mesmo é a súa norma ao cadrado, así que cada token atendería sobre todo a si mesmo. E a relación sería simétrica: se it atende con forza a animal, entón animal atende con forza a it, o que é falso na linguaxe, onde un adxectivo precisa o seu substantivo moito máis do que o substantivo precisa o adxectivo.
Así que dálle a cada token dous papeis, como dúas aplicacións lineais aprendidas del: o que esta posición está buscando, , a query; e o que ofrece para ser atopada por, , a key. Puntúa e a simetría desaparece, porque : un token pode anunciar unha cousa e buscar outra.
Aínda hai unha cousa mal. A suma ponderada facíase sobre os mesmos, o que obriga a que o que se copia sexa o que se emparella. Emparellar quere as características que identifican un token; copiar quere as características útiles máis abaixo. Así que aprende unha terceira aplicación, , o value, e suma iso.
A fórmula é agora contabilidade:
con como máscara causal, cero na diagonal e por baixo dela e por riba. En código son trinta liñas, vinte delas formas:
class Head(nn.Module):
"""One head of causal self-attention."""
def __init__(self, d_model, d_head, block):
super().__init__()
self.q = nn.Linear(d_model, d_head, bias=False)
self.k = nn.Linear(d_model, d_head, bias=False)
self.v = nn.Linear(d_model, d_head, bias=False)
self.d_head = d_head
self.register_buffer("mask", torch.tril(torch.ones(block, block)).bool())
def forward(self, x):
T = x.shape[1]
q, k, v = self.q(x), self.k(x), self.v(x)
s = q @ k.transpose(-2, -1) / math.sqrt(self.d_head)
s = s.masked_fill(~self.mask[:T, :T], float("-inf"))
w = F.softmax(s, dim=-1)
return w @ v Puntuar, enmascarar, normalizar, mesturar. Todo o demais é unha proxección.
A división pola raíz cadrada, e de que protexe
Ligazón á sección: A división pola raíz cadrada, e de que protexeCase todas as explicacións de din «para evitar que o softmax se sature», o cal é certo e non explica nada. O argumento son dúas liñas da varianza do Capítulo 2. Se as entradas de e son independentes con media cero e varianza un, cada produto ten varianza un, e as varianzas de cousas independentes súmanse:
Así que as puntuacións teñen desviación estándar . Medido sobre vinte mil pares aleatorios:
d Var(q.k) std sqrt(d)
4 3.975 1.994 2.000
16 16.071 4.009 4.000
64 64.249 8.016 8.000
256 253.065 15.908 16.000
1024 1015.562 31.868 32.000Por que importa: o softmax é sensible á escala dun xeito que unha capa lineal non o é. Duplicar a entrada dunha capa lineal duplica a súa saída; multiplicar as puntuacións por dez antes dun softmax converte unha mestura suave nunha escolla dura. Unha fila de 64 puntuacións, con e sen a división:
| maior peso, sen dividir | entropía | tokens efectivos | maior peso, dividido | entropía | tokens efectivos | |
|---|---|---|---|---|---|---|
| 4 | 0.205 | 2.944 | 19.0 | 0.081 | 3.758 | 42.9 |
| 16 | 0.438 | 1.692 | 5.4 | 0.075 | 3.849 | 46.9 |
| 64 | 0.489 | 0.874 | 2.4 | 0.085 | 3.673 | 39.4 |
| 256 | 0.9999 | 0.0007 | 1.0 | 0.143 | 3.547 | 34.7 |
| 1024 | 1.0000 | 0.0000 | 1.0 | 0.132 | 3.644 | 38.3 |
«Tokens efectivos» é a exponencial da entropía: sobre cantas posicións fai media realmente a fila. Sen dividir, en , unha head acabada de inicializar atende exactamente a un token de 64, escollido só pola tirada aleatoria.
Iso é malo cara adiante e peor cara atrás, nunha forma que o Capítulo 5 xa mediu nun . Un softmax comprometido cunha entrada case non ten derivada: a diagonal da súa xacobiana é , cero nos dous extremos. Sobre dúas mil filas aleatorias:
| sen dividir | dividido | filas saturadas (maior peso por riba de 0.99) | |
|---|---|---|---|
| 4 | 0.8427 | 0.9568 | 0.2 % → 0.0 % |
| 64 | 0.2940 | 0.9609 | 17.9 % → 0.0 % |
| 256 | 0.1406 | 0.9609 | 49.1 % → 0.0 % |
| 1024 | 0.0681 | 0.9611 | 70.4 % → 0.0 % |
En , sete filas de cada dez están conxeladas antes de que empece o adestramento, e unha head que empeza conxelada non pode aprender a que mirar. Dividido, a cantidade mantense plana en 0.96 en todos os anchos e nada se satura.
Agora a parte que ninguén publica: cambia a perplexity final? Elimina a división e adestra, en catro anchos de head:
| ancho da head | sen dividir | dividido por | dividido por |
|---|---|---|---|
| catro heads, | 37.29 | 38.07 | 37.89 |
| unha head, | 48.51 | 46.10 | 45.99 |
| unha head, | 65.37 | 47.53 | — |
| unha head, | 67.06 | 49.15 | — |
| unha head, | 76.69 | 59.17 | — |
As dúas primeiras filas veñen do orzamento de 3000 pasos de arriba; as tres últimas son unha execución máis curta — 1500 pasos, batch de 32, unha head, sen normalización antes das proxeccións — coas dúas variantes baixo configuración idéntica.
En a división non vale nada e a execución sen ela vai lixeiramente por diante. Iso non é unha licenza para quitala, porque en 256 vale 18 puntos de perplexity e en 1024 vale 17. O mecanismo vese nas propias puntuacións:
| std da puntuación na inicialización | despois de 1500 pasos, sen dividir | despois de 1500 pasos, dividido | filas saturadas, sen dividir | dividido | |
|---|---|---|---|---|---|
| 256 | 10.49 | 121.67 | 2.13 | 91.9 % | 0.8 % |
| 512 | 15.13 | 836.85 | 2.66 | 98.7 % | 1.3 % |
| 1024 | 21.15 | 5147.46 | 3.44 | 99.9 % | 16.5 % |
A head sen dividir non se recupera. Escapa: a desviación estándar das súas puntuacións pasa de 21 na inicialización a 5147, a entropía de attention cae a cero, e o 99,9 % das filas poñen máis de 0.99 do seu peso nun único token. Unha vez que unha head é un selector duro, o seu gradient é case cero e nada a trae de volta, así que o colapso é estable. A head dividida queda cunha desviación estándar de puntuación de 3.44 despois do mesmo adestramento, que é unha mestura suave que aínda se pode cambiar.
Vaswani et al. din exactamente isto e nada máis: sospeitan que os produtos «medran moito en magnitude para valores grandes de » e dividen.5 A palabra grande soporta peso, e as táboas din onde comeza o grande: nada en 32, todo en 256.
Máis dunha opinión, e os dous terzos dos que ninguén fala
Ligazón á sección: Máis dunha opinión, e os dous terzos dos que ninguén falaUnha head é unha fila de softmax por posición, así que mantén unha resposta á pregunta «que é relevante aquí». Predicir a palabra despois de the en the animal that crossed the wet street precisa o oco sintáctico, o suxeito e o token anterior á vez, e unha distribución de probabilidade non pode estar concentrada en tres lugares. Así que executa varias heads en paralelo, cada unha de ancho , concatena e mestura cunha matriz máis : particionaches o ancho, non o aumentaches.
Attention tamén fai exactamente unha cousa: move información entre posicións. Todas as operacións do código anterior son lineais ao longo do eixe de características, e o Capítulo 5 demostrou o que é unha pila de aplicacións lineais. Así que cada bloque tamén leva un pequeno MLP aplicado a cada posición independentemente, expandindo o ancho por catro e volvendo, cun GELU no medio. Paga a pena memorizar a división do traballo: attention mestura entre posicións, a rede feed-forward calcula dentro dunha posición.
A escaleira completa, cada fila engadindo unha peza á fila superior:
| modelo | parámetros | perplexity de validación |
|---|---|---|
| media uniforme, engadida | 279,552 | 60.45 |
| unha attention head, substituíndo o token | 328,704 | 55.47 |
| unha attention head, engadida | 328,704 | 46.10 |
| catro heads en vez dunha | 345,216 | 43.21 |
| máis a rede feed-forward | 476,928 | 39.87 |
| máis LayerNorm: o bloque completo | 477,696 | 38.07 |
Os pesos aprendidos baten os uniformes por 14 puntos de perplexity, que é todo o argumento deste capítulo nunha fila. Catro heads compran outros 3 por 16.512 parámetros extra. E a mesma head vale 9 puntos máis engadida que substituíndo: attention trae información, non decide o que é unha posición.
Agora onde están realmente os parámetros, o que sorprende a quen só viu o diagrama:
| ancho | heads | attention | feed-forward | total por bloque |
|---|---|---|---|---|
| 128 | 4 | 65,664 (33.2 %) | 131,712 (66.6 %) | 197,888 |
| 768 | 12 | 2,360,064 (33.3 %) | 4,722,432 (66.6 %) | 7,085,568 |
| 4096 | 32 | 67,112,960 (33.3 %) | 134,238,208 (66.7 %) | 201,367,552 |
Dous terzos de cada bloque transformer son a rede feed-forward, a todas as escalas, porque attention ten catro matrices e o MLP ten o equivalente a oito. O que queira que saiba un modelo, a maioría dos parámetros que o gardan están no MLP por posición.
Residuais e LayerNorm, herdados do Capítulo 6
Ligazón á sección: Residuais e LayerNorm, herdados do Capítulo 6LayerNorm construíuse e mediuse no Capítulo 6, e este capítulo úsaa tal como quedou alí; as conexións residuais nomeáronse e ablacionáronse alí, e constrúense aquí. As filas «engadida, non substituíndo» de arriba son conexións residuais, que valen 188 puntos de perplexity para a media e 9 para unha head. LayerNorm7 normaliza cada exemplo entre as súas características, e o Capítulo 6 deu as razóns polas que ela, e non BatchNorm, sobreviviu aquí: sen dependencia do batch, sen estatísticas en execución, idéntica en adestramento e inferencia, indiferente á lonxitude da secuencia; cada unha delas convértese nun requisito cando xeras un token de cada vez para un usuario, que é onde acaba o Capítulo 13. Custa 768 parámetros e compra 1,8 puntos de perplexity.
class Block(nn.Module):
def forward(self, x):
x = x + self.att(self.ln1(x))
x = x + self.ff(self.ln2(x))
return xMira onde está a normalización: na entrada de cada subcapa, coa ruta residual da entrada á saída nunca normalizada. Iso é pre-norm. O artigo de 2017 fai o contrario, x = LayerNorm(x + Att(x)): post-norm, que pon unha LayerNorm na propia ruta residual.
Xiong et al. explicaron a diferenza a través do gradient na inicialización, que nunha rede post-norm queda mal escalado coa profundidade: a razón pola que o transformer orixinal precisaba un warmup da taxa de aprendizaxe para adestrar en absoluto.8 Doce bloques, 1000 pasos, taxa de aprendizaxe :
gradient norm per block at initialisation, before any step
pre-norm block 1 0.0498 ... block 12 0.0657 ratio last/first 1.32
post-norm block 1 0.0977 ... block 12 0.1613 ratio last/first 1.65
pre-norm, no warmup perplexity 37.82
pre-norm, 200-step warmup perplexity 37.62
post-norm, no warmup perplexity 308.05
post-norm, 200-step warmup perplexity 37.88Post-norm sen warmup é oito veces peor, e post-norm con warmup iguala exactamente pre-norm. Warmup non é aquí unha boa práctica xeral; é un parche para unha disposición específica da normalización, e mover a LayerNorm elimina a necesidade del. Por iso practicamente todos os modelos desde 2019 son pre-norm, e por iso o diagrama de 2017 debe lerse como historia máis que como especificación.
Onde está un token?
Ligazón á sección: Onde está un token?Elimina os embeddings de posición e o modelo segue adestrando; simplemente non pode saber onde está nada, e iso é unha simetría máis que un fallo de adestramento. Nada na puntuación de attention menciona nin en si, así que permutar a entrada permuta a saída: self-attention é equivariante a permutacións. É a cegueira á orde da media cun disfrace mellor: a máscara causal restaura algo de orde, xa que cada posición ve un prefixo distinto, pero dentro dun prefixo todas as ordenacións son iguais.
Catro maneiras de inxectar posición, adestradas en xanelas de 64 tokens e avaliadas en 64, 128 e 256 — máis alá de calquera lonxitude que viran:
| posicións | perplexity en 64 | en 128 | en 256 |
|---|---|---|---|
| ningunha | 48.79 | 52.63 | 57.52 |
| embeddings absolutos aprendidos | 38.63 | 108.47 | 181.94 |
| sinusoides fixas | 42.96 | 95.26 | 152.25 |
| RoPE | 44.12 | 50.52 | 84.84 |
| ALiBi | 44.95 | 43.51 | 42.49 |
Embeddings absolutos aprendidos — un vector por posición, engadido ao token — gañan na lonxitude adestrada e logo caen polo precipicio, porque a posición 100 nunca estivo nun batch e o seu embedding segue sendo o vector aleatorio co que empezou. Sinusoides, a escolla orixinal, calcúlanse en vez de aprenderse, a partir de senos e cosenos a frecuencias espazadas xeometricamente; o artigo de 2017 esperaba que iso extrapolase, e a táboa di que non: a función está definida na posición 200, pero o modelo nunca aprendeu a lela alí. RoPE9 non engade nada e en vez diso rota query e key por un ángulo proporcional á posición, en franxas bidimensionais; como rotar ambos lados dun produto escalar por igual o deixa sen cambios, a puntuación acaba dependendo só de , así que a posición faise relativa gratis e non hai unha táboa que se esgote. Degrádase, pero degrádase. ALiBi10 é o resultado máis simple e máis estraño aquí: unha penalización lineal na puntuación proporcional á distancia, cunha pendente distinta por head. A súa perplexity mellora a medida que a xanela medra máis alá da lonxitude de adestramento, de 44.95 a 42.49, porque a penalización está definida a calquera distancia e cada head segue facendo o que foi adestrada para facer.
A lección sobrevive á táboa: unha arquitectura que non pode representar algo é un problema distinto dunha que nunca aprendeu ese rango, e o segundo é o que morde. Tamén é a maquinaria detrás de cada anuncio de «estendemos o context a 128K»: case sempre son reescalados dunha codificación rotatoria, e son a razón pola que o Capítulo 16 di que o límite de context se move máis que desaparecer.
Dropout hérdase do mesmo xeito: aparece nos pesos de attention despois do softmax, na saída de cada subcapa antes da suma residual e na suma de embeddings, facendo exactamente o que describiu o Capítulo 6. Nas grandes execucións de pretraining adoita poñerse a cero, porque un modelo que ve cada token unha soa vez non está en condicións de sobreaxustar.
O que custa
Ligazón á sección: O que custaDous tensores da capa teñen forma , onde é o número de tokens: as puntuacións e os pesos despois do softmax. Todo o demais — cada proxección, todo o MLP — é lineal en .
Unha capa de attention, 512 de ancho, 8 heads, batch dun, float32, nunha GPU de portátil. Le as dúas columnas de milisegundos só polas súas proporcións: son tempo de reloxo nunha tarxeta de portátil de 8 GB que baixa de 1.785 MHz a menos de 300 MHz cando se quenta, así que unha execución en frío deste mesmo código volve sete a dez veces máis rápida e unha ocupada aínda máis lenta. As columnas de megabytes son contaxes de bytes do asignador e non se moven.
tokens ms total ms x4 ms projections attn matrix MB peak MB MB x4
128 2.246 - 1.324 0.5 14.6 -
256 2.855 1.27 2.113 2.0 19.2 1.31
512 5.761 2.02 3.105 8.0 34.4 1.79
1024 16.414 2.85 4.008 32.0 89.1 2.59
2048 51.573 3.14 9.989 128.0 296.1 3.32
4096 225.432 4.37 20.176 512.0 1100.1 3.72
8192 832.838 3.69 40.106 2048.0 4300.1 3.91
16384 OUT OF MEMORY 8192.0
fitted exponent (log-log slope, last four rows): time ~ n^1.91 memory ~ n^1.87As columnas x4 son a proporción respecto da fila anterior, e duplicar converxe exactamente a 4 tanto para tempo como para memoria: 3.91 no último paso fronte a un 4 teórico. A columna de proxeccións é o control: 4,0 ms en 1024 tokens a 40,1 ms en 8192, un factor dez por un factor oito. Lineal, como se anunciaba.
Logo a última fila. Unha capa de attention, unha secuencia, sen modelo arredor, queda sen memoria nunha GPU de 8 GB en 16.384 tokens: só a matriz de puntuacións sería de 8 GB, sendo 8 heads por 16.384 por 16.384 por 4 bytes. Non o modelo; un tensor intermedio nunha capa.
Ese é o feito físico baixo tres capítulos posteriores. É a razón pola que un context window ten un límite, que o Capítulo 16 converte nun prezo. É a razón pola que existe FlashAttention, que calcula o mesmo resultado en teselas sen almacenar nunca a matriz: unha optimización de memoria antes que de velocidade.11 E é a aritmética detrás do prezo dun prompt longo, que o Capítulo 24 paga nun bucle de agent: un asunto separado do outro achado dese capítulo, que un modelo tamén usa peor un context longo, algo que mide e rexeita culpar a esta fórmula.
Mostrar detalles
As dúas variantes que reducen a cache, nomeadas aquí e pagadas no Capítulo 13.
A xeración garda na cache as keys e values dos tokens xa procesados: unha key e un value por token, por head e por capa. Multi-query attention12 mantén proxeccións de query pero unha soa proxección de key e value compartida por todas as heads, dividindo esa cache por . Grouped-query attention13 interpola: as heads agrúpanse, cada grupo comparte unha key e un value, así que é attention ordinaria e é multi-query. Case todos os modelos abertos desde 2023 úsaa con 4 ou 8 grupos. Ningunha existe pola calidade; ambas existen polo tamaño desa cache, e o Capítulo 13 fai a aritmética que a converte en «que modelo cabe na túa GPU».
Dúas formas, e o tamaño dunha
Ligazón á sección: Dúas formas, e o tamaño dunhaO artigo de 2017 describe un encoder-decoder: unha pila que le a fonte con attention sen máscara, unha segunda que xera o destino causalmente, e un terceiro tipo de attention no medio onde as queries do decodificador se atopan coas keys do codificador. Iso é correcto para tradución, onde entrada e saída son dúas secuencias.
O que gañou foi a metade decoder-only: unha pila, causal de principio a fin, entrada e saída na mesma secuencia, e a razón non é a elegancia. «Predicir o seguinte token» funciona con calquera texto, así que o conxunto de adestramento é internet en vez dun corpus paralelo, e todo se converte nesa única tarefa: unha tradución é un documento que contén fonte e logo destino, unha pregunta e a súa resposta son un documento, unha conversa cun tool call polo medio é un documento. O Capítulo 11 trata de como se fabrica iso último. Os codificadores non desapareceron: un ve toda a entrada á vez, que é o que queres cando o traballo é representar un texto máis que continualo, e por iso os embeddings de retrieval do Capítulo 19 veñen de codificadores e non do modelo que está chateando.
Co bloque definido, o tamaño do modelo é aritmética. Por bloque, con ancho e expansión por catro: para con biases nas catro, como as ten GPT-2; a táboa anterior deixa o bias fóra de tres delas, de aí 2.304 menos por bloque en ; para o MLP; para dúas LayerNorms: , máis unha táboa de tokens de e, para posicións absolutas, . Para a forma de GPT-2 small — , 12 bloques, un vocabulario de 50.257, un context de 1024, a capa de saída compartindo os pesos do embedding:
token embeddings 50,257 x 768 = 38,597,376
position embeddings 1,024 x 768 = 786,432
one block 7,087,872
12 blocks 85,054,464
final LayerNorm 2 x 768 = 1,536
total (weights tied) 124,439,808Que é o tamaño publicado dese modelo. A fórmula non é unha aproximación; é o modelo. Fíxate tamén en que case un terzo dun modelo pequeno é a táboa de embedding, por iso o tamaño do vocabulario é unha decisión arquitectónica e non unha de preprocessing: o trade-off que preparou o Capítulo 7.
A que mira realmente unha head
Ligazón á sección: A que mira realmente unha headPerplexity é un número sobre un corpus. O que fai unha head é outra pregunta, e un modelo adestrado nun megabyte de Shakespeare é a ferramenta equivocada para ela: o honesto que se pode dicir do mapa de attention dun modelo de 500.000 parámetros é que na súa maior parte non é interpretable. Así que: unha linguaxe onde a pregunta ten unha resposta correcta.
A ilustración clásica é the animal did not cross the street because it was too tired, onde it é o animal, fronte a …because it was too wet, onde unha palabra move o referente á rúa. Estes son esquemas de Winograd14: pares de frases idénticas salvo por unha palabra, onde esa palabra decide a que se refire un pronome.
Tamén son resolubles facendo trampas, que é a parte que saltan os titoriais. Se os dous candidatos son un animal e un lugar, tired e wet identifican o referente por categoría, e un modelo que só sabe que palabras están presentes acertará sen saber nada da orde. Medido nesa versión da tarefa, con pares animal/lugar reservados:
uniform causal average held-out referent accuracy 100.0 %
one transformer block held-out referent accuracy 91.7 %A bolsa de palabras bate o transformer. Calquera demostración construída sobre esa frase non proba nada sobre attention.
Así que pecha o burato: escolle ambos candidatos dun conxunto de dezaseis substantivos, calquera deles podendo aparecer en calquera oco, e divide os adxectivos por papel en vez de por categoría: catro que fan que it sexa quen cruza (tired, scared, slow, weak), catro que fan que sexa o cruzado (wet, wide, busy, steep).
the {x} did not cross the {y} because it was too {adj} , so the {ref} waited .Adestra como un predictor ordinario do seguinte token, puntúa unha posición — a palabra despois de so the — e constrúe o conxunto reservado con pares de substantivos cuxa orde invertida estivo no adestramento, así que calquera cousa que saiba que dous substantivos están presentes pero non cal veu primeiro debe responder ao revés.
| modelo | parámetros | reservado | nomea o outro substantivo |
|---|---|---|---|
| só token actual | 5,796 | 5.2 % | 5.2 % |
| media causal uniforme | 5,796 | 27.9 % | 50.0 % |
| unha head de attention aprendida | 18,084 | 35.4 % | 64.6 % |
| catro heads | 22,244 | 75.0 % | 15.6 % |
| un bloque transformer | 55,716 | 92.7 % | 4.2 % |
| dous bloques transformer | 105,508 | 100.0 % | 0.0 % |
O azar entre os dous substantivos presentes é 50 %. A media uniforme queda en 27.9 % e responde co substantivo incorrecto do par exactamente a metade das veces: a sinatura de algo que sabe que palabras hai e nada sobre a súa orde, tal como predixo a proba de barallado tres seccións atrás.
Agora o mapa: a attention na posición que ten que nomear o referente, mediada sobre as catro heads de cada bloque, para as dúas frases que difiren nunha palabra. Unha media uniforme poñería 0.067 en cada un dos quince tokens visibles.
the animal did not cross the street because it was too tired , so the animal waited .
blk 1 the:0.00 animal:0.70 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.06
because:0.00 it:0.00 was:0.00 too:0.00 tired:0.00 ,:0.05 so:0.00 the:0.19
blk 2 the:0.00 animal:0.00 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.00
because:0.00 it:0.00 was:0.00 too:0.00 tired:1.00 ,:0.00 so:0.00 the:0.00
the animal did not cross the street because it was too wet , so the street waited .
blk 1 the:0.00 animal:0.70 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.06
because:0.00 it:0.00 was:0.00 too:0.00 wet:0.00 ,:0.05 so:0.00 the:0.19
blk 2 the:0.00 animal:0.00 did:0.00 not:0.00 cross:0.03 the:0.00 street:0.49
because:0.00 it:0.00 was:0.00 too:0.20 wet:0.03 ,:0.00 so:0.00 the:0.25O bloque 1 é idéntico nas dúas frases: 0.70 no primeiro substantivo, sexa cal sexa o adxectivo. Iso non é un fallo senón unha proba: na primeira capa, a query nunha posición é función do token e do índice propios desa posición, e the na posición 14 é o mesmo token nas dúas frases. Unha head de primeira capa non pode condicionar unha palabra que aínda non foi buscar. Así que o bloque 1 fai o único útil dispoñible e arrastra o primeiro substantivo cara adiante.
O bloque 2 é onde as frases se separan, e a mesma fila para os oito adxectivos mostra a regra que atopou o modelo:
| adxectivo | bloque 2 en animal | en street | no adxectivo | resposta |
|---|---|---|---|---|
| tired, scared, slow, weak | 0.000 | 0.000 | 1.000 | animal |
| wet, wide, busy, steep | 0.000 | 0.491 | 0.00–0.03 | street |
Para un adxectivo de quen cruza, o segundo bloque pon todo o seu peso no adxectivo, porque a resposta xa está no fluxo residual — o bloque 1 púxoa alí — e todo o que precisa é confirmación. Para un adxectivo do cruzado, vai buscar o outro substantivo. Iso é un circuíto de dous saltos: unha head move un candidato cara adiante, unha head nunha capa posterior le un token que decide se conservalo. A composición entre capas é o mecanismo, e por iso un bloque chegou ao 92.7 % e dous chegaron ao 100 %.
Tamén é a forma do circuíto mellor documentado en modelos reais. Induction heads — unha head de token anterior alimentando unha head na capa seguinte que completa o patrón [A][B] … [A] → [B] — son o que o traballo de interpretabilidade de Anthropic identifica detrás dunha gran parte da aprendizaxe in-context, e fórmanse nun momento identificable durante o pretraining. Este capítulo non intenta esa análise: déixaa delegada, con ambos artigos nas referencias, porque ler circuítos nun modelo real é un campo de investigación e non unha sección.
Finalmente, a implementación. As trinta liñas de arriba, cos seus pesos copiados dos propios de PyTorch:
ours vs nn.MultiheadAttention max |diff| = 1.7881393432617188e-07
ours vs F.scaled_dot_product_attention max |diff| = 1.7881393432617188e-07en saídas cuxa magnitude media é 0.159: a mesma aritmética nunha orde distinta, con precisión float32.
A onde vai isto agora
Ligazón á sección: A onde vai isto agoraTes a arquitectura da que se constrúe cada modelo do resto deste curso, e é menor que a súa reputación: unha media ponderada cuxos pesos se aprenden, un MLP por posición que contén dous terzos dos parámetros, dúas normalizacións e dúas sumas, apiladas.
O que non tes é un modelo que saiba nada, e apilar non o arranxará por si só. Dous bloques neste corpus alcanzan unha perplexity de adestramento de 14.49 e unha perplexity de validación de 40.57, fronte aos 18.77 e 38.07 dun bloque: máis capacidade, mellor no que viu, peor no que non viu, que é a táboa do Capítulo 6 cun transformer dentro. A distancia entre este modelo e aqueles cos que falan os Capítulos 14 a 30 non é arquitectónica. É o mesmo bloque, repetido máis veces, sobre moitísimo máis texto.
O que o converte nun problema de contabilidade, e a contabilidade é máis estraña do que parece. Canto texto, e de onde o saca alguén? Canta aritmética, e como a estimas antes de gastar os cartos? Cun orzamento fixo, é mellor facer o modelo máis grande ou ensinarlle máis datos — e hai unha resposta correcta, ou só unha moda? O Capítulo 10 responde as tres por medición, e pon prezo á forma útil máis barata da pregunta: que custa, hoxe, adestrar un modelo como GPT-2 desde cero?
Fontes e método
Ligazón á sección: Fontes e métodoTres explicacións deste material son mellores ca esta no que pretenden facer, e este capítulo está escrito para lerse xunto a elas. The Illustrated Transformer de Jay Alammar é a mellor imaxe do fluxo de datos que se debuxou nunca. The Annotated Transformer de Harvard NLP é o artigo de 2017 con código executable intercalado liña por liña. Let's build GPT: from scratch, in code, spelled out de Andrej Karpathy constrúe o mesmo modelo en directo en dúas horas, e a escaleira de ablations de arriba é a mesma columna vertebral medida nun corpus distinto. Para a pregunta de interpretabilidade que este capítulo só toca, as fontes primarias son Elhage et al., A Mathematical Framework for Transformer Circuits (2021) e Olsson et al., In-context Learning and Induction Heads (2022), ambos do grupo de interpretabilidade de Anthropic.
Referencias
Ligazón á sección: Referencias-
Hochreiter, S. and Schmidhuber, J. Long Short-Term Memory. Neural Computation 9(8), pp. 1735–1780 (1997). ↩
-
Sutskever, I., Vinyals, O. and Le, Q. V. Sequence to Sequence Learning with Neural Networks. arXiv:1409.3215 (2014). O encoder-decoder cuxo único vector de context é o pescozo de botella. ↩
-
Bahdanau, D., Cho, K. and Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. arXiv:1409.0473 (2014). Attention, tres anos antes do transformer. ↩
-
Perplexity é a exponencial da entropía cruzada media por token, do Capítulo 8. Cada número aquí usa o mesmo tokenizer e a mesma partición de validación, que é a única condición baixo a cal se poden comparar dúas perplexities. ↩
-
Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł. and Polosukhin, I. Attention Is All You Need. arXiv:1706.03762 (2017). A sección 3.2.1 é a frase sobre que este capítulo dedica unha sección a medir. ↩
-
Shazeer, N., Mirhoseini, A., Maziarz, K., Davis, A., Le, Q., Hinton, G. and Dean, J. Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer. arXiv:1701.06538 (2017). ↩
-
Ba, J. L., Kiros, J. R. and Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016). Introducida e medida no Capítulo 6; usada aquí sen cambios. ↩
-
Xiong, R., Yang, Y., He, D., Zheng, K., Zheng, S., Xing, C., Zhang, H., Lan, Y., Wang, L. and Liu, T.-Y. On Layer Normalization in the Transformer Architecture. arXiv:2002.04745 (2020). A análise do gradient detrás de pre-norm, e o argumento de que warmup é un síntoma. ↩
-
Su, J., Lu, Y., Pan, S., Murtadha, A., Wen, B. and Liu, Y. RoFormer: Enhanced Transformer with Rotary Position Embedding. arXiv:2104.09864 (2021). ↩
-
Press, O., Smith, N. A. and Lewis, M. Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation. arXiv:2108.12409 (2021). O resultado de extrapolación reproducido arriba. ↩
-
Dao, T., Fu, D. Y., Ermon, S., Rudra, A. and Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). ↩
-
Shazeer, N. Fast Transformer Decoding: One Write-Head is All You Need. arXiv:1911.02150 (2019). ↩
-
Ainslie, J., Lee-Thorp, J., de Jong, M., Zemlyanskiy, Y., Lebrón, F. and Sanghai, S. GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. arXiv:2305.13245 (2023). ↩
-
Levesque, H. J., Davis, E. and Morgenstern, L. The Winograd Schema Challenge. KR (2012). A construción detrás da frase animal / street que usa cada titorial de attention. ↩