Antevisão · Latent Rehearsal
01

O tokenizador
próprio

Por que 16 mil tokens servem melhor a este corpus que 50 mil, o que ganhamos piorando os números de propósito, e o efeito colateral que não estava no plano.

Apostila 01 Pré-requisito: apostila 01 do curso GPT-2

1 O imposto que você paga por não ser inglês

O BPE do GPT-2 foi treinado no WebText: 40 GB de páginas em inglês. O algoritmo, como vimos no curso anterior, escolhe os pedaços que aparecem muito. Em inglês, tion aparece muito. Em português, ção aparecia pouco naquele corpus — então ele não virou token.

A consequência é cirúrgica. Veja a palavra mais banal do português técnico:

'ação'          nosso 1: ['ação']
                gpt2  3: ['a', 'ç', 'ão']

'implementação' nosso 3: ['im', 'plement', 'ação']
                gpt2  5: ['im', 'plement', 'a', 'ç', 'ão']

Repare no detalhe: o GPT-2 conhece plement. Ele aprendeu a raiz latina pelo inglês implementation. Mas na hora do sufixo, ele quebra o ç sozinho — porque a cedilha, para ele, é um caractere estranho que aparece em textos estranhos.

Por que isso é caro, e não só feio

Cada token custa três coisas: uma posição no contexto (que é finito), uma passada pela atenção (cujo custo é quadrático no número de posições), e um passo de geração (que é serial — 93,3% do tempo de uma requisição, como medimos na apostila 08).

Um texto em português que custa 1,6× mais tokens custa 1,6× mais contexto, ~2,5× mais atenção e 1,6× mais tempo para gerar. O modelo não fica só mais caro: ele fica com menos memória útil, porque o mesmo assunto ocupa mais espaço da janela.

2 As quatro decisões

Treinamos um BPE próprio sobre o nosso corpus — português, inglês e código. Quatro escolhas separam o nosso do original, e cada uma tem um custo.

Decisão 1 — vocabulário de 16 384, não 50 257

Contraintuitivo: vocabulário menor não deveria significar textos mais longos? Significa, tudo o mais constante. Mas tudo o mais não é constante, porque o nosso corpus é o corpus certo. Um vocabulário de 16 k ajustado ao seu texto bate um de 50 k ajustado a outro texto.

E há um segundo ganho, que só aparece quando você conta os parâmetros. A tabela de embedding tem V × d pesos. Com d=256:

Onde vão os parâmetros do modelo mini. A tabela de tokens não raciocina — ela só guarda um vetor por token.
VocabulárioTabelaBlocosTotal% em dicionário
50 257 (GPT-2)12,9 M3,2 M16,1 M80,1%
16 392 (nosso)4,2 M3,2 M7,4 M56,6%

Com o vocabulário do GPT-2, 80% do nosso modelo seria dicionário. Quem aprende é a coluna "blocos". Reduzir o vocabulário não economiza só memória — libera orçamento para as camadas, que é onde mora o raciocínio.

Decisão 2 — dígitos separados, um a um

Esta é a única mudança que piora uma métrica de propósito. O GPT-2 trata números como qualquer texto: os pedaços saem da frequência.

' 1234567'      nosso 8: [' ', '1', '2', '3', '4', '5', '6', '7']
                gpt2  3: [' 123', '45', '67']

Três tokens contra oito. O GPT-2 parece mais eficiente — e está, em bytes. Mas olhe o que ele fez: quebrou 1 234 567 em 123, 45, 67. Esses pedaços não têm nada a ver com a estrutura do número. O 45 ali são as centenas de milhar e as dezenas de milhar; noutro número, o mesmo token 45 serão as unidades.

O que isso faz com a aritmética

Para somar dois números, é preciso alinhar as casas. Se 45 significa uma coisa num número e outra noutro, o modelo precisa aprender a aritmética separadamente para cada padrão de corte do BPE — e os cortes mudam conforme o número.

Com dígitos separados, cada posição é explícita e sempre igual. É a escolha de Llama, Mistral e Qwen, e ajuda a explicar por que eles fazem contas melhor que o GPT-2 em tamanhos comparáveis.

Pagamos +58,3% de tokens em texto com números por essa consistência. É um custo real, e a apostila 06 explica por que o aceitamos sem ter medido o benefício: porque medir exigiria treinar até o modelo saber somar, o que está muito acima do nosso orçamento atual. É uma aposta fundamentada na literatura, não um resultado nosso.

Decisão 3 — tokens de indentação

Código Python é indentação. Adicionamos tokens explícitos para 4, 8, 12 e 16 espaços:

'    return'    nosso 2: ['    ', 'return']
                gpt2  4: [' ', ' ', ' ', ' return']

O GPT-2 gasta um token por espaço. Num arquivo Python com aninhamento profundo, isso é metade do arquivo. Pior: o modelo precisa contar espaços para saber o nível de indentação, o que é exatamente o tipo de tarefa em que a atenção é ruim.

Decisão 4 — o pré-tokenizador em três estágios

tok.pre_tokenizer = pre_tokenizers.Sequence([
    pre_tokenizers.Split(pattern=Regex(r"'s|'t|'re|…| ?\p{L}+| ?\p{N}+|…"),
                         behavior="isolated"),
    pre_tokenizers.Digits(individual_digits=True),   # a decisão 2
    pre_tokenizers.ByteLevel(add_prefix_space=False, use_regex=False),
])

A ordem importa. O Split separa palavras de pontuação; o Digits quebra os números antes do BPE poder fundi-los; o ByteLevel garante que qualquer byte seja representável — nenhum <UNK>, nunca.

3 O resultado, medido

Mesmo texto, os dois tokenizadores. Negativo é melhor para nós.
AmostraNossoGPT-2Diferença
Português corrente1121−47,6%
Português com acentos415−73,3%
Código Python2225−12,0%
Inglês990,0%
Com números1912+58,3%

A linha dos acentos é a mais reveladora: "ação coração informação atenção" custa 4 tokens para nós e 15 para o GPT-2. Quase quatro vezes. E o inglês empata — com um vocabulário três vezes menor, o que já é um resultado por si.

Onde isso aparece de verdade

Tokens são meio, não fim. O que importa é se o modelo prevê melhor. A métrica honesta entre tokenizadores diferentes é bits por caractere — perplexidade é medida por token, e comparar PPL entre vocabulários diferentes não significa nada.

bits/caractere, menor é melhor. Nosso modelo tem 7,4 M de parâmetros; o GPT-2, 124 M.
ModeloPortuguêsInglêsCódigo
nosso mini (7,4 M)2,4062,0382,405
gpt2 (124 M)3,1391,2611,864

Em português, 7,4 milhões de parâmetros gastam menos bits que 124 milhões — 23% menos bits, com 17× menos modelo. Em inglês e código o GPT-2 vai bem melhor, e faz sentido: ele viu ~10 bilhões de tokens contra os nossos 5,7 milhões.

Leia a tabela inteira, não só a primeira coluna

Seria fácil anunciar "nosso modelo de 7 M supera o GPT-2" e parar aí. Seria desonesto. A vantagem existe só onde o tokenizador cobra a diferença, e some onde o GPT-2 tem corpus. O que a tabela prova não é que somos melhores — é que tokenização mal ajustada custa mais que 17× de parâmetros.

4 O efeito colateral que não estava no plano

Ao medir a velocidade de treino, apareceu algo que não esperávamos: o modelo com vocabulário de 16 k treina a 4 000 tokens/s, contra 857 tok/s da medição anterior com 50 k. Cinco vezes mais rápido.

A causa está na última camada. A projeção para os logits é uma multiplicação d × V — e ela roda para cada posição da sequência. Com V três vezes menor, a matriz mais cara do modelo encolhe três vezes.

Analogia

É como um exame de múltipla escolha. Responder uma questão com 50 mil alternativas não é 3× mais lento que uma com 16 mil por causa do raciocínio — o raciocínio é o mesmo. É mais lento porque você precisa ler todas as alternativas antes de escolher. O modelo faz isso a cada token gerado.

Consequência prática: o modelo mini passou de "dias de CPU" para ~4 horas. Uma decisão tomada por qualidade de tokenização acabou sendo, também, a maior otimização de velocidade do projeto. Não previmos isso — e é por isso que medimos em vez de estimar.

5 O que ficou por fazer

  1. Não medimos o ganho dos dígitos separados. Sabemos o custo (+58,3% de tokens); o benefício em aritmética exige um modelo grande o bastante para somar. Está registrado como aposta, não como resultado.
  2. O vocabulário de 16 384 não foi otimizado. Escolhemos por argumento (parâmetros × cobertura), não por varredura. 8 k ou 32 k poderiam ser melhores.
  3. Se a mistura do corpus mudar, o tokenizador precisa ser retreinado. Ele foi ajustado a 40% PT / 30% código / 30% EN. Mudar para um corpus focado em código sem retreinar desperdiça o ganho de −47,6% em português.
Perguntas em aberto

Com o texto virando números do jeito certo, a apostila 02 monta o modelo —
nas duas versões, a de 2019 e a de hoje, no mesmo arquivo para a diferença ser legível.