Phase 04 - Lesson 17
Visão Auto-Supervisionada — SimCLR, DINO, MAE
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
Os rótulos são o gargalo da visão supervisionada. O pré-treino auto-supervisionado os elimina: aprenda características visuais a partir de 100M de imagens sem rótulo e faça o fine-tuning em 10 mil rotuladas.
Tipo: Aprender + Construir Linguagens: Python Pré-requisitos: Fase 4 Lição 04 (Classificação de Imagens), Fase 4 Lição 14 (ViT) Tempo: ~75 minutos
Objetivos de Aprendizagem
- Percorrer as três grandes famílias auto-supervisionadas — contrastiva (SimCLR), professor-aluno (DINO), reconstrução mascarada (MAE) — e enunciar o que cada uma otimiza
- Implementar uma perda InfoNCE do zero e explicar por que um batch de 512 funciona, mas um batch de 32 falha
- Explicar por que a taxa de mascaramento de 75% do MAE não é arbitrária e como ela difere dos 15% do BERT para texto
- Usar checkpoints DINOv2 ou MAE da ImageNet para linear probing e recuperação zero-shot
O Problema
A ImageNet supervisionada tem 1,3M de imagens rotuladas, cuja anotação custou cerca de US$ 10M. Conjuntos de dados médicos e industriais são menores e ainda mais caros de rotular. Toda equipe de visão pergunta: podemos pré-treinar em dados sem rótulo baratos — frames do YouTube, web crawls, gravações de webcam, varreduras de satélite — e depois fazer o fine-tuning em um pequeno conjunto rotulado?
A aprendizagem auto-supervisionada é a resposta. Um ViT auto-supervisionado moderno treinado na LAION ou na JFT alcança ou supera a acurácia da ImageNet supervisionada quando passa por fine-tuning. Ele também transfere melhor para tarefas downstream (detecção, segmentação, profundidade) do que o pré-treino supervisionado. O DINOv2 (Meta, 2023) e o MAE (Meta, 2022) são os padrões de produção atuais para características visuais transferíveis.
A mudança conceitual é que a tarefa-pretexto — aquilo que o modelo é treinado para fazer — não precisa ser a tarefa downstream. O que importa é que ela force o modelo a aprender características úteis. Prever a cor de imagens em tons de cinza, rotacionar imagens e pedir ao modelo que classifique a rotação, mascarar patches e reconstruí-los — tudo funcionou. As três abordagens que escalam são a aprendizagem contrastiva, a destilação professor-aluno e a reconstrução mascarada.
O Conceito
Três famílias
flowchart LR
A["Contrastiva<br/>SimCLR, MoCo, CLIP"] --> AT["pares positivos<br/>(mesma imagem, 2 augs)<br/>aproximados,<br/>negativos afastados"]
B["Professor-aluno<br/>DINO, BYOL, iBOT"] --> BT["o aluno prevê<br/>a saída do professor;<br/>o professor é a EMA do aluno"]
C["Reconstrução mascarada<br/>MAE, BEiT, SimMIM"] --> CT["mascarar 75% dos patches;<br/>reconstruir alvos de<br/>pixel ou token"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fef3c7,stroke:#d97706
style C fill:#dcfce7,stroke:#16a34a
Aprendizagem contrastiva (SimCLR)
Pegue uma imagem, aplique duas augmentations aleatórias e obtenha duas views. Passe ambas pelo mesmo encoder mais uma projection head. Minimize uma perda que diz "esses dois embeddings devem estar próximos" e "este embedding deve estar distante dos embeddings de toda outra imagem no batch."
Loss for positive pair (z_i, z_j) among 2N views per batch:
L_ij = -log( exp(sim(z_i, z_j) / tau) / sum_k in batch \ {i} exp(sim(z_i, z_k) / tau) )
sim = cosine similarity
tau = temperature (0.1 standard)
Essa é a perda InfoNCE. Ela exige muitos negativos por positivo, então o tamanho do batch importa — o SimCLR precisa de 512-8192. O MoCo introduziu uma fila de momentum com batches passados para desacoplar a contagem de negativos do tamanho do batch.
Professor-aluno (DINO)
Duas redes com a mesma arquitetura: aluno e professor. O professor é uma média móvel exponencial (EMA) dos pesos do aluno. Ambos veem views augmentadas da imagem. A saída do aluno é treinada para coincidir com a do professor — sem negativos explícitos.
loss = CE( student_output(view_1), teacher_output(view_2) )
+ CE( student_output(view_2), teacher_output(view_1) )
teacher_weights = m * teacher_weights + (1 - m) * student_weights (m ≈ 0.996)
Por que não colapsa para "prever uma constante": a saída do professor é centrada (subtrai a média por dimensão) e afiada (divide por uma temperatura pequena). A centralização impede que uma dimensão domine; a afiação impede o colapso da saída para uma distribuição uniforme.
O DINO é o que o DINOv2 escala, em 142M de imagens curadas. As características resultantes são o SOTA atual para recuperação visual zero-shot e predição densa.
Reconstrução mascarada (MAE)
Mascare 75% dos patches de uma entrada de ViT. Passe apenas os 25% visíveis pelo encoder. Um pequeno decoder recebe a saída do encoder mais mask tokens nas posições mascaradas e é treinado para reconstruir os pixels dos patches mascarados.
Encoder: visible 25% of patches -> features
Decoder: features + mask tokens at masked positions -> reconstructed pixels
Loss: MSE between reconstructed and original pixels on masked patches only
Escolhas de design fundamentais que fazem o MAE funcionar:
- Taxa de mascaramento de 75% — alta. Força o encoder a aprender características semânticas; reconstruir 25% seria quase trivial (pixels vizinhos são tão correlacionados que uma CNN daria conta).
- Encoder/decoder assimétricos — o grande encoder ViT só vê os patches visíveis; um pequeno decoder (8 camadas, 512 dimensões) cuida da reconstrução. Pré-treino 3x mais rápido que o BEiT ingênuo.
- Alvo de reconstrução no espaço de pixels — mais simples que o alvo tokenizado do BEiT e funciona melhor em ViT.
Após o pré-treino, descarte o decoder. O encoder é o extrator de características.
Por que 75% e não 15%
O BERT mascara 15% dos tokens. O MAE mascara 75%. A diferença é a densidade de informação.
- A linguagem natural tem alta entropia por token. Prever 15% dos tokens ainda é difícil porque cada posição mascarada tem muitas continuações plausíveis.
- Os patches de imagem têm baixa entropia — uma vizinhança não mascarada frequentemente determina os pixels do patch mascarado quase exatamente. Para que a predição exija compreensão semântica, é preciso mascarar de forma agressiva.
75% é alto o suficiente para que a simples extrapolação espacial não consiga resolver a tarefa; o encoder precisa representar o conteúdo da imagem.
Avaliação por linear-probe
Após o pré-treino auto-supervisionado, a avaliação padrão é um linear probe: congele o encoder, treine um único classificador linear por cima usando os rótulos da ImageNet. Reporta a acurácia top-1.
- SimCLR ResNet-50: ~71% (2020)
- DINO ViT-S/16: ~77% (2021)
- MAE ViT-L/16: ~76% (2022)
- DINOv2 ViT-g/14: ~86% (2023)
O linear probe é uma medida pura da qualidade das características; o fine-tuning normalmente adiciona de 2 a 5 pontos, mas também mistura o efeito do retreino da head.
Construa
Passo 1: Pipeline de augmentation de duas views
import torch
import torchvision.transforms as T
two_view_train = lambda: T.Compose([
T.RandomResizedCrop(96, scale=(0.2, 1.0)),
T.RandomHorizontalFlip(),
T.ColorJitter(0.4, 0.4, 0.4, 0.1),
T.RandomGrayscale(p=0.2),
T.ToTensor(),
])
class TwoViewDataset(torch.utils.data.Dataset):
def __init__(self, base):
self.base = base
self.aug = two_view_train()
def __len__(self):
return len(self.base)
def __getitem__(self, i):
img, _ = self.base[i]
v1 = self.aug(img)
v2 = self.aug(img)
return v1, v2
Cada getitem retorna duas views augmentadas da mesma imagem; rótulos não são necessários.
Passo 2: Perda InfoNCE
import torch.nn.functional as F
def info_nce(z1, z2, tau=0.1):
"""
z1, z2: (N, D) L2-normalised embeddings of paired views
"""
N, D = z1.shape
z = torch.cat([z1, z2], dim=0) # (2N, D)
sim = z @ z.T / tau # (2N, 2N)
mask = torch.eye(2 * N, dtype=torch.bool, device=z.device)
sim = sim.masked_fill(mask, float("-inf"))
targets = torch.cat([torch.arange(N, 2 * N), torch.arange(0, N)]).to(z.device)
return F.cross_entropy(sim, targets)
Normalize os embeddings com L2 antes de chamar. tau=0.1 é o padrão do SimCLR; valores menores tornam a perda mais afiada e exigem mais negativos.
Passo 3: Sanity check do InfoNCE
z1 = F.normalize(torch.randn(16, 32), dim=-1)
z2 = z1.clone()
loss_same = info_nce(z1, z2, tau=0.1).item()
z2_random = F.normalize(torch.randn(16, 32), dim=-1)
loss_random = info_nce(z1, z2_random, tau=0.1).item()
print(f"InfoNCE with identical pairs: {loss_same:.3f}")
print(f"InfoNCE with random pairs: {loss_random:.3f}")
Pares idênticos devem dar uma perda baixa (próxima de 0 para um batch grande e temperatura fria). Pares aleatórios devem dar log(2N-1) = ~log(31) = ~3,4 com um batch de 16 pares.
Passo 4: Mascaramento no estilo MAE
def random_mask_indices(num_patches, mask_ratio=0.75, seed=0):
g = torch.Generator().manual_seed(seed)
n_keep = int(num_patches * (1 - mask_ratio))
perm = torch.randperm(num_patches, generator=g)
visible = perm[:n_keep]
masked = perm[n_keep:]
return visible.sort().values, masked.sort().values
num_patches = 196
visible, masked = random_mask_indices(num_patches, mask_ratio=0.75)
print(f"visible: {len(visible)} / {num_patches}")
print(f"masked: {len(masked)} / {num_patches}")
Simples, rápido e determinístico para um dado seed. Implementações reais de MAE fazem isso em batch e mantêm máscaras por amostra.
Use
O DINOv2 é o padrão de produção em 2026:
import torch
from transformers import AutoImageProcessor, AutoModel
processor = AutoImageProcessor.from_pretrained("facebook/dinov2-base")
model = AutoModel.from_pretrained("facebook/dinov2-base")
model.eval()
# Per-image embeddings for zero-shot retrieval
with torch.no_grad():
inputs = processor(images=[pil_image], return_tensors="pt")
outputs = model(**inputs)
embedding = outputs.last_hidden_state[:, 0] # CLS token
O embedding resultante de 768 dimensões é a espinha dorsal dos pipelines modernos de recuperação de imagens, correspondência densa e transferência zero-shot. O fine-tuning em uma tarefa downstream raramente precisa de mais do que uma head linear.
Para embeddings de imagem-texto, o SigLIP ou o OpenCLIP é o equivalente; para fine-tuning no estilo MAE, o repositório timm traz todos os checkpoints de MAE.
Entregue
Esta lição produz:
outputs/prompt-ssl-pretraining-picker.md— um prompt que escolhe SimCLR / MAE / DINOv2 dados o tamanho do conjunto de dados, o compute e a tarefa downstream.outputs/skill-linear-probe-runner.md— uma skill que escreve a avaliação por linear-probe para qualquer encoder congelado + conjunto de dados rotulado.
Exercícios
- (Fácil) Verifique que a perda InfoNCE cai quando você diminui a temperatura para embeddings bem alinhados e sobe quando você diminui a temperatura para embeddings aleatórios. Produza um gráfico de
tau in [0.05, 0.1, 0.2, 0.5]vs perda. - (Médio) Implemente um buffer de centro no estilo DINO. Mostre que, sem a centralização, o aluno colapsa para um vetor constante em poucas épocas.
- (Difícil) Treine o MAE no CIFAR-100 usando a TinyUNet da Lição 10 como backbone. Reporte a acurácia do linear-probe em 10, 50 e 200 épocas. Mostre que um linear probe pré-treinado com MAE supera um linear probe supervisionado treinado do zero no mesmo subconjunto de 1.000 imagens.
Termos-Chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Auto-supervisionado | "Sem rótulos" | Uma tarefa-pretexto que produz representações úteis a partir de dados sem rótulo |
| Tarefa-pretexto | "A tarefa falsa" | O objetivo usado durante a SSL (reconstruir patches, casar views); descartado após o pré-treino |
| Linear probe | "Encoder congelado + head linear" | Avaliação padrão de SSL: treinar apenas um classificador linear por cima de características congeladas |
| InfoNCE | "Perda contrastiva" | softmax sobre similaridades de cosseno; o par positivo é a classe-alvo, todos os outros são negativos |
| Professor EMA | "Professor de média móvel" | Professor cujos pesos são uma média móvel exponencial dos do aluno; usado por BYOL, MoCo, DINO |
| Taxa de mascaramento | "% de patches ocultos" | Fração de patches mascarados durante o MAE; 75% para visão, 15% para texto |
| Colapso de representação | "Saída constante" | Falha de SSL em que o encoder produz um vetor constante para todas as entradas; evitada por centralização, afiação ou negativos |
| DINOv2 | "Backbone de SSL de produção" | O ViT auto-supervisionado da Meta de 2023; as características de imagem de propósito geral mais fortes em 2026 |
Leitura Adicional
- SimCLR (Chen et al., 2020) — referência de aprendizagem contrastiva
- DINO (Caron et al., 2021) — professor-aluno com momentum, centralização, afiação
- MAE (He et al., 2022) — pré-treino de autoencoder mascarado para ViT
- DINOv2 (Oquab et al., 2023) — escalando o ViT auto-supervisionado para características de produção