O attention está errado por uma casa
(evanmiller.org)- O attention softmax dentro do Transformer pode dificultar a quantização e a implantação com pouca memória, porque não permite que uma head escolha “não fazer nada”
- A pista do problema são os pesos/ativações outliers observados em LLMs, e um artigo da Qualcomm AI Research analisa que mais de 97% das ativações outliers vêm de posições de espaço em branco e pontuação
- O softmax tradicional dá peso 1/k a cada termo mesmo quando todas as entradas são muito negativas, mas o
softmax_1adiciona 1 ao denominador para permitir que a saída de attention fique próxima de 0 - O
softmax_1preserva as proporções relativas enquanto limita a soma entre 0 e 1, e também mantém gradientes não nulos graças à sua derivada positiva - Essa mudança não é um patch para encaixar diretamente em modelos existentes: ela exige retreinamento, embora em modelos como o LLaMA possa ser possível fazer experimentos rápidos com um esquema de zero prefix token
Outliers que dificultam a quantização
- Em modelos Transformer aparecem pesos e ativações várias ordens de magnitude maiores que os demais valores, e esses valores parecem ser importantes para o funcionamento do modelo
- Esses outliers causam perda de desempenho na quantização inteira comum com scale-and-bias, o que dificulta colocar modelos grandes em ambientes com RAM limitada, como Mac Mini ou Raspberry Pi
- Reduzir o uso de RAM abre espaço para lidar com modelos maiores ou mais funcionalidades tanto em nuvem quanto em edge
- Quantizable Transformers: Removing Outliers by Helping Attention Heads Do Nothing, da Qualcomm AI Research, liga os valores outliers ao softmax do mecanismo de attention
- A análise conclui que mais de 97% das ativações outliers em LLMs ocorrem em posições de whitespace e punctuation
- clipped softmax tem problema de gradiente zero, e gated attention adiciona milhões de novos parâmetros
O papel do softmax no Transformer
- O embedding de entrada de um Transformer é um vetor de ponto flutuante que representa uma palavra
- O LLaMA 2, da Meta, usa vetores de embedding com comprimento 3.204, e em half-precision são necessários mais de 6 KB para representar uma única palavra
- O vocabulário normalmente tem 30.000~50.000 itens
- O Transformer transforma vetores de entrada em vetores de saída do mesmo tamanho, e o vetor de saída final é usado para prever o próximo token após o token atual
- A residual connection faz o attention funcionar como uma forma de adicionar informação de contexto à informação original da palavra
- Por exemplo, adicionando contexto para distinguir se
pupilsignifica aluno ou pupila do olho
- Por exemplo, adicionando contexto para distinguir se
- Na etapa final, o vetor de saída é convertido em um vetor do tamanho do vocabulário e então passa por softmax para ser tratado como as probabilidades do próximo token
- Na prática, a implementação usa um sampling mechanism em vez de confiar literalmente nas probabilidades produzidas pelo softmax
- O softmax na etapa de saída é visto como uma escolha razoável porque distribui gradientes por todo o vocabulário
Limites do softmax no attention interno
- A equação central do attention interno é a seguinte
[ \textrm{Attention}(Q, K, V) = \textrm{softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V ]
- Em um decoder-only model, (Q), (K) e (V) partem da mesma sequência de entrada, mas passam por projeções diferentes
- (QK^T) encontra correlações entre vetores de embedding de tokens, e o softmax é aplicado a cada linha para produzir pesos que misturam os vetores de valor da matriz (V)
- O multi-head attention executa esse processo em paralelo em várias heads de cada layer
- O vetor de embedding é dividido em vários segmentos, e cada head adiciona informação a um segmento do vetor de saída
- O problema é que o softmax força cada attention head a produzir alguma anotação
- Mesmo quando a head não tem nenhuma informação a acrescentar, o softmax ainda força uma escolha
- Quanto mais especializada for a head, maior a chance de ela precisar de um “pass”, mas o softmax tradicional não oferece essa abstenção
Proposta: softmax_1 e QuietAttention
- A mudança proposta é adicionar 1 ao denominador do softmax
[ (\textrm{softmax}_1(x))_i = \frac{\exp(x_i)}{1+\sum_j \exp(x_j)} ]
- No softmax tradicional, mesmo se todos os valores de (x) forem muito negativos, cada termo converge para (1/k)
[ \lim_{x_1 \to -\infty} \ldots \lim_{x_k \to -\infty} (\textrm{softmax}(x))_i = \frac{1}{k} \gt 0 ]
- No
softmax_1, nas mesmas condições, cada termo converge para 0
[ \lim_{x_1 \to -\infty} \ldots \lim_{x_k \to -\infty} (\textrm{softmax}_1(x))_i = 0 ]
- Essa diferença permite que uma attention head escolha não adicionar informação
- A equação de attention proposta é a seguinte
[ \textrm{QuietAttention}(Q, K, V) := \textrm{softmax}_1 \left(\frac{QK^T}{\sqrt{d}}\right)V ]
Propriedades do softmax_1 e condições experimentais
- O
softmax_1reduz um pouco a magnitude total dos valores, mas como há normalização depois do attention, essa redução pode ser compensada - As proporções relativas do vetor de saída permanecem iguais às do softmax tradicional
[ \frac{(\textrm{softmax}_1(x))_i}{(\textrm{softmax}_1(x))_j} = \frac{(\textrm{softmax}(x))_i}{(\textrm{softmax}(x))_j} = \frac{\exp(x_i)}{\exp(x_j)} \quad \forall \ i, j ]
- A derivada é positiva, então gradientes não nulos são preservados, e a soma fica entre 0 e 1, mantendo a saída dentro de uma faixa controlada
- Esse problema é tratado como uma questão matemática, não de precisão numérica, e precisão extra por si só não resolve
- A ideia experimental é anexar um vetor zero antes de todo o contexto de entrada e garantir, inclusive com positional encoding, que nenhum viés seja adicionado
- Se o zero passar intacto, isso produz o efeito de adicionar 1 a cada denominador do softmax subsequente
- Isso pode ser viável em modelos LLaMA, que usam embedding fixo e um special prefix token
- Não é um experimento para aplicar diretamente a modelos existentes; o modelo precisa de retreinamento
- Os valores que se quer observar são a mudança na kurtosis dos pesos e na infinity norm das ativações
1 comentários
Opiniões do Hacker News
O que o autor propõe não é o softmax da saída final, mas adicionar 1 ao denominador do softmax interno da atenção
O softmax da atenção faz o casamento chave/consulta parecer uma probabilidade, permitindo uma busca chave-valor com pesos de valor contínuo em vez de uma consulta 0/1
Ao adicionar 1 ao denominador, a soma dos pesos fica menor que 1, então deixa de ser um vetor de probabilidade de verdade; mas, se o modelo aprender pesos altos, ele se comporta quase como um vetor de probabilidade, e também pode escolher “não ter certeza de nada” ao produzir pesos todos baixos
Para saber se isso é realmente bom, é só treinar um LLM desse jeito. Mas acho que não faria grande diferença. Nós de atenção com baixa confiança já podem tornar as pontuações pré-softmax parecidas, criando uma distribuição quase uniforme; nesse caso, viram a média de vários vetores, que estatisticamente tem grande chance de ficar perto de 0
Além disso, o Transformer já tem muitos pesos aprendidos capazes de implementar um opt-out, como a matriz V e a camada feed-forward após a atenção. Ainda assim, gosto do tom não acadêmico do texto e da atitude de mexer em uma ideia fundamental; não fiquei totalmente convencido, mas gostaria de ler mais textos assim
Como memória é o gargalo ao executar modelos grandes, se isso for verdade, é algo bastante significativo
Como no trecho em que ele diz que originalmente queria chamar essa função de ghostmax: é como se houvesse um item adicional de valor 0 em x e, como
exp(0)=1, a matriz V também tivesse um vetor zero que enfraquece o resultadoEm vez de “a soma dos pesos é menor que 1, então às vezes nada é escolhido”, é melhor pensar que, toda vez que o conjunto de opções é considerado, a opção não fazer nada também é obrigatoriamente considerada
É a diferença entre “quando você só tem um martelo, tudo parece prego” e “mesmo só tendo um martelo, você bate em pregos e ignora o que não é prego”
Por exemplo, em um sistema de fala para texto, é incômodo quando primeiro uma pessoa precisa especificar o idioma e, ao fornecer áudio nesse idioma, ele produz uma transcrição razoável, mas, se a escolha de idioma na etapa 1 estiver errada, sai um absurdo. Um transcritor de inglês, ao receber áudio em francês, deveria primeiro dizer “isto não é inglês”, o que se aproxima mais do comportamento humano
Em um, coloca-se +1 no denominador do softmax do módulo de atenção; no outro, não. É preciso mostrar que o desempenho é parecido e que, no modelo com +1, há menos explosões, tornando a quantização mais eficaz
Assim como redes neurais não modelam bem a função identidade e por isso precisam de conexões residuais, também acho que elas são bastante fracas para aprender implicitamente transformações de baixa entropia
Mesmo que isso não aumente a expressividade, pode ter o efeito de embutir no modelo uma transformação do tipo procurar agulha no palheiro que seria difícil de alcançar por descida do gradiente. Não sei o quanto isso é útil na prática
O motivo de ela não ser amplamente usada é que as pessoas já tentaram e, na prática, ela não funcionou tão bem. Chamar isso, no texto original, de “bug ignorado por mais de 8 anos” é quase clickbait
Talvez eu esteja deixando algo passar, mas não entendo por que os comentários tratam isso como algo tão grande. Já vi esse truque várias vezes na prática
Por exemplo, há este código em um repositório antigo do Google: https://github.com/google/flaxformer/blob/ee62754ebe5a5eeb11...
Não acho que vá ajudar em nada na estabilidade. Para estabilidade do softmax ao escalar, truques como Q/K layernorm são melhores: https://arxiv.org/pdf/2302.05442.pdf
Escrever um post de blog ou artigo para aumentar a conscientização tem bastante valor. Também é comum que boas ideias sejam descobertas independentemente várias vezes
Se a distribuição mais achatada por causa do denominador maior leva a um comportamento melhor na quantização é algo que só dá para saber comparando diretamente o caso com +1 e sem +1. O texto original considera que esse benefício pode ser grande
Tecnicamente, o softmax não é implementado exatamente como na fórmula apresentada, mas como
exp(x_i-max(x)), e esses valores são somados no denominador. Talvez eu esteja deixando algo passarAlém disso, conexões residuais são usadas porque a rede não consegue aprender bem a função identidade, mas 0 ela consegue aprender. Então, em
f(x): x+g(x), basta queg:x ~> 0, ou seja, que fique quase 0f(x): x+g(x)também facilita o fluxo do gradienteEsse truque “descoberto” faz parte da implementação padrão de atenção multi-head do PyTorch, e se chama
add_zero_attentionComo adiciona 0 aos logits,
e^0=1, então aparece 1 no denominador: https://pytorch.org/docs/stable/generated/torch.nn.Multihead...Não explica nem brevemente o significado. Só adicionar a segunda frase que escrevi acima já a tornaria muito mais útil
Não é sobre IA nem sobre esse algoritmo, mas há casos em que, por mais que você aponte um pequeno erro, não consegue convencer as pessoas de que é um erro.
Em 2011, eu estava tentando copiar o algoritmo de ranking do reddit para um projeto meu e olhei o código-fonte, mas ele tinha um comportamento que não fazia nenhum sentido para posts com soma negativa de votos.
Achei que, numa fórmula simples, um termo tinha sido trocado e os sinais positivo/negativo tinham sido aplicados incorretamente. Então escrevi no blog e postei no reddit, mas muita gente, incluindo funcionários do reddit, disse que eu estava completamente errado e que o algoritmo funcionava como pretendido.
Também disseram que outras pessoas já tinham percebido e apontado a mesma coisa antes, mas todas ouviram que estavam erradas.
No fim, alterei o post do blog para algo como “pessoas mais inteligentes do que eu disseram que não há erro no algoritmo do reddit; apenas a minha variação faz mais sentido para mim”.
Mas, três anos depois, em 2014, exatamente a correção que eu, e as pessoas antes de mim, vínhamos sugerindo foi comitada no código-fonte do reddit: https://github.com/reddit-archive/reddit/commit/50d35de04b92...
O open source permite que muitos olhos encontrem bugs, mas às vezes você não consegue convencer ninguém de que encontrou um bug. Claro que o reddit fechou o código em 2017.
No fim, não coloquei no meu app nem a funcionalidade de ranking que eu pretendia copiar originalmente, nem a de votação.
Era preciso codificar muitos valores nos parâmetros de query, e alguns parâmetros específicos, na prática, precisavam ser codificados duas vezes, então minha ferramenta fazia isso. Mas o engenheiro que estava implementando insistia que minha ferramenta estava errada, usou o fato de eu ser estagiário contra mim e até recorreu à especificação do OAuth, forçando uma interpretação de que a implementação dele estava certa e eu é que estava lendo errado.
No fim, só depois de chamarem Eran Hammer-Lahav para confirmar é que se concluiu que eu estava certo, e só então aquele engenheiro admitiu que, obviamente, era aquilo mesmo. Não houve nenhum reconhecimento nem pedido de desculpas pelos dias de ataques pessoais.
Aprendi uma lição importante: ser mais sênior não significa estar sempre certo. Hoje, normalmente sou eu que estou na posição mais sênior, mas tento me lembrar disso todos os dias.
Só de ser “a pessoa que coloca logs em vários pontos do codebase e raciocina passo a passo”, já dá para construir uma carreira longa e de impacto. Mesmo fazendo isso em um nível bem simples, muitas vezes vi correções surpreendentes para problemas antigos.
Mas isso também vem com bastante diversão política. A primeira reação das pessoas é negar, e depois piora. Só uma ou duas pessoas veem como “ah, então é só corrigir”; alguém vai escrever um e-mail, com o chefe do chefe do chefe em cópia, embalando de forma bonita algo como “há falta de preocupação com concorrência/gerenciamento de memória/etc.”
Nesses casos, é melhor esperar em silêncio, sem confrontar nem reclamar. Se nada acontece, a liderança não pergunta nada, mas os colegas começam a perguntar, é melhor começar a planejar uma mudança para outra equipe.
Há uma discussão interessante sobre features outlier e quantização: https://timdettmers.com/2022/08/17/llm-int8-and-emergent-fea...
Valores outlier são usados para podar valores, e Transformers parecem passar por uma “transição de fase” na forma como lidam com features outlier por volta de 6,7 bilhões de parâmetros. Isso pode complicar estudos de ablação.
Parece haver muito a conversar com Tim Dettmers.
O autor identifica um problema real e propõe uma solução simples. Passa em todos os meus critérios de detecção de gente esquisita
Sobre “por que ninguém pensou nisso?”, é plausível a explicação de que o autor estava muito familiarizado com a função softmax em trabalhos fora de machine learning, e que as pessoas investigando esse problema talvez tenham chegado a restringi-lo a “algo relacionado ao softmax”, mas sem entender o próprio softmax com profundidade suficiente
Dito isso, se o autor do post original vir este comentário, seria bom se ele detalhasse melhor a afirmação de que isso “resolveria o loop de feedback de outliers com 99,44% de probabilidade”. Por enquanto, essa frase é a única explicação de como outliers poderiam estar relacionados ao softmax
https://github.com/google/flaxformer/blame/ee62754ebe5a5eeb1...
O comentário diz: “Função softmax com um logit virtual adicional igual a 0. Para compatibilidade com alguns modelos treinados anteriormente. Isso equivale a somar 1 ao denominador. No contexto de atenção, permite não olhar para nada”
Ela cria exatamente o mesmo softmax modificado deste texto. O tempo dirá por que isso foi ignorado publicamente. Talvez não tenha tido muito efeito, talvez tenha simplesmente ficado enterrado, talvez o Google não tenha promovido a ideia
Não é algo que tenha sido de fato testado; é apenas algo que se acredita que vá funcionar. Uma mudança tão simples no softmax não levaria muito tempo para validar, então é bem constrangedor não ter feito isso antes de publicar
Softmax é muito bem compreendido dentro da comunidade de machine learning. É um truque extremamente comum, e propriedades como essa também são bem conhecidas. Parece improvável que ninguém tenha pensado nisso
Ainda assim, é possível que a convenção atual de softmax tenha sido escolhida por acaso e que o autor tenha identificado corretamente sua deficiência
Mesmo que o diagnóstico esteja correto, LLMs em precisão total podem contornar o problema atribuindo pesos de atenção altos a tokens sem significado, de modo a produzir uma saída de atenção inofensiva
Esse problema só importa ao quantizar os pesos, e o objetivo do desenvolvimento recente de LLMs de ponta não é necessariamente o desempenho com quantização
Algo como: o softmax é bom em expressar 99,9% de certeza ou 0,1% de certeza, mas quase nada no meio
Sei que reclamar da academia é moda no HN, mas este post de blog não constrói um bom argumento
O ponto central poderia ter sido transmitido em 1/4 do tamanho total, talvez até em menos de 1/8, mas foi embrulhado em linguagem informal e em reclamações mal disfarçadas sobre publicação acadêmica
Como resultado, a discussão aqui virou 200 comentários sobre publicação acadêmica vs. blog, escrita formal vs. escrita informal, em vez dos resultados ou da ideia do texto
Pode ser um bom estilo se você quer colocar um post de blog na primeira página do HN. Mas, se quer que as pessoas examinem e discutam os prós e contras da ideia, não é muito bom
As pessoas têm uma quantidade limitada de atenção para gastar com tudo, mas a capacidade e a necessidade de receber atenção são ilimitadas. É o que Michael Goldhaber dizia
Isso se torna a semente da explosão de informação. Coisas como 6 bilhões de vídeos ensinando a cozinhar ovos ou 200 comentários estilo “bike shed”
Para tentar conter isso, lugares como Google, Facebook e HN ranqueiam comentários, links e feeds de notícias, mas como a maior parte do conjunto ranqueado é besteira, isso vira apenas mais uma camada de besteira
Ainda não projetamos sistemas de informação que reflitam o que Goldhaber disse sobre atenção há 30 ou 40 anos
O objetivo pode ser informar e, ao mesmo tempo, entreter. Muita gente gosta de discussões soltas em torno do ponto central, e o autor pode preferir isso ao tom clínico e formal de um artigo acadêmico
Ainda assim, é um pouco irritante ter que pular 200 comentários de reclamações fora do assunto para vê-la
Fiz um experimento parecido e, na minha configuração, não ajudou
Não vou afirmar que não havia algum bug, mas prestar atenção à posição atual parece resolver esse problema em certa medida. Quando não deve dizer nada, o modelo simplesmente emite o valor da posição atual
Mais precisamente, eu não somei 1 ao denominador do softmax; em vez disso, anexei antes de QK um attention sink que era um parâmetro aprendido, e o removi depois do softmax, de modo que a soma não fosse 1 ao multiplicar por V
Também testei uma variante que olha para a posição atual e outra que não olha, além de uma variante que gera o sink por posição usando uma rede feedforward em vez de um parâmetro aprendido. Na minha configuração, nenhuma delas fez grande diferença, mas havia muitas outras coisas estranhas misturadas, então talvez valha a pena tentar de novo
No contexto deste texto, tanto o desempenho na tarefa quanto a quantidade e o tamanho dos pesos outliers parecem importantes
Não vejo resultados. Se houvesse números complementando a teoria, seria muito mais forte e convincente
Não é tão difícil ajustar finamente um modelo de linguagem existente com poucos dados para verificar se funciona
Dito isso, concordo com a ideia de que pode haver fórmulas de atenção melhores. O artigo de 2020 https://arxiv.org/abs/2005.09561 ajudou bastante em um modelo Transformer que treinei. Não era um modelo de linguagem geral, mas um problema multimodal de grafos específico
Esse artigo propõe atenção normalizada e, se eu não estiver enganado, ela também pode ajudar no problema de quantização
Esse método era usado com frequência antes de os tokens dummy se popularizarem. Vi essa ideia pela primeira vez no paper do XLNet
Pelo que sei, ela já estava no PyTorch desde 2019/2020, e alguém provavelmente conseguiria encontrar referências ainda mais antigas
Fiquei surpreso com o tom exagerado do post original. Especialmente por se tratar de algo que a maioria dos pesquisadores de Transformers entende. Também me surpreende que haja muitas respostas com a posição de que “é assim que se deve fazer pesquisa”. Isto é mais um exemplo de por que pesquisa não funciona desse jeito; a revisão por pares é boa em vários aspectos, e um deles é reduzir as chances de você passar vergonha
Parece que estão lendo uma autodepreciação ambígua como se fosse uma afirmação literal
Resumindo por que isso era importante e foi compartilhado: trata-se de um problema bem de nicho, relevante quando se tenta rodar uma imitação tênue do ChatGPT em hardware limitado. Portanto, é bem possível que grandes equipes de pesquisa não tenham considerado isso importante. Afinal, elas não estão tentando rodar LLMs em uma 3090
O texto tem um tom coloquial, autodepreciativo e bem-humorado. Não sei quais são os prós e contras, mas consegui acompanhar totalmente o raciocínio. Está longe de ser arrogante
Dizer que “reduz as chances de você passar vergonha” implica que estar errado ou não ser o primeiro a descobrir algo seria vergonhoso. Isso não é arrogante?