Amostragem por Núcleo (Amostragem Top-p)
Visão geral
Amostragem por núcleo (nucleus sampling), também chamada de amostragem top‑p (top‑p sampling), é uma estratégia de decodificação probabilística (probabilistic decoding strategy) para geração de texto em modelos de linguagem de grande porte (large language model, LLM). A cada etapa de geração, em vez de sempre escolher o único próximo token mais provável (decodificação gulosa (greedy decoding)) ou buscar uma sequência globalmente de alta probabilidade (busca em feixe (beam search)), a amostragem por núcleo:
- Ordena os próximos tokens candidatos por probabilidade (da maior para a menor)
- Seleciona o menor conjunto de tokens cuja massa de probabilidade acumulada (cumulative probability mass) seja pelo menos um limiar p (por exemplo, 0,9)
- Amostra o próximo token apenas desse conjunto (após renormalizar as probabilidades (renormalizing probabilities))
A ideia central é amostrar a partir de um conjunto dinâmico de tokens plausíveis: quando o modelo está confiante, o núcleo é pequeno; quando o modelo está incerto, o núcleo se expande. Isso frequentemente produz um texto mais diverso do que a decodificação gulosa/busca em feixe, mantendo-se mais coerente do que a amostragem irrestrita a partir de todo o vocabulário.
A amostragem por núcleo é amplamente usada em APIs e aplicações de LLMs porque oferece um equilíbrio prático entre:
- Diversidade / criatividade
- Coerência / correção
- Evitar loops repetitivos “travados” que podem ocorrer com decodificação determinística (deterministic decoding)
Este artigo situa a amostragem por núcleo entre outras estratégias de decodificação em Estratégias de Decodificação e a contrasta com abordagens como Busca em Feixe.
Contexto: distribuições do próximo token
LLMs geram texto de forma autorregressiva (autoregressively): eles predizem o próximo token dado o prompt e os tokens gerados anteriormente. Internamente, o modelo produz logits (logits) (z \in \mathbb{R}^{V}) sobre o vocabulário (vocabulary) de tamanho (V). Eles são convertidos em probabilidades via a função softmax (softmax):
[ P(t_i \mid \text{context}) = \frac{e^{z_i}}{\sum_{j=1}^{V} e^{z_j}} ]
Um método de decodificação decide como escolher o próximo token a partir dessa distribuição e então repete.
O que a amostragem por núcleo (top‑p) faz
Definição
Dada a distribuição de probabilidade do próximo token (P) sobre tokens, a amostragem por núcleo seleciona o menor conjunto (S) tal que:
- Os tokens em (S) são os tokens mais prováveis (ordenados por (P))
- A probabilidade acumulada de (S) é pelo menos (p):
[ \sum_{t \in S} P(t) \ge p ]
Então, ela amostra o próximo token a partir de (S) usando a distribuição renormalizada (renormalized distribution):
[ P'(t) = \begin{cases} \frac{P(t)}{\sum_{u \in S} P(u)} & \text{if } t \in S \ 0 & \text{otherwise} \end{cases} ]
Por que “menor conjunto” importa
Como você pega o menor conjunto que excede (p), o tamanho do núcleo se adapta à confiança do modelo:
- Se o modelo está confiante (distribuição bem concentrada), poucos tokens podem já exceder (p) → núcleo pequeno
- Se o modelo está incerto (distribuição mais uniforme), muitos tokens são necessários para alcançar (p) → núcleo grande
Essa é a principal diferença em relação à amostragem top‑k (top‑k sampling), que sempre usa exatamente (k) candidatos independentemente da confiança.
Algoritmo (passo a passo)
Em cada etapa de decodificação:
- Calcule probabilidades sobre o vocabulário:
probs = softmax(logits) - Ordene tokens por probabilidade decrescente
- Calcule somas cumulativas sobre as probabilidades ordenadas
- Encontre o índice de corte em que a probabilidade cumulativa ultrapassa
ppela primeira vez - Mantenha os tokens até esse corte (o “núcleo”)
- Renormalize as probabilidades dentro do núcleo
- Amostre um token do núcleo
- Anexe o token e repita
Implementação de referência (estilo Python)
import numpy as np
def softmax(x):
x = x - np.max(x)
ex = np.exp(x)
return ex / np.sum(ex)
def top_p_sample(logits, p=0.9, rng=np.random):
probs = softmax(logits)
# sort tokens by probability
sorted_idx = np.argsort(probs)[::-1]
sorted_probs = probs[sorted_idx]
# nucleus cutoff
cumsum = np.cumsum(sorted_probs)
cutoff = np.searchsorted(cumsum, p) # first index where cumsum >= p
cutoff = max(cutoff, 0)
nucleus_idx = sorted_idx[:cutoff+1]
nucleus_probs = probs[nucleus_idx]
nucleus_probs = nucleus_probs / nucleus_probs.sum()
# sample within nucleus
sampled = rng.choice(nucleus_idx, p=nucleus_probs)
return sampled
Notas:
- Isso garante que pelo menos um token esteja no núcleo.
- Em sistemas de produção, isso é altamente otimizado (ordenar um vocabulário inteiro a cada etapa é caro); implementações frequentemente usam ordenação parcial ou combinam com limites de top‑k.
Exemplo trabalhado (intuitivo)
Suponha que as probabilidades do próximo token do modelo sejam:
| Token | Probabilidade |
|---|---|
| “the” | 0.40 |
| “a” | 0.20 |
| “an” | 0.10 |
| “this” | 0.08 |
| “my” | 0.07 |
| others (many) | remaining 0.15 |
Se (p = 0.90), acumulamos a partir do topo:
- “the”: 0.40
- “a”: 0.60
- “an”: 0.70
- “this”: 0.78
- “my”: 0.85
- Ainda precisamos de mais 0.05 → adicionamos tokens adicionais até que o acumulado ≥ 0.90
Então o núcleo pode incluir, por exemplo, os 8–20 principais tokens, dependendo da cauda. Depois, amostramos entre eles proporcionalmente às suas probabilidades.
Se, em vez disso, o modelo estivesse muito confiante:
- “the”: 0.92
- todo o resto: 0.08
Então, com (p = 0.90), o núcleo conteria apenas um token (“the”), tornando a etapa determinística.
Como a amostragem por núcleo se compara a outras estratégias de decodificação
Decodificação gulosa (argmax)
A decodificação gulosa seleciona o token mais provável a cada etapa.
- Prós: determinística, frequentemente coerente, boa para tarefas factuais ou estruturadas quando o modelo está bem alinhado
- Contras: pode ser sem graça, pode cair em repetição, e pode perder conclusões globais melhores porque nunca explora alternativas
Relação com top‑p:
- Top‑p se torna semelhante à decodificação gulosa quando a distribuição é muito concentrada (ou quando a temperatura é próxima de zero), porque o núcleo pode conter apenas o token do topo.
Busca em feixe
A busca em feixe mantém múltiplas hipóteses parciais (um “feixe”) e as expande, selecionando sequências com alta probabilidade total. Veja Busca em Feixe.
- Prós: encontra sequências de alta probabilidade; boa em tarefas como tradução automática (historicamente)
- Contras para geração aberta: frequentemente produz texto genérico, repetitivo ou excessivamente “seguro” porque otimiza verossimilhança, não o quão interessante é; além disso, é mais cara
Top‑p vs busca em feixe:
- A busca em feixe é um procedimento de busca que otimiza a probabilidade da sequência.
- Top‑p é amostragem a partir de uma distribuição truncada, priorizando diversidade enquanto permanece dentro da massa provável.
Amostragem top‑k
A amostragem top‑k mantém os (k) tokens mais prováveis e amostra entre eles.
- Prós: simples; limita a aleatoriedade ao restringir candidatos
- Contras: (k) fixo é uma abordagem pouco sutil:
- Quando o modelo está confiante, (k) pode incluir muitos tokens desnecessários de baixa probabilidade (adicionando ruído)
- Quando o modelo está incerto, (k) pode ser pequeno demais (forçando o modelo a escolhas arbitrárias)
Top‑p resolve isso ao tornar o tamanho do conjunto de candidatos adaptativo.
Amostragem pura (sem truncamento)
A amostragem a partir de todo o vocabulário raramente é usada diretamente porque a cauda longa contém muitos tokens com probabilidades minúsculas, porém não nulas, incluindo:
- palavras fora de tópico
- continuações incoerentes
- falhas de formatação
- tokens raros que desestabilizam a saída
Top‑p é uma forma controlada de evitar essa cauda sem precisar de um (k) fixo.
O papel da temperatura (e como ela interage com top‑p)
Escalonamento de temperatura
Antes do softmax, muitos sistemas dividem os logits pela temperatura (temperature) (T):
[ P_T(t_i) = \text{softmax}(z_i / T) ]
- (T) menor (< 1) → a distribuição fica mais “afiada” (mais concentrada)
- (T) maior (> 1) → a distribuição fica mais “plana” (mais aleatória)
Interação entre temperatura e top‑p
A temperatura altera a distribuição de probabilidade, e então o top‑p a trunca. Juntas, elas moldam fortemente a qualidade da saída:
Temperatura baixa + p alto
- Muitas vezes próximo da decodificação gulosa
- Alta coerência, baixa diversidade
- Ainda pode repetir se o modelo entrar em um loop
Temperatura moderada + p em torno de 0.9–0.95
- Configuração “equilibrada” comum para linguagem natural
- Melhor variedade de formulações, geralmente coerente
Temperatura alta + p alto
- O núcleo pode ficar grande (uma distribuição mais plana significa que mais tokens são necessários para atingir o p cumulativo)
- A saída pode ficar criativa, mas com risco de incoerência, desvio de tópico ou afirmações contraditórias
Temperatura alta + p baixo
- Você achata a distribuição e então a trunca fortemente
- Isso pode gerar um comportamento “excêntrico, mas contido”, às vezes útil para variação estilística sem caos total
Intuição prática
- A temperatura controla o quão “espalhada” a massa de probabilidade está
- Top‑p controla quanta dessa massa você está disposto a considerar
Assim, você pode pensar na temperatura como reformando a distribuição e no top‑p como cortando a cauda.
Efeitos sobre diversidade, coerência e repetição
Diversidade
- Aumentar p geralmente aumenta a diversidade (mais tokens candidatos).
- Aumentar a temperatura também aumenta a diversidade (as probabilidades ficam mais próximas entre si).
Porém, diversidade nem sempre é desejável — especialmente para tarefas que exigem exatidão (matemática, código, QA factual).
Coerência e correção
- p mais baixo reduz a exposição a tokens de baixa probabilidade, o que frequentemente melhora a coerência.
- temperatura mais baixa tende a manter as gerações mais próximas da continuação mais provável, melhorando a gramática e a consistência local.
Mas aleatoriedade excessivamente baixa pode deixar o modelo:
- repetitivo
- formal ou genérico demais
- frágil (ele se compromete cedo com uma formulação subótima e não consegue se recuperar)
Repetição
A repetição em saídas de LLMs tem múltiplas causas (dinâmica de treinamento, artefatos de tokenização, máximos locais de probabilidade). A decodificação influencia isso:
- A decodificação gulosa/busca em feixe pode amplificar a repetição porque, quando um padrão repetitivo se torna ligeiramente favorecido, a decodificação determinística continua reforçando-o.
- A amostragem por núcleo pode reduzir a repetição ao ocasionalmente escolher tokens alternativos — mas se (p) for baixo demais, o núcleo ainda pode ser dominado por uma sequência de tokens repetitiva.
- Temperatura muito alta às vezes pode aumentar repetição caótica (não a mesma frase, mas loops desorganizados).
Na prática, a repetição muitas vezes é mitigada com técnicas adicionais aplicadas sobre top‑p:
- penalidades de repetição (repetition penalties), isto é, penalidades nos logits (logit penalties)
- penalidades de frequência/presença (frequency/presence penalties)
- restrições de n‑gramas sem repetição (no-repeat n-gram constraints)
- sequências de parada (stop sequences) e limites máximos de tokens (max token limits)
Top‑p é uma alavanca, não a única.
Escolhas típicas de parâmetros
Elas variam conforme o modelo e a aplicação, mas pontos de partida comuns:
Chat geral / assistentes:
temperature: 0.7–1.0top_p: 0.9–0.95
Resumos factuais / determinísticos:
temperature: 0.0–0.3top_p: 0.8–0.95 (frequentemente menos importante se a temperatura for muito baixa)
Escrita criativa / brainstorming:
temperature: 0.9–1.3top_p: 0.92–0.98
Geração de código:
temperature: 0.0–0.4 (com frequência)top_p: 0.8–0.95
Código tolera menos aleatoriedade “interessante”; pequenos desvios podem quebrar sintaxe ou lógica.
Um erro comum é aumentar ambos os controles (temperatura alta e top_p muito alto) e depois se surpreender com a incoerência.
Padrões práticos de aplicação
Padrão 1: Respostas de assistente “estáveis, mas não robóticas”
Objetivo: evitar formulações repetitivas mantendo precisão.
- Comece com
top_p = 0.9etemperature = 0.7 - Se as respostas parecerem formulaicas demais: aumente a temperatura para ~0.9 ou aumente o top_p para 0.95
- Se as respostas começarem a derivar ou alucinar mais: reduza a temperatura primeiro (frequentemente mais eficaz do que reduzir p)
Padrão 2: Variantes para brainstorming
Objetivo: muitas continuações plausíveis diferentes.
- Use
temperature ~ 1.0–1.2,top_p ~ 0.95–0.98 - Gere múltiplas amostras e selecione/classifique (possivelmente com um segundo modelo ou heurísticas)
Padrão 3: Completações curtas onde o risco de cauda é alto
Para completações muito curtas (títulos, frase única), um único token ruim pode arruinar a saída. Considere:
- Reduzir
top_p(por exemplo, 0.85–0.9) - Temperatura moderada (0.6–0.9)
Isso reduz a chance de tokens raros e estranhos.
Sutilezas e casos-limite
1) Tamanho grande do núcleo pode ser caro ou ruidoso
Quando a distribuição é plana (por exemplo, no começo da geração com um prompt aberto), alcançar (p=0.95) pode exigir milhares de tokens. Isso pode:
- aumentar a aleatoriedade
- às vezes reduzir o foco no tópico
- aumentar a computação (dependendo da implementação)
Por isso, muitos sistemas combinam a amostragem por núcleo com um limite de top‑k (por exemplo, “top‑p, mas não mais do que top‑k=200”).
2) Efeitos da tokenização
LLMs operam sobre tokens, não palavras. Decisões de amostragem podem ser afetadas por fronteiras de token:
- fragmentos raros de subpalavra (subword) podem aparecer na cauda
- tokens de pontuação e de espaço em branco (whitespace tokens) podem influenciar a formatação Top‑p ajuda excluindo grande parte da cauda, mas você ainda pode ver formatação estranha se seus parâmetros permitirem aleatoriedade demais.
3) Determinismo e reprodutibilidade
A amostragem por núcleo é estocástica (stochastic). Para saídas reprodutíveis, você precisa:
- uma semente aleatória (random seed) fixa
- versão fixa do modelo
- parâmetros de decodificação idênticos Mesmo assim, a inferência distribuída (distributed inference) pode introduzir pequenas não-determinismos dependendo do hardware e dos kernels.
4) Top‑p vs truncamento por “probabilidade mínima”
Algumas variantes mais novas truncam tokens abaixo de um limiar absoluto de probabilidade (às vezes chamado de min‑p). Diferentemente do top‑p, isso não garante uma massa de probabilidade fixa, e o comportamento difere quando as distribuições são planas. Top‑p continua sendo o método padrão de truncamento por “massa de probabilidade”.
Quando usar amostragem por núcleo
A amostragem por núcleo é um forte padrão para geração aberta, como:
- assistentes que devem soar naturais em vez de robóticos
- storytelling e diálogo
- ideação (variações de copy de marketing, brainstorming)
- qualquer cenário em que você queira uma boa resposta, mas não quer que seja a mesma resposta toda vez
Você pode preferir uma decodificação mais determinística (decodificação gulosa/temperatura baixa) quando:
- você precisa de consistência rigorosa (alguns cenários de código e matemática)
- você está produzindo texto sensível a conformidade, onde variabilidade aumenta risco
- você pretende verificar saídas e quer menos graus de liberdade
Resumo
- Amostragem por núcleo (top‑p) mantém o menor conjunto de tokens cuja massa de probabilidade acumulada excede p, e então amostra a partir desse conjunto.
- Em comparação com top‑k, ela adapta o tamanho do conjunto de candidatos à confiança do modelo, frequentemente melhorando o trade-off coerência–diversidade.
- Em comparação com decodificação gulosa e busca em feixe, ela introduz aleatoriedade controlada que pode reduzir a falta de variedade e, às vezes, reduzir repetição.
- A temperatura remodela a distribuição; top‑p a trunca. Juntas, elas governam criatividade, coerência e risco de cauda.
- Padrões práticos frequentemente ficam em torno de
top_p ≈ 0.9–0.95comtemperature ≈ 0.7–1.0, ajustados conforme as exigências da tarefa.
Para uma estratégia de decodificação contrastante que otimiza a verossimilhança da sequência via busca em vez de amostragem, veja Busca em Feixe.