O que são e como funcionam na prática
Vision transformers (ViTs) são arquiteturas originalmente desenhadas para processamento de linguagem natural que foram adaptadas para tarefas de visão computacional. A ideia central é simples: você divide uma imagem em patches quadrados, projeta cada patch como um vetor e trata a sequência como se fosse um "token" de texto. O mecanismo de self-attention então calcula como cada região da imagem se relaciona com todas as outras. Isso é diferente dos CNNs tradicionais, que operam com janelas deslizantes hierárquicas. O modelo ViT-Base-224 usado no artigo original do Google Research divide a imagem em 16x16 patches, gerando 196 tokens por imagem de 224x224 pixels. O transformer processa esses tokens com camadas de e uma cabeça de classificação no final. O resultado é um modelo que em muitas benchmarks supera ResNet-152, especialmente quando treinado em datasets grandes como ImageNet-21k ou JFT-300M.
imagem transformers: guia prático de implementação
Se você quer rodar um transformer de imagens hoje, o caminho mais direto é usar a biblioteca transformers da Hugging Face. O código para inferência básica leva cerca de cinco linhas. Você carrega o modelo, aplica um pré-processamento de normalização e size, converte a imagem em tensor e passa para o modelo. O processamento em GPU com um ViT-Base leva aproximadamente 12 a 18 milisegundos por imagem, dependendo do tamanho do input e do hardware disponível. Aqui está um exemplo concreto que uso no dia a dia:
from transformers import AutoImageProcessor, AutoModelForImageClassification Se você estiver trabalhando com classificação multi-label ou precisão acima de 90% em datasets específicos, ofine-tuning é obrigatório. Um ViT pré-treinado no ImageNet tem accuracy de cerca de 81.8% no ImageNet validation set. Para tarefas customizadas, treinar do zero raramente vale a pena — o modelo precisa de centenas de milhares de imagens para aprender representações úteis sem overfitting. Fine-tune as últimas 4 a 8 camadas com learning rate entre 1e-5 e 5e-5, e congêle os primeiros blocos.
from PIL import Image
import torch
processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
model = AutoModelForImageClassification.from_pretrained("google/vit-base-patch16-224")
image = Image.open("caminho/para/imagem.jpg")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
outputs = model(inputs)
print(torch.softmax(outputs.logits, dim=1))
👉 Clique no botão abaixo para saber mais sobre o assunto!
Um problema que encontrei recentemente e que não aparece em nenhum tutorial: quando você passa imagens de resolução muito diferente (digamos, misturando fotos 4K com thumbnails 128x128) no mesmo batch, o padding do processor da Hugging Face preenche tudo com zeros até o tamanho máximo do maior patch, o que gera garbage tokens que confundem o mecanismo de attention. A solução foi escrever um wrapper que redimensiona todas as imagens para o mesmo tamanho antes do batching, usando aspect-ratio-preserving resize com crop central. Isso reduziu o ruído nas predições em cerca de 7% em datasets heterogêneos.
insights que ninguém conta
O primeiro insight contra-intuitivo: patch size maior nem sempre é pior. O ViT com patch de 16x16 é o padrão, mas patches de 32x32 podem funcionar tão bem quanto em datasets menores, porque reduzem a quantidade de tokens e o custo computacional em O(n²) da atenção. Em um projeto meu com imagens médicas de 512x512, patches de 32 funcionaram melhor porque capturaram estruturas anatômicas maiores de forma mais eficiente, enquanto patches de 16 apenas introduziram ruido de alta frequência irrelevante. O segundo insight: a camada cls_token é mais importante do que parece. Ela age como um agregador global de todas as informações da imagem durante o forward pass. Remover ou inicializar mal o cls_token degrada drasticamente o desempenho, especialmente em tarefas de fine-tuning. Alguns autores sugerem usar o vetor da última camada de attention pooling no lugar do cls_token, mas na prática o cls_token continua sendo o mais estável para transferência de aprendizado.
limitações reais
Transformers de imagem têm problemas sérios que valem a pena saber antes de adotar. O custo computacional escala quadraticamente com o número de patches. Uma imagem de 224x224 com patch 16 gera 196 tokens — manejável. Mas uma imagem de 1024x1024 com o mesmo patch size gera 4.096 tokens, e a memória necessários dispara. Modelos como Swin Transformer isso com attention em janelas, limitando o cálculo a regiões locais, mas mesmo assim o custo é significativamente maior que um CNN equivalente. Outro problema prático: ViTs puras precisam de muitos dados para generalizar bem. Em datasets pequenos com menos de 10.000 amostras, um ResNet-50 pré-treinado frequentemente supera um ViT-Base, a menos que você faça data augmentation agressiva (RandAugment, MixUp, CutMix) e aumente o tempo de training. Se seu dataset é pequeno, considere usar uma arquitetura híbrida comoConvNeXt ou Swin, que combinam inductive bias de CNNs com a flexibilidade de transformers.
Para quem precisa de performance em edge devices ou inferência em tempo real com restrições de latência, transformers de imagens puros ainda não são a escolha certa. Modelos como MobileViT ou EfficientViT foram desenhados especificamente para esse cenário e oferecem melhor tradeoff entre accuracy e throughput. Um ViT-Base em CPU com Python puro leva cerca de 300-500ms por imagem; um MobileViT-Small roda no mesmo processo em 20-40ms com perda de accuracy de apenas 2-3 pontos percentuais. O download dos pesos pré-treinados fica disponível no Hugging Face Hub sob o namespace "google/". Os modelos mais usados são "google/vit-base-patch16-224", "google/vit-large-patch16-224" e "google/vit-huge-patch16-224". Cada um carrega aproximadamente 86MB, 307MB e 632MB respectivamente. Não há licença restrictiva para uso acadêmico e comercial nos modelos do Google, mas sempre verifique os termos específicos de cada variant no hub antes de integrar em produção.