Phase 07 - Lesson 09
Vision Transformers (ViT)
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
Uma imagem é uma grade de patches. Uma frase é uma grade de tokens. O mesmo transformer consome ambos.
Tipo: Build Linguagens: Python Pré-requisitos: Fase 7 · 05 (Transformer Completo), Fase 4 · 03 (CNNs), Fase 4 · 14 (Introdução a Vision Transformers) Tempo: ~45 minutos
O Problema
Antes de 2020, visão computacional significava convoluções. Cada SOTA no ImageNet, COCO e benchmarks de detecção usava um backbone CNN. Transformers eram para linguagem.
Dosovitskiy et al. (2020) — "An Image is Worth 16x16 Words" — mostraram que você pode descartar as convoluções inteiramente. Fatie uma imagem em patches de tamanho fixo, projete linearmente cada patch em um embedding, alimente a sequência em um encoder de transformer vanilla. Em escala suficiente (pré-treinamento no ImageNet-21k ou maior), o ViT se equipara ou supera modelos baseados em ResNet.
O ViT foi o início de um padrão mais amplo em 2026: uma arquitetura, muitas modalidades. O Whisper tokeniza áudio. O ViT tokeniza imagens. Tokens de ação para robótica. Tokens de pixel para vídeo. O transformer não se importa — alimente-o com uma sequência e ele aprende.
Até 2026, o ViT e seus descendentes (DeiT, Swin, DINOv2, ViT-22B, SAM 3) dominam a maior parte da visão computacional. CNNs ainda vencem em dispositivos de borda e tarefas sensíveis à latência. Todo o resto possui um ViT em algum lugar do stack.
O Conceito
Passo 1 — patchify
Divida uma imagem H × W × C em uma sequência N × (P·P·C) de patches achatados. Configuração típica: imagem 224 × 224, patches 16 × 16 → 196 patches de 768 valores cada.
image (224, 224, 3) → 14 × 14 grid of 16x16x3 patches → 196 vectors of length 768
O tamanho do patch é a alavanca. Patches menores = mais tokens, melhor resolução, custo de atenção quadrático. Patches maiores = mais grosseiros, mais baratos.
Passo 2 — linear embedding
Uma única matriz aprendida projeta cada patch achatado para d_model. Equivalente a uma convolução com kernel de tamanho P e stride P. Em PyTorch, isso é literalmente nn.Conv2d(C, d_model, kernel_size=P, stride=P) — uma implementação de 2 linhas.
Passo 3 — prepend do token [CLS], adicionar embeddings posicionais
- Adicione um token
[CLS]aprendível ao início (prepend). Seu estado oculto final é a representação da imagem usada para classificação. - Adicione embeddings posicionais aprendíveis (ViT original) ou senoidais 2D (variantes posteriores).
- Em 2024+, o RoPE foi estendido para 2D para posição, às vezes sem embeddings explícitos.
Passo 4 — transformer encoder padrão
Empilhe L blocos de LayerNorm → Self-Attention → + → LayerNorm → MLP → +. Idêntico ao BERT. Sem camadas específicas de visão. Esta é a sacada pedagógica do artigo.
Passo 5 — head
Para classificação: use o estado oculto do [CLS] → linear → softmax. Para DINOv2 ou SAM, descarte o [CLS], use os embeddings de patch diretamente.
Variantes que importaram
| Modelo | Ano | Mudança |
|---|---|---|
| ViT | 2020 | O original. Tamanho de patch fixo, atenção global completa. |
| DeiT | 2021 | Destilação; treinável apenas no ImageNet-1k. |
| Swin | 2021 | Hierárquico com janelas deslocadas (shifted windows). Custo subquadrático fixo. |
| DINOv2 | 2023 | Autossupervisionado (sem rótulos). Melhores features gerais de visão. |
| ViT-22B | 2023 | 22B de parâmetros; leis de escala se aplicam. |
| SigLIP | 2023 | ViT + par de linguagem, perda contrastiva sigmoide. |
| SAM 3 | 2025 | Segment anything; ViT-Large + decoder de máscara baseado em prompts. |
Por que demorou um pouco
O ViT precisa de muito mais dados para se equiparar às CNNs porque não possui nenhum dos vieses indutivos das CNNs (invariância por translação, localidade). Sem mais de 100M de imagens rotuladas ou um forte pré-treinamento autossupervisionado, as CNNs ainda vencem sob a mesma quantidade de computação. O DeiT corrigiu isso em 2021 com truques de destilação; o DINOv2 corrigiu isso definitivamente em 2023 com autossupervisão.
Construa
Veja code/main.py. Patchify puro da stdlib + linear embedding + verificações de sanidade. Sem treinamento — o ViT em qualquer escala realista precisa do PyTorch e horas de tempo de GPU.
Passo 1: imagem falsa
Uma imagem RGB 24 × 24 como uma lista de linhas de tuplas (R, G, B). Usamos patches 6×6 → 16 patches, vetor de embedding de 108 dimensões cada.
Passo 2: patchify
def patchify(image, P):
H = len(image)
W = len(image[0])
patches = []
for i in range(0, H, P):
for j in range(0, W, P):
patch = []
for di in range(P):
for dj in range(P):
patch.extend(image[i + di][j + dj])
patches.append(patch)
return patches
Ordem raster: majoritária por linha (row-major) ao longo da grade. Todo ViT usa essa ordenação.
Passo 3: linear embed
Multiplique cada patch achatado por uma matriz aleatória (patch_flat_size, d_model). Verifique se a forma da saída é (N_patches + 1, d_model) após adicionar o [CLS] ao início.
Passo 4: contar parâmetros para um ViT realista
Imprima a contagem de parâmetros para o ViT-Base: 12 camadas, 12 cabeças, d=768, patch=16. Compare com a ResNet-50 (~25M). O ViT-Base fica em torno de ~86M. ViT-Large ~307M. ViT-Huge ~632M.
Use
from transformers import ViTImageProcessor, ViTModel
import torch
from PIL import Image
processor = ViTImageProcessor.from_pretrained("google/vit-base-patch16-224-in21k")
model = ViTModel.from_pretrained("google/vit-base-patch16-224-in21k")
img = Image.open("cat.jpg")
inputs = processor(img, return_tensors="pt")
out = model(**inputs).last_hidden_state # (1, 197, 768): [CLS] + 196 patches
cls_emb = out[:, 0] # image representation
Os embeddings do DINOv2 são o padrão de 2026 para features de imagem. Congele o backbone, treine uma cabeça minúscula. Funciona para classificação, busca (retrieval), detecção, geração de legendas (captioning). Os checkpoints do DINOv2 da Meta superam o CLIP em todas as tarefas de visão não textuais.
Escolha do tamanho do patch. Modelos pequenos usam 16×16 (ViT-B/16). Predição densa (segmentação) usa 8×8 ou 14×14 (SAM, DINOv2). Modelos muito grandes usam 14×14.
Entregue
Veja outputs/skill-vit-configurator.md. A skill escolhe uma variante de ViT e o tamanho do patch para uma nova tarefa de visão, considerando o tamanho do dataset, resolução e orçamento computacional.
Exercícios
- Fácil. Execute
code/main.py. Verifique se o número de patches é igual a(H/P) * (W/P)e se a dimensão do patch achatado é igual aP*P*C. - Médio. Implemente embeddings posicionais senoidais 2D — dois códigos senoidais independentes para a linha (
row) e coluna (col) de cada patch, concatenados. Alimente-os em um ViT minúsculo em PyTorch e compare a acurácia em relação a embeddings posicionais aprendíveis no CIFAR-10. - Difícil. Construa um ViT de 3 camadas (PyTorch), treine em 1.000 imagens do MNIST com patches de 4×4. Meça a acurácia de teste. Agora adicione pré-treinamento do DINOv2 nas mesmas 1.000 imagens (simplificado: apenas treine o encoder para prever embeddings de patch a partir de patches mascarados). A acurácia melhora?
Termos-chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Patch | "O token do vision-transformer" | Vetor achatado de valores de pixel para uma região P × P × C da imagem. |
| Patchify | "Cortar + achatar" | Fatiar a imagem em patches que não se sobrepõem e achatar cada um em um vetor. |
Token [CLS] |
"O resumo da imagem" | Token aprendível adicionado ao início; seu embedding final é a representação da imagem. |
| Viés indutivo | "O que o modelo assume" | O ViT tem menos premissas do que as CNNs; precisa de mais dados para compensar essa lacuna. |
| DINOv2 | "ViT autossupervisionado" | Treinado sem rótulos usando aumentação de imagem + professor de momentum (momentum teacher). Melhores features gerais de imagem em 2026. |
| SigLIP | "Sucessor do CLIP" | ViT + encoder de texto treinado com perda contrastiva sigmoide; melhor que o CLIP sob a mesma quantidade de computação. |
| Swin | "ViT em janelas" | ViT hierárquico com atenção local + janelas deslocadas; subquadrático. |
| Tokens de registro | "Truque de 2023" | Alguns tokens adicionais aprendíveis que absorvem os sinks de atenção; melhora as features do DINOv2. |
Leitura Adicional
- Dosovitskiy et al. (2020). An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale — o artigo do ViT.
- Touvron et al. (2021). Training data-efficient image transformers & distillation through attention — DeiT.
- Liu et al. (2021). Swin Transformer: Hierarchical Vision Transformer using Shifted Windows — Swin.
- Oquab et al. (2023). DINOv2: Learning Robust Visual Features without Supervision — DINOv2.
- Darcet et al. (2023). Vision Transformers Need Registers — a correção de tokens de registro para o DINOv2.