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

Imagem → patches → tokens → transformer

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

  1. 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 a P*P*C.
  2. 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.
  3. 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

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