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 \]

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, os últimos quatro capítulos colapsam numa ideia só.

Movendo partículas

Você tem partículas distribuídas como \(p_0 = \mathcal{N}(0, I)\). Você as quer distribuídas como seus dados 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 \]

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\). Você não consegue calcular isso. 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 movimento que o DDPM faz ao regredir \(\epsilon\) em vez do score. Mesmo truque, enunciado uma vez e em geral, em vez de uma vez por cronograma de ruído.

A difusão é um caso particular

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

\[ 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 — um quarto de círculo
Flow matching (caminho OT) \(t\) \(1 - t\) Reto, por par
Fluxo retificado3 \(t\) \(1 - t\) Reto e reacoplado

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. 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 aprendidos com o interpolante linear saem mais curvos que os de difusão.
  • Passados uns 32 passos, os dois interpolantes convergem para o mesmo erro. O argumento inteiro é sobre o regime de poucos passos.

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

É o objetivo: uma única regressão sem ponderação, sem cronograma a ajustar, com peso uniforme ao longo de \(t\) e sem a decisão \(\epsilon\)-versus-\(\mathbf{v}\) para errar em ruído alto. É por isso que SD3 e FLUX o adotaram. Afirmações de "2–10× menos passos" vindas só do interpolante não sobrevivem a uma medição cuidadosa; os ganhos de passos vêm de reflow e 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. Mas o acoplamento agora é um que o modelo consegue realizar com uma reta e uma reta é integrada exatamente por um passo de Euler.

Marque depois de um reflow no painel e a curvatura vai a zero e o erro vai a zero em qualquer número de passos. É esse o mecanismo por trás da geração de um passo e de poucos passos e é por isso que SD3 e FLUX são descritos como modelos de fluxo retificado e não meramente de flow matching.

Para onde vai a partir dali Ideia
Modelos de consistência4 Treinar o mapa de qualquer ponto da trajetória direto para o ponto final. Autoconsistência é a perda.
Modelos de atalho5 Condicionar a rede no próprio tamanho do passo, para que um modelo sirva a 1, 4 ou 128 passos.
MeanFlow6 Aprender a velocidade média num intervalo em vez da instantânea — geração de um passo sem estágio separado de destilação.

Onde é usado

Flow matching não é mais uma alternativa de nicho; é sobre ele que a geração atual de modelos está construída.

Modelo Para que usa
Stable Diffusion 37 Fluxo retificado + MMDiT, com deslocamento de timestep dependente da resolução
FLUX.1 Fluxo retificado + um DiT de 12B, dois encoders CLIP e T5-XXL
Modelos de vídeo e áudio O mesmo objetivo, sem mudanças, sobre um latente temporal
Moléculas e proteínas Flow matching em variedades — o framework não assume dados euclidianos
Políticas de robôs Blocos de ações como um fluxo; o mesmo código, um \(p_1\) diferente
flowchart LR
    A["Texto<br/>(prompt)"] --> B["Encoders de texto<br/>CLIP + T5-XXL"]
    N["Ruído<br/>z₀ ~ N(0,I)"] --> C
    B --> C["Diffusion Transformer<br/>fluxo retificado"]
    C -->|"ODE: 20–50 passos"| D["Latente z₁"]
    D --> E["Decoder VAE"]
    E --> F["Imagem 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.
       A custo igual, bate o Euler assim que o campo tem qualquer curvatura."""
    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

Lendo um código de flow matching

Três convenções diferem entre artigos e custam uma tarde se você assumir: se \(t = 0\) é ruído ou dados (este capítulo usa ruído), 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.

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.
  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.
  4. "Caminhos retos" vale para o caminho condicional. O caminho marginal — o que o modelo aprende — não é reto e pode ser mais curvo que o da difusão.
  5. A vantagem real é o objetivo: mais simples, sem ponderação, sem cronograma para errar. É por isso que SD3 e FLUX o adotaram.
  6. O reflow entrega retidão de verdade, reacoplando cada amostra de ruído com a saída que ela já produz. É o que torna a geração de um passo possível.
  7. Modelos de consistência, de atalho e o MeanFlow atacam o mesmo alvo: colapsar a trajetória em menos avaliações.
  8. Passados ~32 passos o interpolante deixa de importar. Todo argumento aqui é sobre o regime de poucos passos.


  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. ↩↩

  2. Black Forest Labs (2024). FLUX.1. ↩

  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. 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 ablação de interpolantes e ponderações de timestep na seção 3 é a comparação publicada mais útil. ↩

  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 acima. ↩