Antevisão · Latent Rehearsal
18

Procurar melhor
não conserta a energia

A apostila 16 mostrou que a busca por energia não achava o mínimo e criou uma busca exata. Esta mede o que a busca exata faz com o texto, e o resultado aponta para outro lugar: a troca entre seguir o rumo e escrever algo plausível é decidida pela energia, não por onde se procura.

Apostila 18 Pré-requisito: 16 (o mínimo e o volume) e 12 (custos e modos de inferência)

1 A pergunta que a 16 deixou

O gerador, no modo energia, escolhe cada token em dois passos. Primeiro monta uma lista curta de candidatos. Depois imagina, no espaço latente, para onde cada candidato levaria o texto, e dá a cada um uma energia com dois termos: o quanto o estado previsto se afasta do rumo pedido e o quanto o token é improvável segundo a própria cabeça de tokens.

E(a) = 1 − cos(Pred(zt, ea), rumo) + γ · (−log p(a))

A apostila 16 mostrou que a lista curta — os 8 tokens mais prováveis — muitas vezes não contém o token de menor energia: com γ = 0 isso acontece em todas as 96 posições medidas. A resposta foi um modo novo, todos, que calcula a energia de cada um dos 16.392 tokens do vocabulário e pega os de menor energia. Ficou uma pergunta, a primeira da lista de perguntas em aberto daquela apostila: achar o mínimo de verdade melhora o texto, ou só abaixa a energia?

2 Um defeito encontrado no caminho

A primeira medida saiu estranha. Com γ = 0,1, o modo todos deu afinidade ao rumo de 0,780, bem acima de tudo o que a apostila 12 tinha medido, mas com perplexidade 491; no modo energia sem cabeça de custo a perplexidade chegou a 2.098. A varredura da 16 dizia que, com γ = 0,1, o mínimo verdadeiro já está entre os 8 mais prováveis em 85% das posições. Uma busca que acha o mínimo não deveria produzir texto tão pior que a lista curta.

O motivo estava no código. A função que ordena o vocabulário (_todos_por_energia, em server/ours.py) usava só o termo do rumo e deixava de fora o termo γ · (−log p). Os oito candidatos eram, então, os mínimos do rumo puro — os fragmentos de sílaba que a apostila 16 §5 mostrou que nenhuma política escolheria —, e o γ só reordenava esse conjunto. Com γ = 0 as duas ordenações coincidem, e por isso as medidas da 16, feitas pelo model/inference.py com a energia inteira, não mudam.

A ordenação agora usa a energia inteira, a mesma que o inference.py mede. Todos os números abaixo são depois do conserto.

3 Três lugares para procurar, a mesma troca

Para ver se o que importa é onde se procura, comparamos três conjuntos de busca, sempre escolhendo pela mesma energia:

  1. política: os 8 tokens mais prováveis (o comportamento de sempre);
  2. vocabulário inteiro: os 16.392 tokens (o modo todos);
  3. núcleo: só os tokens que, somados do mais provável para baixo, cobrem uma fração da probabilidade — a mesma ideia da amostragem por núcleo (top-p). A busca é exata dentro dele. É o modo novo nucleo, com a massa em nucleus_mass.

A ideia do núcleo era manter uma restrição de plausibilidade firme, como a da lista curta, e procurar o mínimo exato dentro dela.

Tabela de modos (model/modes.py), modelo mini-moderno-reg1-wm1-sz1-duelo, 4 prompts × 32 tokens, rumo "futebol gol campeonato". Afinidade: probabilidade de o texto ser sobre o rumo, dada por uma cabeça de custo de outro modelo (reg1-lat1o), para o gerador não julgar a si mesmo; maior = mais no rumo. PPL: perplexidade do texto medida pelo próprio gerador; menor = mais plausível. Guardrail: fração de tokens numéricos no prompt "Em 1999, o total foi de" com a cabeça "sem-numeros" aplicada ao estado real, 3 sementes. Uma semente de geração nas duas primeiras colunas.
onde procuraγenergia: afinidadePPLcabeça + estado real: afinidadePPLguardrail: dígitosPPL
sem leme (livre)—0,25648,50,25648,540,6%10,7
política, top-80,10,20019,80,35536,727,6%26,1
núcleo, 50% da massa0,10,450694,50,48084,20,0%75,6
núcleo, 80% da massa0,10,351421,80,47683,40,0%247,2
vocabulário inteiro0,10,351421,80,47683,40,0%247,2
política, top-800,357293,10,48882,40,0%144,7
núcleo, 50% da massa00,2501.008,40,751639,00,0%275,7
vocabulário inteiro00,2645.363,40,841853,50,0%625,3

A coluna do meio, a da melhor configuração do leme (cabeça de custo aplicada ao estado real), é a que responde. As quatro linhas em negrito caem praticamente no mesmo ponto: afinidade entre 0,476 e 0,488, perplexidade entre 82 e 84. Três delas são as três buscas com γ = 0,1; a quarta é a lista curta de sempre com γ = 0. Procurar no núcleo ou no vocabulário inteiro, com γ = 0,1, leva o texto exatamente para onde já se chegava baixando o γ.

Dito de outro jeito: existe uma troca entre seguir o rumo e escrever texto plausível. Baixar o γ anda sobre essa troca; procurar melhor também anda sobre ela, e não a desloca. Nenhuma das buscas comprou mais rumo pelo mesmo preço em perplexidade.

Uma exceção pequena merece registro: no guardrail, o núcleo de 50% zera os dígitos com perplexidade 75,6, contra 144,7 da lista curta com γ = 0 e 247,2 do vocabulário inteiro. É uma medida de 3 sementes num prompt só, e vale como pista para repetir, não como resultado.

4 Por que as buscas empatam

As linhas do núcleo de 80% e do vocabulário inteiro não são parecidas: são idênticas, até a terceira casa. Isso não é defeito; é o que duas medidas já feitas preveem juntas.

A primeira é a varredura de γ, feita com o model/inference.py sobre 96 posições do conjunto de validação. Ela diz com que frequência o token de menor energia está entre os k mais prováveis da política:

Cobertura do top-k da política sobre o mínimo exato da energia, rumo "futebol gol campeonato", 6 sequências × 16 posições. "Ações a ≤ 5%": quantos tokens ficam a menos de 5% da menor energia (as "múltiplas respostas" da apostila 16 §5). As linhas γ = 0, 0,1 e 1 repetem a 16 §4 número por número.
γk = 1k = 8k = 32k = 128energia perdida no top-8ações a ≤ 5%
00,0%0,0%0,0%9,4%+35,9%35,5
0,010,0%2,1%10,4%21,9%+22,4%43,0
0,021,0%9,4%24,0%47,9%+13,8%40,4
0,0521,9%61,5%83,3%92,7%+3,9%11,1
0,133,3%85,4%97,9%100,0%+1,2%4,1
0,256,2%96,9%100,0%100,0%+0,1%2,3
0,583,3%100,0%100,0%100,0%0,0%1,5
190,6%100,0%100,0%100,0%+0,0%1,4

A segunda é o tamanho do núcleo. A política do mini é plana: a probabilidade se espalha por muitos tokens.

Quantos tokens a política precisa para cobrir cada fração da probabilidade, 8 sequências × 64 posições da validação.
massa do núcleomedianamédia90% das posições até
50%71198572
80%2.0172.1484.427
90%5.3675.0798.062
95%8.8188.25310.996

Juntas, elas explicam o empate. Com γ = 0,1, o token de menor energia está entre os 128 mais prováveis em todas as posições. Um núcleo de 80% tem cerca de 2.000 tokens, e o de 95%, quase 9.000; os dois contêm os mesmos oito tokens de menor energia que o vocabulário inteiro. As buscas são diferentes, os candidatos que elas devolvem não são.

5 O que segura a plausibilidade é a posição, não a massa

A tabela da §3 tem, então, uma leitura mais precisa do que "a lista curta é melhor". O que faz a lista curta produzir texto plausível é o corte por posição: nenhum token abaixo do oitavo mais provável entra. Os tokens que a energia prefere com γ = 0,1 estão quase sempre entre a 9ª e a 128ª posição da política — dentro de qualquer núcleo razoável, mas fora da lista curta —, e é deles que vem a perplexidade de 83.

O termo γ · (−log p) não imita esse corte. Um token na posição 50 tem probabilidade baixa, mas não baixa a ponto de o termo pesar mais que o ganho no rumo quando γ é pequeno. Com γ alto, o termo pesa o bastante, e a energia volta a ser quase a própria política (a 16 §4 mostrou isso com γ = 1). Na nossa energia, a plausibilidade está num termo contínuo, e o que funcionou foi um corte.

O que esta apostila mostra

Procurar melhor não desloca a troca entre rumo e plausibilidade. Com três buscas diferentes — a exata no vocabulário, a exata dentro do núcleo e a lista curta com γ menor —, o texto cai no mesmo ponto. O que decide onde o texto cai é a energia: com γ baixo ela considera barato o que a política acha pouco provável. A busca exata continua útil para medir quanto a lista curta deixa de fora (apostila 16); para gerar texto melhor, a peça a mexer é a energia.

6 O que mudou no código

Mudanças aditivas: o padrão do gerador continua sendo a lista curta da política.
ondeo que mudou
server/ours.py, _todos_por_energiaconserto: a ordenação do vocabulário usa a energia inteira, com γ · (−log p). Com γ = 0 nada muda
server/ours.py, _nucleo_por_energiamodo de candidatos novo, nucleo (nucleus): busca exata só entre os tokens do núcleo da política; massa em nucleus_mass (padrão 0,95); a trajetória registra o tamanho do núcleo em cada passo
model/modes.py--candidates nucleo e --nucleus-mass

7 Limites desta medida

Perguntas em aberto
Referências

As fontes das ideias usadas aqui. Os números foram medidos no projeto.

  1. LeCun, Y., Chopra, S., Hadsell, R., Ranzato, M. e Huang, F. J. (2006). A Tutorial on Energy-Based Learning. Em Predicting Structured Data, MIT Press. yann.lecun.com/exdb/publis/pdf/lecun-06.pdf
  2. LeCun, Y. (2022). A Path Towards Autonomous Machine Intelligence. OpenReview. openreview.net/forum?id=BZ5a1r-kVsf
  3. Holtzman, A., Buys, J., Du, L., Fang, M. e Choi, Y. (2020). The Curious Case of Neural Text Degeneration. ICLR 2020 (amostragem por núcleo, top-p). arXiv:1904.09751
  4. Apostila 16 desta coleção, O mínimo e o volume: cobertura, energia perdida e a busca exata.

Medido na CPU em 17/09/2026. Dados em out/cpu_1709/.