Como o modelo converte token em vetor e vetor de volta em token?
A camada de embedding é uma tabela de consulta: o id do token endereça uma linha de uma matriz grande, e essa linha é o vetor que entra no primeiro bloco. O unembedding faz o caminho de volta e não é uma tabela — ele compara o vetor que sai do último bloco com todas as linhas, uma a uma, e devolve um número por token do vocabulário. Em muitos modelos as duas pontas usam a mesma matriz.
São as duas fronteiras do modelo. Antes da primeira não existe vetor, só id de token, e o caminho até ali está em do texto ao token. Depois da segunda não existe mais vetor, só uma pontuação por token do vocabulário, e o que se faz com essa pontuação está em logits e logprobs. O percurso inteiro entre uma e outra é o assunto de como um LLM funciona por dentro.
Vale limpar uma confusão de nome antes de seguir. “Embedding” em busca vetorial é outra coisa: um vetor por frase ou por documento, produzido por um modelo treinado para que textos de sentido parecido fiquem perto, o embedding de recuperação. Aqui é um vetor por entrada do vocabulário, aprendido como efeito colateral de treinar o modelo a prever a próxima palavra. Os dois espaços não se substituem, e usar um no lugar do outro é um erro comum e caro.
As duas pontas, com a mesma matriz
A matriz tem uma linha por entrada do vocabulário e uma coluna por dimensão do modelo. No Qwen3-8B são 151.936 linhas de 4.096 números cada, 622 milhões de pesos. É um dos poucos pedaços de um LLM que dá para descrever inteiro em uma frase.
Nos livros a entrada aparece como uma multiplicação de matrizes: o token vira um
vetor com um 1 na sua posição e zero em todas as outras, e esse vetor multiplica a
matriz. A conta funciona, e o resultado é exatamente a linha correspondente — os
zeros anulam todo o resto. Nenhuma implementação faz isso. Seriam 151.936
multiplicações para ler uma linha que está num endereço conhecido. Na prática é um
gather: pega a linha, pronto.
Uma sutileza do paper de 2017 sobrevive na maioria dos modelos de hoje. Depois de ler a linha, os valores são multiplicados pela raiz quadrada da dimensão do modelo1. Com 4.096 dimensões isso é um fator de 64. O paper registra a operação sem explicar o motivo; a leitura comum é que a mesma matriz precisa ter escalas diferentes nas duas pontas, e o fator ajusta a magnitude do lado da entrada sem mexer no da saída.
Na saída a lógica se inverte. O vetor que sai do último bloco é multiplicado por cada linha da matriz, e cada produto escalar vira um logit. Um número por token do vocabulário, 151.936 deles, calculados do zero a cada token gerado. Na entrada o custo é de um acesso à memória; na saída é de uma multiplicação contra a matriz inteira.
Essa assimetria explica a intuição geométrica do que o modelo está fazendo. O produto escalar é maior quando o vetor final aponta na direção da linha. Gerar texto, então, é empurrar um vetor até que ele aponte para a região do espaço onde mora o token certo. Todos os blocos do meio existem para isso: mover um ponto num espaço de alguns milhares de dimensões, um empurrão de cada vez.
O que cada bloco escreve, lido no vocabulário
Se a saída é um produto contra a matriz, dá para aplicar esse produto antes da última camada e ver o que o modelo estava prestes a dizer no meio do caminho. Isso funciona porque o vetor não é substituído a cada bloco: ele acumula somas ao longo do residual stream, e o que a matriz de saída lê no fim é a soma de tudo que foi escrito. A técnica ficou conhecida como logit lens, e é a base de boa parte da interpretabilidade prática.
Geva e colegas levaram a ideia a sério em 2022 e reinterpretaram a camada feed-forward inteira nesses termos. Tratando a representação de um token como uma distribuição sobre o vocabulário, cada camada vira uma atualização aditiva sobre essa distribuição, e cada atualização se decompõe em sub-atualizações correspondentes a vetores individuais de parâmetro — muitas delas promovendo conceitos que uma pessoa consegue nomear. Eles usaram isso para duas coisas concretas: reduzir a toxicidade do GPT-2 em cerca de metade e economizar 20% de computação com saída antecipada2.
O método tem um problema conhecido, e ele importa. Projetar uma camada intermediária com a matriz de saída assume que aquela camada já escreve na mesma base que a última, e isso não é verdade. Belrose e colegas mediram o desvio e propuseram uma correção: uma sonda afim treinada para cada bloco, que converte o estado escondido em distribuição sobre o vocabulário. Em modelos de até 20 bilhões de parâmetros, a versão calibrada ficou mais previsível, mais confiável e menos enviesada que o logit lens simples, e as trajetórias de previsão que ela produz identificam entradas maliciosas com boa precisão3.
Dar e colegas foram um passo além e mostraram que dá para projetar os próprios parâmetros do transformer no espaço do vocabulário, sem rodar o modelo, e ainda assim interpretá-los4. É a mesma ideia levada ao limite: a matriz de saída é o dicionário que traduz qualquer vetor interno em palavras.
Pesos amarrados
A ideia de usar a mesma matriz nas duas pontas é de 2016 e vem de dois trabalhos independentes. Press e Wolf estudaram a matriz do topo de modelos de linguagem, mostraram que ela também é um embedding de palavras válido e recomendaram amarrar as duas; o ganho foi redução consistente de perplexidade, e em tradução automática o modelo caiu para menos da metade do tamanho sem perder desempenho5. Inan, Khosravi e Socher chegaram ao mesmo arranjo por outro caminho, partindo de um enquadramento teórico da função de perda em vez de uma observação empírica6. O transformer original já nasceu com os pesos compartilhados, citando o primeiro dos dois1.
O motivo de funcionar é razoável. As duas matrizes descrevem o mesmo conjunto de símbolos; treinar duas versões independentes gasta parâmetros para redescobrir a mesma estrutura duas vezes, e a versão da saída recebe sinal de treino muito mais concentrado nos tokens frequentes.
O que mudou desde então é a escala, e com ela a decisão. A família Qwen3, lançada em 2025, dá o exemplo mais limpo porque usa o mesmo vocabulário de 151.936 entradas em todos os tamanhos. Os modelos de 0,6B, 1,7B e 4B amarram os pesos; os de 8B e 14B não. A conta explica por quê. Com 1.024 dimensões, a matriz tem 156 milhões de pesos, e o modelo de 0,6B tem 0,44 bilhão de parâmetros fora dela. Amarrar economiza 26% do modelo inteiro. Com 4.096 dimensões, cada matriz tem 622 milhões de pesos, e as duas juntas são 1,25 bilhão dos 8,2 bilhões do modelo de 8B: 15%, contra 6,95 bilhões de parâmetros de verdade fazendo o trabalho.
Em modelo pequeno, portanto, amarrar é quase obrigatório: um quarto do orçamento de parâmetros iria para uma tabela de consulta. Em modelo grande a economia deixa de compensar a restrição, porque a geometria que serve para agrupar tokens parecidos na entrada não é a mesma que serve para separá-los na saída. Um exemplo direto: na entrada, interessa que as várias grafias de uma palavra caiam perto umas das outras; na saída, interessa distingui-las, porque só uma está certa naquele contexto.
O custo, em memória e em conta
A matriz de saída é o único lugar do modelo onde o vocabulário aparece na conta, e por isso ela se comporta diferente do resto.
Memória. No Qwen3-8B, 622 milhões de pesos em 16 bits ocupam 1,24 GB. Com as duas matrizes separadas, 2,5 GB antes de qualquer bloco. Não é o que domina a fatura de um modelo desse porte, mas é um número que costuma ser esquecido nas estimativas rápidas.
Computação por token. A passada de saída são 622 milhões de multiplicações acumuladas, cerca de 1,24 GFLOP. Uma passada completa do modelo de 8B fica na casa de 16 GFLOP, então a cabeça de saída sozinha responde por algo perto de 8% do custo de gerar um token. Para um modelo com o mesmo vocabulário e um décimo dos parâmetros, a mesma cabeça vira uma fatia bem maior.
O tensor de logits. Este é o que morde na prática. São 151.936 números por posição; em 32 bits, 594 KB. Uma posição só é irrelevante. Mas se você materializa os logits do prompt inteiro — o que acontece no treino, e em qualquer código que peça logprobs de toda a sequência — um contexto de 4.096 tokens vira um tensor de 2,5 GB, para uma requisição, antes do lote. É a razão de bibliotecas de treino calcularem a perda em fatias e de a maioria das APIs devolver logprobs só dos tokens gerados e só do topo da distribuição.
Onde isso falha
O posto da matriz limita o que pode ser dito. Os logits de todos os contextos possíveis formam uma matriz cujo posto não passa da dimensão do modelo, porque ela é o produto de dois fatores dessa largura. Yang e colegas formalizaram isso em 2017 como softmax bottleneck: se a distribuição verdadeira da linguagem exige posto maior, nenhum treino resolve, e a saída fica limitada por construção. Eles propuseram uma mistura de softmaxes e melhoraram o estado da arte em Penn Treebank e WikiText-2, para 47,69 e 40,68 de perplexidade7. O escopo é de modelos recorrentes de 2017, e a dimensão de hoje é muito maior; o argumento estrutural, porém, continua valendo.
Algumas palavras não conseguem ganhar. Demeter, Kimmel e Downey mostraram um efeito mais concreto do mesmo mecanismo. Como o logit é um produto escalar e a probabilidade sai de um softmax sobre esses produtos, palavras cujo vetor cai no interior do fecho convexo do espaço de embedding têm a probabilidade limitada superiormente pelas palavras que estão na casca8. Elas nunca podem ser a previsão mais provável, em contexto nenhum. Não é falta de treino: é geometria.
A ida e a volta não são inversas. É tentador ler a simetria da figura como “desfazer o embedding”, e não é. A ida é um endereçamento exato; a volta é uma comparação com todas as linhas, que devolve uma distribuição. Nada garante que passar um vetor de embedding pela saída recupere o token de origem, e a proximidade entre duas linhas não diz que o modelo confunde os dois tokens — só que os vetores apontam para direções parecidas.
A linha do embedding não sabe de contexto. No ponto em que a matriz é lida, o vetor de “banco” é o mesmo na frase sobre dinheiro e na frase sobre praça. Isso é por construção, e é o que distingue esse vetor daquilo que se chama de embedding em recuperação. Tratar as linhas da matriz de um LLM como representações semânticas de palavra é aplicar a elas uma expectativa que vem de word2vec e de trabalhos da mesma linhagem, que treinavam vetores especificamente com esse objetivo e mediam a qualidade em testes de similaridade sintática e semântica9. A matriz de um LLM foi otimizada para outra coisa.
Trocar o vocabulário quebra as duas pontas. Adicionar tokens exige redimensionar a matriz, e num modelo com pesos amarrados a linha nova entra na entrada e na saída ao mesmo tempo. Inicializar as linhas novas com ruído costuma degradar o modelo de imediato; a prática que funciona é partir da média das linhas existentes ou da média dos subtokens que compunham o termo antes.
O que fazer com isso
- Compare modelos por parâmetros não-embedding. É o número que prevê capacidade. Dois modelos de “0,6B” com vocabulários diferentes podem ter 30% de diferença no que de fato computa.
- Não use a matriz de um LLM como embedding de busca. Para recuperação, use um modelo treinado para isso. A distinção está em o que é um embedding.
- Peça logprobs só do que você vai usar. O tensor completo é de centenas de KB por posição, e quase toda API devolve apenas o topo da distribuição por padrão.
- Conte a matriz separadamente ao dimensionar memória de modelo pequeno. Em modelo de menos de 2 bilhões de parâmetros ela é uma fatia grande e some das estimativas feitas por regra de três.
- Ao expandir o vocabulário, inicialize a partir do que já existe. Média das linhas dos subtokens antigos, não ruído. E confira se o modelo amarra os pesos antes de mexer em uma das pontas.
- Ao ler logit lens de camada intermediária, desconfie. A projeção crua é enviesada; se a conclusão importa, use uma sonda calibrada por camada.
Footnotes
-
Vaswani et al. (2017) descrevem, na seção 3.4, o compartilhamento da mesma matriz de pesos entre as duas camadas de embedding e a transformação linear anterior ao softmax, com os pesos da entrada multiplicados pela raiz quadrada da dimensão do modelo. ↩ ↩2
-
Geva et al. (2022) trataram a representação de um token como distribuição sobre o vocabulário e mostraram que cada camada feed-forward é uma atualização aditiva decomponível em sub-atualizações interpretáveis; aplicaram o resultado para cortar cerca de metade da toxicidade do GPT-2 e economizar 20% de computação com saída antecipada. ↩
-
Belrose et al. (2023) treinaram uma sonda afim por bloco para converter estados escondidos em distribuição sobre o vocabulário e mostraram que ela é mais previsível, confiável e menos enviesada que o logit lens, em modelos de até 20 bilhões de parâmetros. ↩
-
Dar et al. (2022) propuseram interpretar os parâmetros do transformer projetando-os no espaço do vocabulário, sem passada para frente nem para trás, e aplicaram isso a alinhamento de parâmetros entre modelos que compartilham vocabulário. ↩
-
Press e Wolf (2016) mostraram que a matriz do topo de um modelo de linguagem é um embedding de palavras válido e que amarrá-la à matriz de entrada reduz perplexidade; em tradução automática, o modelo cai para menos da metade do tamanho sem perda de desempenho. ↩
-
Inan et al. (2016) chegaram ao mesmo compartilhamento por um enquadramento teórico da função de perda, argumentando que treinar contra alvos one-hot desperdiça informação e parâmetros. ↩
-
Yang et al. (2017) formularam modelagem de linguagem como fatoração de matriz e mostraram que o softmax sobre embeddings distribuídos limita o posto da matriz de logits, propondo uma mistura de softmaxes que levou a perplexidade a 47,69 no Penn Treebank e 40,68 no WikiText-2. ↩
-
Demeter et al. (2020) mostraram, por análise numérica, teórica e empírica, que palavras no interior do fecho convexo do espaço de embedding têm a probabilidade limitada pelas palavras da casca, o que as impede estruturalmente de serem a previsão mais provável. ↩
-
Mikolov et al. (2013) propuseram duas arquiteturas para aprender vetores contínuos de palavra a partir de corpora muito grandes, com ganho de qualidade a custo computacional bem menor, medido em um conjunto de teste de similaridade sintática e semântica. ↩
Perguntas frequentes
- O que é a matriz de embedding de um LLM?
- É uma tabela com uma linha por entrada do vocabulário e uma coluna por dimensão do modelo. O id que sai do tokenizador é o número da linha, e essa linha é o vetor que entra no primeiro bloco. Ela é aprendida no pré-treino junto com o resto dos pesos.
- O que são tied embeddings?
- É usar a mesma matriz na entrada e na saída, em vez de duas independentes. Economiza vocabulário vezes dimensão pesos, o que em modelo pequeno é um quarto do total. O custo é que a geometria boa para agrupar tokens na entrada nem sempre é a boa para separá-los na saída.
- A cabeça de saída de um LLM é uma tabela de consulta?
- Não. Na entrada há endereçamento: um id, uma linha. Na saída há comparação: o vetor final é multiplicado por todas as linhas do vocabulário e cada produto vira um logit. É a diferença entre ler uma posição da memória e varrer a matriz inteira a cada token gerado.
- O embedding de um LLM serve para busca vetorial?
- Mal. As linhas da matriz representam tokens isolados e sem contexto, e foram otimizadas para prever a próxima palavra. Modelos de recuperação produzem um vetor por trecho de texto, treinados para que trechos com sentido parecido fiquem perto. São espaços diferentes com objetivos diferentes.
- Por que o vetor de entrada de um token é sempre o mesmo?
- Porque nesse ponto o modelo ainda não olhou para o resto da frase. A matriz é indexada por id, e o id de "banco" é o mesmo em qualquer frase. A diferenciação por contexto acontece depois, nos blocos de atenção, que somam ao vetor informação vinda das outras posições.
- Quanto de um modelo é matriz de embedding?
- Depende do tamanho. No Qwen3-0,6B a matriz amarrada tem 156 milhões de pesos, 26% do modelo. No Qwen3-8B, com as duas matrizes separadas, são 1,25 bilhão de pesos, 15% do total. Em modelo pequeno a tabela de consulta é uma fatia grande do orçamento.
Referências
- Vaswani, A. et al.. Attention Is All You Need (2017)arXiv:1706.03762
- Mikolov, T.; Chen, K.; Corrado, G.; Dean, J.. Efficient Estimation of Word Representations in Vector Space (2013)arXiv:1301.3781
- Press, O. e Wolf, L.. Using the Output Embedding to Improve Language Models (2016)arXiv:1608.05859
- Inan, H.; Khosravi, K.; Socher, R.. Tying Word Vectors and Word Classifiers: A Loss Framework for Language Modeling (2016)arXiv:1611.01462
- Geva, M.; Caciularu, A.; Wang, K. R.; Goldberg, Y.. Transformer Feed-Forward Layers Build Predictions by Promoting Concepts in the Vocabulary Space (2022)arXiv:2203.14680
- Belrose, N. et al.. Eliciting Latent Predictions from Transformers with the Tuned Lens (2023)arXiv:2303.08112
- Yang, Z.; Dai, Z.; Salakhutdinov, R.; Cohen, W. W.. Breaking the Softmax Bottleneck: A High-Rank RNN Language Model (2017)arXiv:1711.03953
- Demeter, D.; Kimmel, G.; Downey, D.. Stolen Probability: A Structural Weakness of Neural Language Models (2020)arXiv:2005.02433
- Dar, G.; Geva, M.; Gupta, A.; Berant, J.. Analyzing Transformers in Embedding Space (2022)arXiv:2209.02535