Phase 12 - Lesson 01

Vision Transformers e a Primitiva de Patch-Token

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Antes de qualquer processamento multimodal, uma imagem precisa se tornar uma sequência de tokens que um transformer consiga consumir. O artigo original do ViT de 2020 resolveu isso com patches de 16x16 pixels, uma projeção linear e um embedding de posição. Cinco anos depois, todo modelo de fronteira de 2026 (Claude Opus 4.7 em 2576px nativo, Gemini 3.1 Pro, Qwen3.5-Omni) ainda começa dessa maneira — o codificador mudou de ViT para DINOv2 e depois para SigLIP 2, tokens de registro foram adicionados e o esquema posicional passou a ser 2D-RoPE, mas a primitiva se manteve. Esta lição detalha o pipeline de patch-token de ponta a ponta e o constrói em Python nativo para que o restante da Fase 12 tenha um modelo mental concreto para "tokens visuais".

Tipo: Aprender Linguagens: Python (biblioteca padrão, tokenizador de patches + calculadora de geometria) Pré-requisitos: Fase 7 (Transformers), Fase 4 (Visão Computacional) Tempo: ~120 minutos

Objetivos de Aprendizado

  • Converter uma imagem HxWx3 em uma sequência de tokens de patches com codificação posicional correta.
  • Calcular o comprimento da sequência, a quantidade de parâmetros e os FLOPs para um ViT com base em (tamanho do patch, resolução, dimensão oculta, profundidade).
  • Nomear as três melhorias que levaram o ViT da pesquisa em 2020 para a produção em 2026: pré-treinamento autossupulsionado (DINO / MAE), tokens de registro e empacotamento de resolução nativa.
  • Escolher entre CLS pooling, mean pooling e tokens de registro para uma tarefa downstream.

O Problema

Os transformers operam em sequências de vetores. O texto já é uma sequência (bytes ou tokens). Uma imagem é uma grade 2D de pixels com três canais de cores — não uma sequência. Se você planificar todos os pixels, uma imagem RGB de 224x224 se torna 150.528 tokens, e a autoatenção (self-attention) com esse comprimento é inviável (quadrática no comprimento da sequência).

As abordagens anteriores a 2020 acoplavam um extrator de recursos CNN na entrada: a ResNet gera um mapa de recursos de 7x7 com vetores de dimensão 2048, alimentando esses 49 tokens no transformer. Isso funciona, mas herda os vieses das CNNs (equivariância de translação, campos receptivos locais) e perde o apetite por escala do transformer.

Dosovitskiy et al. (2020) fizeram a pergunta direta: e se pularmos a CNN? Dividir a imagem em patches de tamanho fixo (por exemplo, 16x16 pixels), projetar linearmente cada patch em um vetor, adicionar um embedding posicional e alimentar a sequência em um transformer clássico. Na época, isso era uma heresia — visão computacional sem convoluções. Com dados suficientes (JFT-300M, depois LAION), ele superou a ResNet no ImageNet e continuou melhorando.

Em 2026, a primitiva ViT é a base inquestionável. A torre de visão de cada VLM open-weights é algum descendente (DINOv2, SigLIP 2, CLIP, EVA, InternViT). A questão não é mais "devemos usar patches?", mas sim "qual tamanho de patch, qual cronograma de resolução, qual objetivo de pré-treinamento, qual codificação posicional".

O Conceito

Patches como tokens

Dada uma imagem x com formato (H, W, 3) e um tamanho de patch P, você divide a imagem em uma grade de (H/P) x (W/P) patches que não se sobrepõem. Cada patch é um cubo de pixels de tamanho P x P x 3. Planifique cada cubo para um vetor de tamanho 3 P^2. Aplique uma projeção linear compartilhada W_E com formato (3 P^2, D) para mapear cada patch para a dimensão oculta D do modelo.

Para a configuração canônica do ViT-B/16:

  • Resolução 224, tamanho do patch 16 → grade 14x14 → 196 tokens de patch.
  • Cada patch consiste em 16 x 16 x 3 = 768 valores de pixels, projetados para D = 768.
  • Adicione um token [CLS] aprendível → comprimento de sequência de 197.

A projeção de patches é matematically idêntica a uma convolução 2D com tamanho de kernel P, stride P e D canais de saída. É assim que o código de produção realmente a implementa — nn.Conv2d(3, D, kernel_size=P, stride=P). O enquadramento de "projeção linear" é conceitual; o enquadramento de kernel é eficiente.

Embeddings posicionais

Os patches não possuem ordem intrínseca — o transformer os vê como um conjunto desordenado. Os primeiros ViTs adicionavam um embedding posicional 1D aprendível (um vetor de dimensão 768 por posição, 197 deles). Isso funciona, mas vincula o modelo à resolução de treinamento: na inferência, você precisa interpolar a tabela de posições se alterar a grade.

Os backbones de visão modernos usam 2D-RoPE (M-RoPE do Qwen2-VL, o padrão do SigLIP 2) ou posições 2D fatoradas. O 2D-RoPE rotaciona os vetores de consulta (query) e chave (key) com base no índice (linha, coluna) do patch, permitindo que o modelo infira a posição 2D relativa a partir do ângulo de rotação. Sem tabela de posições. O modelo lida com tamanhos de grade arbitrários durante a inferência.

Token CLS, saída agregada (pooled output) e tokens de registro

Qual é a representação ao nível da imagem? Três opções coexistem:

  1. Token [CLS]. Precede a sequência de patches com um vetor aprendível. Após todos os blocos do transformer, o estado oculto do token CLS é a representação da imagem. Herdado do BERT. Usado pelo ViT original e pelo CLIP.
  2. Média simples (Mean pool). Faz a média dos estados ocultos de saída dos tokens de patches. Usado pelo SigLIP, DINOv2 e pela maioria dos VLMs modernos.
  3. Tokens de registro (Register tokens). Darcet et al. (2023) observaram que ViTs treinados sem um token de descarte (sink token) explícito desenvolvem patches "artefatos" de norma alta que monopolizam a autoatenção. A adição de 4 a 16 tokens de registro aprendíveis absorve essa carga e melhora a qualidade da predição densa (segmentação, profundidade). Tanto o DINOv2 quanto o SigLIP 2 são fornecidos com registros.

A escolha é importante para tarefas posteriores (downstream). O CLS funciona bem para classificação. Para VLMs que alimentam tokens de patches em um LLM, você ignora completamente a agregação (pooling) — cada patch se torna um token de entrada para o LLM. Os registros são descartados antes do envio (eles servem como andaime, não como conteúdo).

Pré-treinamento: supervisionado, contrastivo, mascarado, autodestilado

O ViT de 2020 foi pré-treinado com classificação supervisionada no JFT-300M. Rapidamente suplantado por:

  • CLIP (2021): contraste imagem-texto em 400 milhões de pares. Lição 12.02.
  • MAE (2021, He et al.): mascara 75% dos patches, reconstrói pixels. Autossupervisionado, funciona em imagens puras.
  • DINO (2021) / DINOv2 (2023): autodistilação com estudante-professor, sem rótulos, sem legendas. O DINOv2 ViT-g/14 de 2023 é o backbone puramente visual mais forte e o padrão para casos de uso de "recursos densos" (dense features).
  • SigLIP / SigLIP 2 (2023, 2025): CLIP com uma perda sigmoide e NaFlex para proporção de tela nativa. A torre de visão dominante nos VLMs abertos de 2026 (Qwen, Idefics2, LLaVA-OneVision).

Sua escolha de pré-treinamento determina para que o backbone é adequado: CLIP/SigLIP para correspondência semântica com texto, DINOv2 para recursos visuais densos e MAE como ponto de partida para ajuste fino (finetuning) downstream.

Leis de escala

A escala de ViT (Zhai et al. 2022) estabeleceu que a qualidade de um ViT obedece a leis previsíveis em tamanho de modelo, tamanho de dados e computação. Sob computação fixa:

  • Modelo maior + mais dados → melhor qualidade.
  • O tamanho do patch é uma alavanca entre o comprimento da sequência e a fidelidade. O patch 14 (comum para DINOv2/SigLIP SO400m) gera mais tokens por imagem do que o patch 16; melhor para OCR e tarefas densas, pior para velocidade.
  • A resolução é la outra grande alavanca. Ir de 224 para 384 e para 512 quase sempre ajuda, a um custo quadrático em FLOPs.

O ViT-g/14 (1B de parâmetros, patch 14, resolução 224 → 256 tokens) e o SigLIP SO400m/14 (400M de parâmetros, patch 14) são os dois codificadores mais utilizados nos VLMs abertos de 2026.

Contagem de parâmetros para um ViT

O cálculo completo está em code/main.py. Para o ViT-B/16 em 224:

patch_embed = 3 * 16 * 16 * 768 + 768  =  591k
cls + pos    = 768 + 197 * 768          =  152k
block        = 4 * 768^2 (QKVO) + 2 * 4 * 768^2 (MLP) + 2 * 2*768 (LN)
             = 12 * 768^2 + 3k          =  7.1M
12 blocks    = 85M
final LN    = 1.5k
total       ≈ 86M

Estime cada ViT dessa forma antes de carregar o checkpoint. O tamanho do backbone define o seu limite mínimo de VRAM em qualquer VLM downstream.

Configuração de produção de 2026

O codificador com o qual a maioria dos VLMs abertos é fornecida em 2026 é o SigLIP 2 SO400m/14 em resolução nativa (NaFlex). Ele possui:

  • 400 milhões de parâmetros.
  • Tamanho de patch 14, resolução padrão 384 → 729 tokens de patch por imagem.
  • Agregação por média (Mean pool) para tarefas ao nível de imagem; todos os 729 patches fluem para o LLM para VQA.
  • 4 tokens de registro, descartados antes do envio ao LLM.
  • 2D-RoPE com dimensionamento ao nível da imagem para proporção de tela nativa.

Cada decisão nessa configuração remete a um artigo científico que você pode ler.

Use

O arquivo code/main.py é um tokenizador de patches e calculadora de geometria. Ele recebe (H da imagem, W, patch P, D oculto, profundidade L) e relata:

  • O formato da grade e o comprimento da sequência após a divisão em patches.
  • A sequência de tokens para uma imagem sintética de brinquedo de 8x8 pixels (passando pelo caminho de planificar + projetar).
  • A contagem de parâmetros dividida por incorporação de patch, incorporação de posição, blocos do transformer e cabeçote.
  • FLOPs por passagem direta (forward pass) na resolução alvo.
  • Uma tabela comparativa entre ViT-B/16 @ 224, ViT-L/14 @ 336, DINOv2 ViT-g/14 @ 224, SigLIP SO400m/14 @ 384.

Execute-o. Faça a correspondência da contagem de parâmetros com os números publicados. Experimente alterar o tamanho do patch e a resolução para sentir o custo da contagem de tokens.

Envie

Esta lição produz o arquivo outputs/skill-patch-geometry-reader.md. Dada uma configuração do ViT (tamanho do patch, resolução, dimensão oculta, profundidade), ela gera uma estimativa de contagem de tokens, contagem de parâmetros e VRAM com justificativas. Use essa habilidade sempre que escolher um backbone de visão para um VLM — isso evita surpresas como "a quantidade de tokens explodiu e meu contexto do LLM esgotou".

Exercícios

  1. Calcule o comprimento da sequência de tokens de patch para o Qwen2.5-VL em entrada nativa de 1280x720 com tamanho de patch 14. Como isso se compara a uma representação apenas com CLS?

  2. Um quadro de 1080p (1920x1080) com patch 14 produz quantos tokens? A 30 FPS em um vídeo de 5 minutos, quantos tokens visuais teremos no total? Qual dessas otimizações economiza mais custo: pooling, amostragem de quadros (frame sampling) ou fusão de tokens (token merging)?

  3. Implemente mean pooling sobre tokens de patch em Python puro. Verifique se o mean-pool sobre 196 tokens de uma saída do DINOv2 corresponde ao que o método forward do modelo retorna quando você solicita um embedding agregado (pooled embedding).

  4. Leia a Seção 3 do artigo "Vision Transformers Need Registers" (arXiv:2309.16588). Descreva em duas frases qual artefato os registros absorvem e por que isso importa para a predição densa downstream.

  5. Modifique o arquivo code/main.py para suportar o recurso patch-n'-pack: dada uma lista de imagens de diferentes resoluções, gere uma única sequência compactada e a máscara de atenção bloco-diagonal. Verifique o resultado com base na Lição 12.06 quando chegar a ela.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Patch "Quadrado de 16x16 pixels" Uma região não sobreposta de tamanho fixo da imagem de entrada; torna-se um token
Incorporação de patch (Patch embedding) "Projeção linear" Uma matriz aprendida compartilhada (ou Conv2d com stride=P) mapeando os pixels achatados do patch para vetores de dimensão D
Token CLS "Token de classe" Vetor aprendível anexado ao início que representa toda a imagem em seu estado oculto final; opcional em 2026
Token de registro (Register token) "Token de descarte" Tokens aprendíveis extras que absorvem os artefatos de atenção de alta norma que os ViTs desenvolvem durante o pré-treinamento
Incorporação de posição (Position embedding) "Informações posicionais" Vetor ou rotação por posição que torna a sequência sensível à ordem; 2D-RoPE é o padrão moderno
Grade (Grid) "Grade de patches" A matriz 2D (H/P) x (W/P) de patches para uma determinada resolução e tamanho de patch
NaFlex "Resolução nativa flexível" Recurso do SigLIP 2: um único modelo atende a várias proporções de tela e resoluções sem necessidade de retreinamento
Backbone "Torre de visão" O codificador de imagem pré-treinado cujas saídas de tokens de patch alimentam o LLM em um VLM
Pooling "Resumo ao nível de imagem" Estratégia para transformar tokens de patch em um único vetor: CLS, média (mean), pooling de atenção ou baseado em registros
Patch 14 vs 16 "Grade mais fina vs mais grossa" O patch 14 produz mais tokens por imagem, proporcionando melhor fidelidade para OCR, mas é mais lento; o patch 16 é o padrão clássico

Leituras Adicionais

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).