Phase 12 - Lesson 06

Visão em Qualquer Resolução: Patch-n'-Pack e NaFlex

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

Imagens reais não são quadrados de 224x224. Um recibo é 9:16, um gráfico é 16:9, um exame médico pode ser 4096x4096, uma captura de tela de celular é 9:19.5. A resposta dos VLMs pré-2024 — redimensionar tudo para um quadrado fixo — descartava o sinal que faz o OCR, a compreensão de documentos e a análise de cenas de alta resolução funcionarem. O NaViT (Google, 2023) mostrou que era possível empacotar patches de resolução variável em um único lote de transformer com mascaramento em bloco diagonal. O M-RoPE do Qwen2-VL (2024) eliminou completamente as tabelas posicionais absolutas. O AnyRes do LLaVA-NeXT dividiu imagens de alta resolução em uma base + sub-imagens. A variante NaFlex do SigLIP 2 (2025) é agora o codificador padrão para VLMs abertos que desejam um único checkpoint para atender a qualquer proporção de tela (aspect ratio). Esta lição implementa o patch-n'-pack de ponta a ponta.

Tipo: Build Idiomas: Python (biblioteca padrão, patch packer + máscara em bloco diagonal) Pré-requisitos: Phase 12 · 01 (patches de ViT), Phase 12 · 05 (LLaVA) Tempo: ~120 minutos

Objetivos de Aprendizado

  • Empacotar patches de um lote de imagens de resolução variável em uma única sequência e construir a máscara de atenção em bloco diagonal.
  • Escolher entre AnyRes tiling (LLaVA-NeXT), NaFlex (SigLIP 2) e M-RoPE (Qwen2-VL) para uma determinada tarefa.
  • Calcular orçamentos de tokens para OCR, gráficos e fotografia sem redimensionamento.
  • Nomear os três modos de falha do redimensionamento quadrado: texto espremido, conteúdo cortado e tokens desperdiçados com preenchimento (padding).

O Problema

Transformers esperam uma sequência. Um lote (batch) é uma pilha de sequências do mesmo comprimento. Se suas imagens forem 224x224, você obterá 196 tokens de patch todas as vezes, sem necessidade de preenchimento (padding), trabalho concluído. Treine em 224, infira em 224, nunca mais pense em resolução.

O mundo não colabora. Documentos são em formato retrato (8,5x11 polegadas, cerca de 2:3). Capturas de tela de gráficos são em formato paisagem (16:9). Recibos são altos e estreitos (1:3). Imagens médicas vêm em 2048x2048 ou maiores. Capturas de tela de dispositivos móveis são 1170x2532 (0.46:1).

Três opções pré-2024 e por que cada uma falha:

  1. Redimensionar para um quadrado fixo (224x224 ou 336x336). A distorção espreme textos e rostos. A redução de escala destrói rótulos de gráficos e conteúdo de OCR. Prática padrão até o LLaVA-1.5.
  2. Recortar para uma proporção fixa. Você descarta a maior parte da imagem, e escolher o local do recorte é um problema de visão por si só.
  3. Preencher (pad) até o lado mais longo. Corrige a distorção, mas desperdiça mais de 50% dos tokens em preenchimento para imagens em formato retrato. Custo de atenção quadrático em todos esses tokens de preenchimento.

A resposta para 2024-2025: permitir que o transformer receba patches na resolução nativa da imagem e descobrir como empacotar um lote heterogêneo em uma única sequência sem desperdício de computação.

O Conceito

NaViT e patch-n'-pack

O NaViT (Dehghani et al., 2023) foi o artigo que mostrou que isso funciona em escala. A ideia é mecânica:

  1. Para cada imagem no lote, calcule sua grade de patches nativa em um tamanho de patch escolhido (por exemplo, 14).
  2. Aplane (flatten) os patches de cada imagem em sua própria sequência de comprimento variável.
  3. Concatene os patches de todas as imagens em uma única sequência longa para o lote.
  4. Construa uma máscara de atenção em bloco diagonal para que os patches da imagem A apenas prestem atenção (attend) dentro da própria imagem A.
  5. Carregue informações de posição por patch (2D RoPE ou embeddings de posição fracionários).

Um lote de três imagens em 336x336 (576 tokens), 224x224 (256 tokens) e 448x336 (768 tokens) torna-se uma única sequência de 1600 tokens com uma máscara em bloco diagonal de 1600x1600. Sem preenchimento. Sem desperdício de computação. O transformer lida com proporções de aspecto arbitrárias.

O NaViT também introduziu o descarte fracionário de patches (fractional patch dropping) durante o treinamento — descartando 50% dos patches aleatoriamente ao longo do lote —, o que regulariza e acelera o treinamento. O SigLIP 2 herdou isso.

AnyRes (LLaVA-NeXT)

O AnyRes do LLaVA-NeXT é a alternativa pragmática. Dada uma imagem de alta resolução e um codificador fixo (CLIP ou SigLIP em 336), divida a imagem em blocos (tiles):

  1. Escolha um layout de grade a partir de um conjunto predefinido — (1x1), (1x2), (2x1), (1x3), (3x1), (2x2), etc. — que melhor se adapte à proporção da imagem.
  2. Divida a imagem completa na grade; cada bloco torna-se um recorte de 336x336.
  3. Produza também uma miniatura (thumbnail): a imagem inteira redimensionada para 336x336 como um token de contexto global.
  4. Codifique cada bloco através do codificador 336 congelado. Concatene os tokens dos blocos + tokens da miniatura.

Para uma imagem de 672x672 em uma grade de 2x2 mais miniatura: 4 * 576 + 576 = 2880 tokens visuais. Caro, mas eficaz — o LLM vê tanto o detalhe local quanto o contexto global.

O AnyRes é o caminho escolhido quando seu codificador está congelado e suporta apenas uma resolução. Ele explode a contagem de tokens para imagens grandes (uma imagem de 1344x1344 em uma grade de 4x4 consome 9216 + 576 ≈ 9800 tokens, o que preenche a maior parte de um contexto de LLM de 8k).

M-RoPE (Qwen2-VL)

O Qwen2-VL introduziu o Multimodal Rotary Position Embedding (Embedding de Posição Rotativo Multimodal). Em vez das posições fracionárias do NaViT ou do bloco-e-miniatura do AnyRes, cada patch carrega uma posição 3D (temporal, altura, largura). As rotações de query/key lidam com H (altura), W (largura) e comprimento temporal arbitrários.

O M-RoPE oferece resolução dinâmica nativa sem retreinamento. Na inferência, você fornece qualquer imagem HxW, o incorporador de patch (patch embedder) produz H/14 x W/14 tokens, cada token recebe sua posição (t=0, r=linha, c=coluna), o RoPE rotaciona a atenção com as frequências corretas, pronto. O Qwen2.5-VL e o Qwen3-VL continuam com isso. O V2PE do InternVL3 segue a mesma ideia com codificação variável por modalidade.

Diferente do AnyRes, o M-RoPE usa tokens O(H x W / P^2) na resolução nativa — sem a sobrecarga multiplicativa de blocos (tiles). Diferente do NaViT, ele ainda espera uma única imagem por passagem direta (forward). O loteamento (batching) entre resoluções ainda requer patch-n'-pack por cima.

NaFlex (SigLIP 2)

O NaFlex é o modo nativo-flexível do checkpoint do SigLIP 2. Um único modelo serve a múltiplos comprimentos de sequência (256, 729, 1024 tokens) na inferência. Internamente, ele usa o patch-n'-pack no estilo NaViT durante o treinamento e posições fracionárias absolutas por patch. O diferencial de vendas: um único checkpoint, escolha seu orçamento de tokens na inferência com base na tarefa.

Para uma tarefa semântica (classificação, busca), 256 tokens. Para OCR ou compreensão de gráficos, 1024 tokens. Sem retreinamento.

A máscara de empacotamento

A máscara em bloco diagonal é onde a maioria das implementações tropeça. Para uma sequência empacotada de comprimento N_total cobrindo imagens i=0..B-1 com comprimentos n_i, a máscara M de formato (N_total, N_total) é 1 se ambos os índices caírem no mesmo bloco de imagem, caso contrário 0. Você pode construí-la a partir de uma lista de comprimentos cumulativos:

offsets = [0, n_0, n_0+n_1, ..., N_total]
M[i, j] = 1 iff there exists b where offsets[b] <= i < offsets[b+1] and offsets[b] <= j < offsets[b+1]

Isso é feito em uma linha no PyTorch com torch.block_diag ou uma coleta (gather) explícita. O caminho de comprimento variável do FlashAttention (cu_seqlens) ignora completamente a máscara e realiza a atenção dentro das sequências usando o tensor de comprimento cumulativo diretamente — cerca de 10x mais rápido do que uma máscara densa para lotes típicos.

Orçamentos de tokens

Escolha sua estratégia por tarefa:

  • OCR / documentos: 1024-4096 tokens. SigLIP 2 NaFlex em 1024, ou AnyRes 3x3 + miniatura.
  • Gráficos e interface de usuário (UI): 729-1024 tokens em 384-448 nativos. Resolução dinâmica do Qwen2.5-VL com limite máximo de pixels (max pixels cap).
  • Fotos naturais: 256-576 tokens são suficientes. O LLM downstream vê o bastante. Pague por tokens onde a densidade de conteúdo é alta.
  • Vídeo: 64-128 tokens por quadro após pooling espacial, 2-8 FPS. A Lição 12.17 aborda isso.

A regra de produção de 2026: escolha um limite máximo de pixels por tarefa, codifique na proporção nativa até esse limite, empacote o lote e pule o preenchimento (padding). O Qwen2.5-VL expõe min_pixels and max_pixels exatamente para esse ajuste.

Use

code/main.py implementa o patch-n'-pack para um lote heterogêneo de imagens com coordenadas de pixel inteiras. Ele:

  • Recebe uma lista de tamanhos de imagem (H, W).
  • Calcula o comprimento da sequência de patches de cada imagem com tamanho de patch 14.
  • Empacota-os em uma sequência de comprimento total sum(n_i).
  • Constrói a máscara de atenção em bloco diagonal (densa, para maior clareza).
  • Compara o custo empacotado versus o redimensionamento quadrado e o AnyRes tiling.
  • Imprime uma tabela de orçamento de tokens para um lote misto (recibo, gráfico, captura de tela, foto).

Execute-o. Os números resultantes são a razão pela qual todos os VLMs abertos de 2026 usam patch-n'-pack.

Implemente

Esta lição produz outputs/skill-resolution-budget-planner.md. Dado um volume de trabalho com proporções mistas (OCR, gráficos, fotos, quadros de vídeo) e um orçamento total de tokens, ela escolhe a estratégia correta (NaFlex, AnyRes, M-RoPE ou fixed-square) e emite uma configuração por requisição. Use esta habilidade ao dimensionar um VLM para um produto — isso evita a explosão silenciosa de tokens de 10x que destrói os orçamentos de latência.

Exercícios

  1. Um recibo tem 600x1500 (1:2.5). Com tamanho de patch 14, quantos tokens na resolução nativa? Quantos após o redimensionamento quadrado para 336? Qual perde mais precisão de OCR na prática?

  2. Construa a máscara em bloco diagonal para um lote de quatro imagens com comprimentos 256, 576, 729, 1024. Verifique se a matriz de atenção é 2585x2585 e possui exatamente 256^2 + 576^2 + 729^2 + 1024^2 entradas diferentes de zero.

  3. Para uma imagem de 1792x896 no patch 14, compare: (a) redimensionamento quadrado para 336 e codificação, (b) AnyRes 2x1 + miniatura, (c) M-RoPE no modo nativo. Qual usa menos tokens? Qual preserva mais detalhes?

  4. Implemente o descarte fracionário de patches (fractional patch dropping): dada uma sequência empacotada, descarte 50% dos tokens uniformemente de forma aleatória e atualize a máscara em bloco diagonal adequadamente. Meça a alteração de esparsidade da máscara.

  5. Leia a Seção 3.2 do artigo do Qwen2-VL (arXiv:2409.12191). Descreva em duas sentenças o que min_pixels e max_pixels controlam e por que ambos os limites importam.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Patch-n'-pack "Empacotamento estilo NaViT" Concatena sequências de patches de comprimento variável de diferentes imagens em uma única dimensão de lote
Block-diagonal mask "Máscara de empacotamento" Máscara de atenção que restringe os patches de cada imagem para atender apenas a si mesmos, não aos vizinhos no pacote
AnyRes "Tiling do LLaVA-NeXT" Divide uma imagem de alta resolução em uma grade de blocos de tamanho fixo mais uma miniatura global; codifica cada bloco com um codificador fixo
NaFlex "SigLIP 2 native-flex" Checkpoint único do SigLIP 2 que atende a orçamentos de 256/729/1024 tokens na inferência sem retreinamento
M-RoPE "RoPE Multimodal" Codificação de posição rotativa 3D (tempo, linha, coluna) que lida com H, W, T arbitrários sem tabelas de posição
cu_seqlens "Empacotamento FlashAttention" Tensor de comprimento cumulativo que o caminho varlen do FlashAttention usa em vez de uma máscara em bloco diagonal densa
min_pixels / max_pixels "Limites de resolução" Controles por requisição do Qwen2.5-VL que limitam a contagem de tokens em entradas muito pequenas ou muito grandes
Visual token budget "Quantos tokens por imagem" Contagem aproximada de tokens de patch emitidos por imagem; define o orçamento de prompt do LLM e o custo de atenção

Leituras Adicionais

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