Ir para o conteúdo

21. Flow Matching

A difusão funciona e é um jeito estranho de ter chegado a algo que funciona. Há uma equação diferencial estocástica, um limite variacional, um cronograma de ruído com nome próprio, uma cadeia discreta de mil passos e três parametrizações intercambiáveis. O método não é complicado — a dedução é.

O flow matching1 chega ao mesmo lugar pela outra direção e a montagem cabe em três linhas. Sorteie uma amostra de ruído e uma de dados. Trace a reta entre elas. Treine uma rede para prever a direção do deslocamento num ponto aleatório dessa reta. É o método inteiro.

\[ \mathcal{L}_{\text{CFM}} = \mathbb{E}_{t,\,x_0,\,x_1}\Big[\big\|v_\theta(x_t, t) - (x_1 - x_0)\big\|^2\Big], \qquad x_t = (1-t)\,x_0 + t\,x_1 \]

Aqui \(x_0 \sim \mathcal{N}(0, I)\) é o ruído, \(x_1\) uma amostra dos dados, \(t\) um instante sorteado de forma uniforme em \([0, 1]\) e \(v_\theta\) a rede, com pesos \(\theta\). CFM quer dizer conditional flow matching (flow matching condicional), porque o alvo \(x_1 - x_0\) é o de um par sorteado. O tempo vai do ruído (\(t = 0\)) aos dados (\(t = 1\)), o contrário do capítulo 20.

Sem cronograma, sem limite, sem cadeia. E — esta é a parte que vale deixar clara — não é uma família diferente de modelo. Difusão é flow matching com um interpolante curvo. Assim que você vê isso, o capítulo 20 e este se fundem numa ideia só.

Também não é uma curiosidade histórica. Desde 2024, quase todo gerador aberto de imagem e de vídeo cujo objetivo de treino é publicado — Stable Diffusion 3, FLUX, Wan, HunyuanVideo, Qwen-Image — treina exatamente com essa perda. Modelos de fala e as cabeças de ação de políticas de robôs também. Onde é usado tem a lista, com datas.

Slides

Clique nos slides e use as setas ← → para navegar; F abre em tela cheia e P abre a visão do apresentador, com as notas. Os três simuladores desta página e três dos diagramas dela rodam dentro dos slides. Abrir os slides numa aba nova


Movendo partículas

Você tem partículas distribuídas como \(p_0 = \mathcal{N}(0, I)\). Você as quer distribuídas como seus dados, \(p_1\), no tempo \(t = 1\). Aprenda um campo de velocidade \(v_\theta(x, t)\) que diga para onde cada partícula deve se mover em cada instante e integre.

\[ \frac{dx}{dt} = v_\theta(x, t), \qquad x_0 \sim p_0 \;\Longrightarrow\; x_1 \sim p_1 \]

O painel tem as duas imagens que este capítulo vai comparar o tempo todo. Pares de treino é o que a perda acima vê: cada amostra de ruído ligada por uma reta a um ponto de dados sorteado de forma independente. O fluxo aprendido é aquilo para onde converge uma rede treinada nessas retas, calculado aqui de forma exata (os dados são uma mistura de gaussianas pequenas, então nada precisa ser treinado). Anime os dois.

t = 0.00

Há um problema óbvio em treinar isso e é aquele em que a área toda estava travada. O campo de velocidade de que você precisa é um marginal: na posição \(x\) e no tempo \(t\), ele precisa fazer média sobre todo ponto de dados que plausivelmente poderia ter produzido \(x\),

\[ u_t(x) = \mathbb{E}\big[\,x_1 - x_0 \;\big|\; x_t = x\,\big]. \]

Você não consegue calcular isso para dados reais. Você nem consegue escrever.

O teorema que faz funcionar

Você não precisa. Regredir a velocidade condicional — a de um único par sorteado \((x_0, x_1)\), que é simplesmente \(x_1 - x_0\) — tem o mesmo gradiente que regredir a marginal intratável1. Então você treina sobre um alvo que cabe numa linha e a rede converge para o campo que você de fato queria.

É exatamente o que o DDPM faz ao regredir \(\epsilon\) em vez do score \(\nabla_x \log p_t(x)\), a direção em que a densidade de \(x_t\) cresce mais rápido. Mesmo truque, enunciado uma vez e em geral, em vez de uma vez por cronograma de ruído.

O teorema fica mais fácil de ver num ponto só. Com dois pontos de dados, exatamente duas retas de treino passam por cada \((x, t)\) e dá para calcular tudo à mão:

Duas retas de treino passam pelo mesmo ponto x t em t = 0,25: uma do ruído x0 = (1, 1) até B = (−2, 0), outra de x0′ = (−0,33; 1) até A = (2, 0). Os alvos delas são (−3, −1) e (2,33; −1). Pesados pela probabilidade de cada amostra de ruído, 0,39 e 0,61, eles têm média igual à velocidade marginal (0,25; −1,00); a dispersão em torno dela, 6,77, é o piso da perda neste ponto. ruído 𝒩(0, I) ut​ A = (2, 0)B = (−2, 0) x0​ x0​′ xt​ RETA ATÉ B x0​ = (1, 1) alvo (−3, −1) peso 0,39 erro² 10,56 RETA ATÉ A x0​′ = (−0,33; 1) alvo (2,33; −1) peso 0,61 erro² 4,34 t = 0,25xt​ = (0,25; 0,75) ut​(xt​) = 0,61·(2,33; −1) + 0,39·(−3, −1) = (0,25; −1) piso = 0,61 · 4,34 + 0,39 · 10,56 = 6,77 setas: 0,5 × velocidade

Duas consequências aparecem no painel das partículas e merecem ser ditas, porque as duas surpreendem na primeira vez:

  • A perda de treino não vai a zero. Muitos pares passam perto do mesmo \((x, t)\) com direções diferentes; a rede só consegue devolver a média deles e a dispersão em torno dela é um piso. No alvo de oito gaussianas do laboratório o piso é 3,73 (calculado de forma exata) e a rede treinada termina em 3,76, poucos centésimos acima dele. Uma perda de 3,76 aqui é um modelo que convergiu, não um que falhou.
  • Os caminhos aprendidos não podem se cruzar. Uma ODE tem uma velocidade por ponto e instante, então duas partículas nunca se encontram. O fluxo, portanto, repareia ruído e dados: cada partícula chega aos dados, mas não ao ponto com que foi pareada no treino. No painel, os pares de treino percorrem 1,23 em média e o fluxo 0,51.

Os mesmos dois fatos no código do laboratório: um passo de treinar_2d em três pares em 2-D, depois a amostragem de Euler a partir do ruído do par 1. A rede é trocada pelo campo para o qual ela converge, exato aqui porque os dados são dois pontos, \(A = (2, 0)\) e \(B = (-2, 0)\). O par 1 liga o ruído \((1, 1)\) a \(B\): com a rede já ideal, ele responde pela perda inteira; depois o fluxo leva esse ruído a \(A\). Mude \(t\), o número de passos de Euler ou o caso:

x0 · ruído
x1 · dados
t

● dados A, B · ● x0 · ● xt · → alvo · → v · — Euler (setas: 0,25 × velocidade)

A difusão é um caso particular

Tome um par qualquer de funções \(a(t)\), \(b(t)\) e defina o interpolante8

\[ x_t = a(t)\, x_1 + b(t)\, x_0 \]

Todo método deste módulo é uma escolha de \(a\) e \(b\):

Método \(a(t)\) \(b(t)\) Formato do caminho
DDPM / difusão \(\sqrt{\bar\alpha_t}\) \(\sqrt{1 - \bar\alpha_t}\) Curvo: \((b, a)\) num quarto de círculo
Flow matching (caminho OT) \(t\) \(1 - t\) Reto, por par
Fluxo retificado3 \(t\) \(1 - t\) Reto e reacoplado

Aqui \(\bar\alpha_t\) é o cronograma de ruído do capítulo 20 lido de trás para frente: vai de 0 no ruído a 1 nos dados. Com o cronograma cosseno ele é \(\bar\alpha_t = \operatorname{sen}^2(\pi t/2)\), então \(a = \operatorname{sen}(\pi t/2)\) e \(b = \cos(\pi t/2)\). OT é optimal transport (transporte ótimo), o nome que Lipman et al. dão ao caminho reto. Um par sob os dois interpolantes (escolha \(t\)):

t =
O mesmo par de ruído e dado sob dois interpolantes. À esquerda, os pesos (b, a): o flow matching anda na reta a + b = 1, a difusão no quarto de círculo a² + b² = 1. À direita, o par no plano: o flow matching vai de x0 a x1 em linha reta com velocidade constante x1 − x0; a difusão segue uma curva e a velocidade dela, a′x1 + b′x0, muda no caminho. Os botões escolhem t. OS PESOS: (b, a) 011 b: peso do ruído a: peso do dado a + b = 1 a² + b² = 1 UM PAR: xt​ = a·x1​ + b·x0​ 0 x0​ (ruído) x1​ (dado) setas: 0,25 × velocidade flow matching: a = t, b = 1 − t difusão: a = sen(πt/2), b = cos(πt/2)

A velocidade condicional é \(a'(t)x_1 + b'(t)x_0\) em todos os casos e a marginal é a esperança condicional dela. Um framework, uma perda, um código. Com um \(p_0\) gaussiano as duas visões são exatamente intercambiáveis: um modelo treinado de um jeito pode ser amostrado do outro. No caminho linear, o sampler determinístico DDIM é o passo de Euler do fluxo9 (nos outros cronogramas, é um passo de Euler em variáveis reescaladas). As diferenças restantes são a ponderação da perda ao longo de \(t\) e o formato da trajetória — que é o que o próximo painel mede.

O que "caminhos mais retos" de fato significa

A afirmação padrão é que o flow matching dá trajetórias retas e por isso precisa de menos passos de integração. É meio verdade e a metade que é falsa vale conhecer.

Tudo naquele painel é exato — o alvo é uma mistura de gaussianas, então as velocidades marginais dos dois interpolantes têm forma fechada e nada é treinado. Compare os dois e:

  • O caminho condicional — a reta entre uma amostra de ruído e uma de dados — é reto por construção com o interpolante linear.
  • O caminho marginal, que é o que o modelo de fato aprende, não é. Ele precisa fazer média sobre todo ponto de dados compatível com a posição atual e ruído e dados acoplados de forma independente se cruzam o tempo todo. Neste alvo, os caminhos do interpolante linear saem mais curvos que os de difusão: 111% mais longos que a reta contra 58%.
  • Nenhum interpolante vence em todo número de passos (com 2 passos o erro do ponto final da difusão é menor; com 8, o do linear) e passados uns 32 passos os dois ficam abaixo de qualquer coisa que se veja. O argumento inteiro é sobre o regime de poucos passos.

Em imagens reais os resultados divergem e a ponderação da perda ao longo de \(t\) importa tanto quanto o caminho. Lipman et al. contaram as avaliações de que um solver adaptativo precisa: 122–142 com o caminho linear contra 183–193 com o caminho de difusão na mesma arquitetura, no CIFAR-10 e no ImageNet 32 e 641 — de 22 a 37% a menos, não uma ordem de grandeza. Esser et al. treinaram 61 formulações para o Stable Diffusion 3: as variantes de fluxo retificado foram as melhores ao amostrar com poucos passos, mas com \(t\) uniforme o fluxo retificado ficou abaixo da clássica predição de \(\epsilon\) no geral e só com a amostragem logit-normal de timesteps (abaixo) ele ficou em primeiro7. O laboratório treina os dois caminhos no MNIST com \(t\) uniforme e o mesmo orçamento: o caminho cosseno da difusão vence em todo número de passos (FD 94,0 contra 133 com 8 passos de Euler). O FD é a receita do FID, a distância de Fréchet entre os atributos que uma rede extrai de imagens geradas e de imagens reais, com um classificador de dígitos no lugar da rede Inception; menor é melhor.

A vantagem real do flow matching não é a trajetória

É o objetivo: uma única regressão, sem cronograma a ajustar e sem a escolha entre prever \(\epsilon\) ou \(\mathbf{v}\) (capítulo 20) para errar em ruído alto. A equipe do Movie Gen, que treinou os dois, relata o flow matching como mais robusto à escolha do cronograma de ruído e melhor que as perdas de difusão que testou10. Isso, mais que o número de passos, é o motivo de SD3, FLUX e os modelos de vídeo o terem adotado. O interpolante sozinho economiza dezenas por cento dos passos; ir de cinquenta passos para quatro ou um exige reflow ou destilação, que é a próxima seção.

Fluxo retificado: endireitar de propósito

Se os caminhos não são retos, endireite-os3. O reflow são dois passos:

  1. Sorteie ruído \(z\), integre a ODE treinada com precisão, obtenha \(x = \text{ODE}(z)\).
  2. Retreine o modelo nos pares \((z, x)\) que ele mesmo produziu, na reta entre eles.

A distribuição marginal de \(x\) não muda — você não está alterando o que o modelo gera, apenas qual ruído é pareado com qual saída. E o novo pareamento é um que o modelo consegue realizar quase com retas: os caminhos do fluxo não se encontram, então as retas entre seus pontos finais raramente se cruzam. Uma reta é integrada exatamente por um passo de Euler. Os mesmos passos com seis amostras de ruído e os dois pontos de dados de antes:

Seis amostras de ruído e dois pontos de dados, A e B. Passo 1: o treino liga cada amostra de ruído a um ponto de dados sorteado por uma reta e as retas se cruzam. Passo 2: o fluxo aprendido curva os caminhos para que nunca se encontrem; quatro das seis chegam ao outro ponto de dados. Passo 3: um passo de Euler nesse fluxo leva todas as amostras à média dos dados, (0, 0). Passo 4: o reflow pareia cada amostra com o fim do próprio caminho, por uma reta. Passo 5: depois do reflow, um passo de Euler cai nos dados. ruído 𝒩(0, I) média dos dados A = (2, 0)B = (−2, 0) passe o mouse numa amostra de ruído amostra de ruído zponto de dados

Marque depois de um reflow ideal no painel de caminhos acima: a curvatura (quanto os caminhos são mais longos que a reta entre as pontas deles) e o erro vão a zero em qualquer número de passos. Esse é o limite, um modelo que aprendeu as novas retas de forma exata. Um reflow treinado chega perto: nas oito gaussianas do laboratório ele derruba a curvatura de 88% para 0,1% e faz um passo valer mais que 8 do modelo original; no MNIST, um passo vai de FD 2255 para 201. Mas não sai de graça. Cada rodada precisa de um conjunto grande de pares gerados com a ODE completa, os erros do primeiro modelo ficam gravados neles e, em imagens, um reflow deixou uma diferença visível até a receita de treino ser refeita (o fluxo 2-retificado no CIFAR-10 foi de um FID de um passo de 12,21 para 3,07 com uma inicialização, uma amostragem de timesteps e uma perda melhores)11. O InstaFlow rodou reflow mais destilação no Stable Diffusion para texto-imagem em um passo, em 202312.

O nome diz menos do que parece

SD3 e FLUX são chamados de modelos de fluxo retificado e nenhum dos dois artigos descreve uma etapa de reflow. No artigo do SD3 o nome se refere ao interpolante reto \((1-t)\,x + t\,\epsilon\) de Liu et al. (dado \(x\) em \(t = 0\)), que é o caminho de flow matching deste capítulo7. As versões de poucos passos que foram lançadas saíram de destilação: o FLUX.1 [schnell] por destilação adversarial de difusão latente (1–4 passos) e o SD3.5 Large Turbo por destilação adversarial de difusão (4 passos)13.

Menos passos: de velocidades a saltos

O reflow endireita o campo para que uma integração curta seja precisa. A outra linha de trabalho para de integrar: treina a rede para prever onde a trajetória termina depois de um salto de qualquer tamanho, um mapa de fluxo \(X_{s \to t}(x)\): o ponto, no instante \(t\), da trajetória que passa por \(x\) no instante \(s\)14. A velocidade instantânea é o limite de um salto de comprimento zero e um sampler de um passo é o salto de 0 a 1.

Método O que a rede aprende Resultado
Modelos de consistência4 O mapa de qualquer ponto de uma trajetória até o ponto final; a autoconsistência ao longo da trajetória é a perda. O sCM (2025) fez a versão de tempo contínuo treinar de forma estável em escala15 FID de 2 passos 1,88 no ImageNet 512
Modelos de atalho5 A velocidade e o tamanho do passo: um salto de \(2d\) precisa ser igual a dois saltos de \(d\) Um modelo para 1, 4 ou 128 passos
MeanFlow6 A velocidade média num intervalo, por uma identidade que a liga à instantânea FID de 1 passo 3,43 no ImageNet 256, do zero; 1,72 na versão melhorada (dez. 2025)16
Destilação adversarial (ADD, LADD) Um aluno de poucos passos de um modelo treinado, com um discriminador — a GAN do capítulo 18 — mantendo nítidos os passos únicos O que FLUX.1 [schnell] e SD3.5 Turbo lançaram

Os métodos de pesquisa (os três primeiros) treinam modelos de um passo do zero no ImageNet; o que chega aos produtos em 2026 ainda é, na maior parte, destilação de um modelo de flow matching de muitos passos, adversarial ou por casamento de distribuições. Os dois partem do campo que este capítulo treina.

Escolhas de treino que importam

A perda é uma linha, mas três escolhas em volta dela mudaram entre os primeiros artigos e os modelos atuais. Você vai encontrar as três em qualquer código recente:

  • Onde em \(t\) treinar. Um \(t\) uniforme desperdiça esforço perto das pontas, onde o alvo é fácil. O SD3 sorteia \(t\) de uma logit-normal, concentrada no meio7; o HunyuanVideo faz o mesmo. As políticas de robôs π0 e GR00T usam uma distribuição Beta que favorece a ponta ruidosa17.
  • Deslocar com a resolução. Com mais pixels ou tokens, um mesmo nível de ruído esconde menos da imagem, então imagens grandes e vídeos deslocam os timesteps para o lado do ruído, por um fator que cresce com o número de tokens (SD3, LTX-Video). É o deslocamento de timestep do painel de SNR do capítulo 20.
  • O que a rede devolve. Velocidade é o padrão, mas a rede pode prever \(x_1\) (o dado limpo) ou o ruído, todos conversíveis dado \(t\). Li e He argumentam que prever o dado limpo diretamente é o que deixa um Transformer simples gerar no espaço de pixels com patches grandes18 — um resultado de 2025 que reabriu uma escolha que todos davam por resolvida.

Onde é usado

Flow matching não é mais uma alternativa de nicho. Onde o objetivo de treino é publicado, a geração atual de modelos generativos o usa — mas não em toda parte. Alguns dos sistemas mais conhecidos nem dizem o que usam.

Domínio Modelos (primeiro lançamento) O que flui
Imagem Stable Diffusion 3 (2024)7, FLUX.1 (ago. 2024)2, FLUX.1 Kontext (maio 2025), Qwen-Image (ago. 2025), Z-Image (nov. 2025), FLUX.2 (nov. 2025)19 Um latente de VAE, por um MMDiT ou um DiT de fluxo único
Vídeo Movie Gen (out. 2024)10, HunyuanVideo (dez. 2024), LTX-Video, Wan 2.1 (fev. 2025)20, Open-Sora 2.0 Um latente espaço-temporal, dividido em patches no espaço e no tempo
Fala, áudio, música Voicebox (2023)21, Matcha-TTS, CosyVoice, F5-TTS (2024), Movie Gen Audio, ACE-Step (2025) Espectrogramas mel ou latentes de áudio, condicionados em texto e numa amostra de voz
Políticas de robôs π0 (out. 2024)17, π0.5, GR00T N1 (mar. 2025), SmolVLA Um bloco de ações futuras (50 passos no π0), condicionado num modelo de visão e linguagem
Proteínas FrameFlow, FoldFlow (2023), Proteina (2025) Coordenadas ou frames da cadeia principal; nos frames, flow matching numa variedade22
Dentro de LLMs multimodais JanusFlow (2024), BAGEL (2025) Uma cabeça de imagem treinada com fluxo retificado ao lado da perda de próximo token

Duas coisas nessa tabela merecem uma segunda olhada. Na robótica, o flow matching venceu por um motivo que não é qualidade de imagem: o π0 precisa de uns 10 passos de Euler para um bloco de 50 ações, rápido o bastante para controle a até 50 Hz. Ele também consegue representar uma distribuição de ações com vários modos, onde uma cabeça de regressão faria a média deles numa ação que não corresponde a nenhum17. No vídeo, o pipeline é o mesmo das imagens — só o latente ganha um eixo de tempo.

O que não é flow matching ensina tanto quanto: o AlphaFold 3 usa um módulo de difusão padrão; o CogVideoX treina com difusão de predição \(\mathbf{v}\); o Stable Audio Open com o objetivo \(\mathbf{v}\); Sora e Veo 3 são descritos por quem os fez como modelos de difusão, sem que o objetivo seja revelado. Dada a equivalência acima a fronteira é fina e o rótulo importa menos que o interpolante, o alvo e a ponderação dos timesteps.

O FLUX.1-dev em 1024 × 1024, com o formato do que passa entre as partes. O campo de velocidades deste capítulo é a caixa do meio, agora condicionado também ao texto, \(c\); tudo em volta dela é a estrutura da difusão latente do capítulo 20 e o Transformer em si é o capítulo 22. O FLUX.2 mantém o esquema com um Transformer de 32B e troca os dois encoders de texto por um modelo de visão e linguagem de 24B19.

O FLUX.1-dev gerando uma imagem de 1024 × 1024. O prompt vai a dois encoders de texto congelados: o CLIP-L dá um vetor agregado de 768 (que junto com o tempo t modula todo bloco, via adaLN) e o T5-XXL dá 512 tokens de 4096, que entram na atenção junto com os tokens da imagem. O ruído z0, 16 × 128 × 128, é cortado em patches de 2 × 2, 4096 tokens de 64. O Diffusion Transformer de 12B prevê uma velocidade e um solver de ODE dá de 20 a 50 passos de t = 0 (ruído) a t = 1 (dado); o latente z1, 16 × 128 × 128, passa uma vez pelo decoder do VAE e vira uma imagem 3 × 1024 × 1024. prompt texto ruído z0​ 16 × 128 × 128 CLIP-L vetor agregado · 768 T5-XXL 512 tokens × 4096 patches 2 × 2 4096 tokens × 64 Diffusion Transformer · 12B fluxo retificado adaLN: CLIP + t atenção conjunta tokens de texto e imagem tokens da imagem prevê vθ​(x, t, c) x ← x + Δt · vθ​(x, t, c) 20–50 passos, t de 0 (ruído) a 1 (dado) latente z1​ 16 × 128 × 128 decoder do VAE ×8 por lado, 16 → 3 canais imagem 3 × 1024 × 1024

Amostragem

O treino te dá um campo de velocidade. Transformá-lo numa amostra é integração de ODE e o solver é escolha sua — a mesma separação do capítulo 20.

import torch

@torch.no_grad()
def sample_euler(model, shape, n_steps=25, device='cuda'):
    """Primeira ordem. Uma avaliação do modelo por passo."""
    x = torch.randn(shape, device=device)             # x em t = 0 é ruído puro
    dt = 1.0 / n_steps
    for i in range(n_steps):
        t = torch.full((shape[0],), i * dt, device=device)
        x = x + dt * model(x, t)
    return x

@torch.no_grad()
def sample_heun(model, shape, n_steps=15, device='cuda'):
    """Segunda ordem: duas avaliações por passo, mas muito menos erro por passo."""
    x = torch.randn(shape, device=device)
    dt = 1.0 / n_steps
    for i in range(n_steps):
        t  = torch.full((shape[0],), i * dt, device=device)
        t2 = torch.full((shape[0],), (i + 1) * dt, device=device)
        v1 = model(x, t)
        v2 = model(x + dt * v1, t2)                   # preditor, depois correção
        x = x + dt * (v1 + v2) / 2
    return x

Conte avaliações do modelo, não passos: Heun com 8 passos custa o mesmo que Euler com 16. No modelo de MNIST do laboratório o Heun perde com poucas avaliações (FD 550 contra 226 do Euler com 4) e vence de 16 em diante (89,7 contra 99,3): um passo de segunda ordem precisa de passos pequenos o bastante para que a correção dele acerte.

Lendo um código de flow matching

Três convenções diferem entre artigos e custam uma tarde se você presumir errado: se \(t = 0\) é ruído ou dados (este capítulo usa ruído; o artigo do SD3 e muitos códigos põem os dados em \(t = 0\)), se o modelo prevê velocidade, \(x_1\) ou \(\epsilon\) (todos interconversíveis, dados \(t\) e o interpolante) e se \(t\) é passado como número em \([0,1]\) ou como índice inteiro de timestep. Confira as três antes de depurar qualquer outra coisa. O Flow Matching Guide and Code, da Meta, enuncia todas numa notação só e vem com uma biblioteca de referência em PyTorch23.

Laboratório: flow matching do zero

As afirmações do capítulo são medidas num notebook do Colab que treina modelos de flow matching de ponta a ponta, primeiro em duas dimensões, onde o campo exato é conhecido, depois no MNIST. Roda no plano gratuito: CPU basta para as seções 1–5 e as seções do MNIST pedem uma GPU T4 (Ambiente de execução → Alterar o tipo de ambiente de execução → GPU T4); a execução de referência de todas as células levou de 15 a 25 minutos numa GPU de notebook da Apple dividida com outros processos, mais lenta que uma T4. Oito seções, cada uma terminando num checkpoint com um valor de verificação:

  1. o campo marginal exato de uma mistura 2-D e o piso da perda, calculados;
  2. um MLP de velocidade treinado até esse piso e a distância dele até o campo exato;
  3. amostragem: erro do ponto final e distância aos dados contra o número de passos, Euler contra Heun a custo igual e a curvatura dos caminhos aprendidos;
  4. o interpolante de difusão com o mesmo código e qual dos dois é mais reto;
  5. uma rodada de reflow e o que ela faz com a curvatura e com amostras de um passo;
  6. MNIST: uma U-Net pequena treinada com a mesma perda, avaliada por uma distância de Fréchet;
  7. um passo cai no dígito médio; Heun e o interpolante de difusão em imagens;
  8. reflow no MNIST e uma tarefa aberta: timesteps logit-normais, com uma tabela para preencher.

Abrir o laboratório no Colab — salve uma cópia no seu Drive (Arquivo → Salvar uma cópia no Drive) para rodar e editar.

Pontos principais

  1. O flow matching aprende um campo de velocidade e amostra integrando uma ODE. A perda é um único erro quadrático, sem cronograma e sem limite variacional.
  2. A velocidade marginal é intratável, mas regredir a condicional tem o mesmo gradiente. Esse teorema é o método inteiro. Uma consequência: a perda tem um piso acima de zero.
  3. Difusão é flow matching com um interpolante curvo. \(a(t) = \sqrt{\bar\alpha_t}\) em vez de \(a(t) = t\). Um framework cobre os dois; no caminho linear, o DDIM é exatamente o passo de Euler do fluxo.
  4. "Caminhos retos" vale para o caminho condicional. O caminho marginal — o que o modelo aprende — não é reto; ele repareia ruído e dados para que os caminhos nunca se encontrem.
  5. Em imagens o caminho linear economiza no máximo cerca de um terço dos passos do solver e só com a ponderação certa ao longo de \(t\); com \(t\) uniforme um bom cronograma de difusão pode vencê-lo, como no laboratório. Os motivos maiores para adotá-lo são o objetivo (simples, robusto ao cronograma) e a receita em volta dele: timesteps logit-normais, deslocamento por resolução.
  6. O reflow endireita o campo retreinando nos pares do próprio modelo. Funciona, ao custo de gerar esses pares. O "fluxo retificado" de SD3 e FLUX é o interpolante reto, não o reflow.
  7. A geração em um passo vem de aprender saltos em vez de velocidades — consistência, atalho, MeanFlow — e, nos modelos lançados, de destilação (FLUX.1 [schnell], SD3.5 Turbo).
  8. Desde 2024 o objetivo é compartilhado por modelos de imagem, vídeo, fala e ações de robôs: um \(p_1\) diferente, a mesma linha de código.


  1. Lipman, Y., Chen, R. T. Q., Ben-Hamu, H., Nickel, M., & Le, M. (2023). Flow Matching for Generative Modeling — ICLR. O teorema do flow matching condicional é a seção 3 e é curta; as avaliações do solver estão na tabela 1 (solver adaptativo; o DDPM precisa de 262–274 nos mesmos benchmarks). ↩↩↩

  2. Black Forest Labs (2024). Announcing Black Forest Labs e FLUX.1 — um modelo de 12B "construído sobre flow matching"; o [dev] é destilado em guidance a partir do [pro]. ↩

  3. Liu, X., Gong, C., & Liu, Q. (2023). Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flow — ICLR. Fluxo retificado e o procedimento de reflow. ↩↩

  4. Song, Y., Dhariwal, P., Chen, M., & Sutskever, I. (2023). Consistency Models — ICML. ↩

  5. Frans, K., Hafner, D., Levine, S., & Abbeel, P. (2025). One Step Diffusion via Shortcut Models — ICLR. Condicione no tamanho do passo e um modelo serve a qualquer orçamento de passos. ↩

  6. Geng, Z., Deng, M., Bai, X., Kolter, J. Z., & He, K. (2025). Mean Flows for One-step Generative Modeling — NeurIPS. Velocidade média em vez de instantânea e geração de um passo sem estágio de destilação. ↩

  7. Esser, P., et al. (2024). Scaling Rectified Flow Transformers for High-Resolution Image Synthesis — ICML. SD3. A seção 5.1 compara 61 formulações (interpolantes, alvos e amostradores de timestep); o mesmo artigo introduz a amostragem logit-normal de timesteps e o deslocamento dependente da resolução. ↩↩↩↩

  8. Albergo, M. S., Boffi, N. M., & Vanden-Eijnden, E. (2023). Stochastic Interpolants: A Unifying Framework for Flows and Diffusions. A formulação geral \(a(t), b(t)\) usada na tabela. ↩

  9. Diffusion Meets Flow Matching: Two Sides of the Same Coin (2025), post de blog; os autores não são nomeados na página. "Modelos de difusão e flow matching gaussiano são a mesma coisa", demonstrado sampler a sampler. ↩

  10. Polyak, A., et al. (2024). Movie Gen: A Cast of Media Foundation Models. Flow matching para vídeo (seção 3.1.2) e para áudio (seção 6); a comparação com perdas de difusão está na seção 3.6.2. ↩↩

  11. Lee, S., Lin, Z., & Fanti, G. (2024). Improving the Training of Rectified Flows — NeurIPS. Por que um reflow costuma bastar e quanto ele custa. ↩

  12. Liu, X., Zhang, X., Ma, J., Peng, J., & Liu, Q. (2024). InstaFlow: One Step is Enough for High-Quality Diffusion-Based Text-to-Image Generation — ICLR. ↩

  13. Model cards: FLUX.1 [schnell] ("treinado com destilação adversarial de difusão latente") e Stable Diffusion 3.5 Large Turbo (destilação adversarial de difusão, 4 passos). ↩

  14. Boffi, N. M., Albergo, M. S., & Vanden-Eijnden, E. (2024). Flow Map Matching. Modelos de consistência, de atalho e de fluxo médio como maneiras de aprender o mapa de dois tempos. ↩

  15. Lu, C., & Song, Y. (2025). Simplifying, Stabilizing and Scaling Continuous-Time Consistency Models — ICLR. ↩

  16. Geng, Z., Lu, Y., Wu, Z., Shechtman, E., Kolter, J. Z., & He, K. (2025). Improved Mean Flows: On the Challenges of Fastforward Generative Models. Preprint. ↩

  17. Black, K., et al. (2024). π0: A Vision-Language-Action Flow Model for General Robot Control. O especialista de ações, blocos de 50 ações, 10 passos de integração e uma distribuição Beta de timesteps; o GR00T N1 (Bjorck et al., 2025) usa 4 passos para blocos de 16. ↩↩↩

  18. Li, T., & He, K. (2025). Back to Basics: Let Denoising Generative Models Denoise. Preprint. ↩

  19. Black Forest Labs (2025). FLUX.2 — "uma arquitetura de flow matching latente", um modelo de visão e linguagem Mistral-3 de 24B com um Transformer de fluxo retificado; 32B de parâmetros segundo o model card do FLUX.2 [dev]. ↩↩

  20. Wan Team (2025). Wan: Open and Advanced Large-Scale Video Generative Models. O objetivo de flow matching é a seção 4.2.2. HunyuanVideo (Kong et al., 2024) e LTX-Video (HaCohen et al., 2024) enunciam o mesmo objetivo. ↩

  21. Le, M., et al. (2023). Voicebox: Text-Guided Multilingual Universal Speech Generation at Scale — NeurIPS. O F5-TTS (Chen et al., 2024) é flow matching com um Transformer de difusão. ↩

  22. Chen, R. T. Q., & Lipman, Y. (2024). Flow Matching on General Geometries — ICLR. Flow matching riemanniano, a base dos modelos de proteínas baseados em frames (FrameFlow, FoldFlow). ↩

  23. Lipman, Y., Havasi, M., Holderrieth, P., Shaul, N., Le, M., Karrer, B., Chen, R. T. Q., Lopez-Paz, D., Ben-Hamu, H., & Gat, I. (2024). Flow Matching Guide and Code. Com o pacote PyTorch flow_matching. ↩