算法可视化与交互学习平台

学习 Flow Matching:从 Diffusion 到 Rectified FlowFlow Matching and Rectified Flow: From Diffusion to Straight ODE Paths

承接 No.4 VAE、No.5 DDPM、No.10 Latent Diffusion、No.11 条件生成与 No.12 DiT,把生成目标从预测噪声改写为学习连续速度场,理解 Flow Matching、Rectified Flow、Reflow 与 ODE 采样,并用 Tiny DiT 在 latent 中完成条件生成。

Deep LearningIntermediateFree
Kernel
1

先抓住 Flow Matching 的核心直觉

Flow Matching 的一句话版本:

不再问模型:这份 noisy latent 里混入了多少 epsilon? 而是问模型:位于时间 t 的这个样本,现在应该朝哪个方向、以多快的速度移动?

No.12 的 DiT 仍然可以处理 latent patch tokens,No.11 的条件仍然可以通过 adaLN-Zero 或 Cross Attention 进入网络,No.4 的 VAE 仍然负责 image 与 latent 的互译。真正改变的是监督答案与采样规则:模型从 epsilon_theta(z_t,t,c) 变成速度场 v_theta(z_t,t,c),生成过程从 DDPM Scheduler 更新变成求解一条 ODE 轨迹。

2

从 No.4、5、10、11、12 走到 No.13

已有模块继续保留No.13 新变化
No.4 VAEimage ↔ latent速度场直接在压缩 latent 中学习
No.5 DDPM从噪声生成数据的任务epsilon target 换成 velocity target
No.10 Latent Diffusion生成变量仍是 z不再依赖 alpha_bar / beta schedule
No.11 Cross Attention / CFG条件输入与有/无条件分支CFG 合并 velocity,而不是 epsilon
No.12 DiTPatchify、Self-Attention、adaLN-Zero、Unpatchify输出张量的数学含义变成 dz/dt
No.12:DiT 改变谁来预测,DDPM 目标没有变 No.13:DiT 可以不变,但预测目标与采样动力学改变 保留:VAE + latent + condition + DiT 替换:noise schedule + epsilon loss + DDPM step 为:continuous path + velocity loss + ODE solver
3

DDPM vs Flow Matching:究竟改变了什么

维度DDPM / Latent DiffusionFlow Matching / Rectified Flow
中间样本由 alpha_t、sigma_t 构造 noisy z_t由选定概率路径构造 z_t
监督答案通常是加入的 epsilon路径在该点的条件速度 u_t
模型输出epsilon_theta 或其他 diffusion 参数化v_theta = dz/dt
生成动力学Reverse SDE / DDPM step / probability-flow ODE直接求解 learned ODE
时间离散Scheduler 管理噪声日程和步进公式ODE solver 管理时间网格与积分精度
随机性取决于 sampler,可逐步注入噪声给定初始噪声后,常规 ODE 轨迹是确定的
4

连续流 ODE:速度场怎样搬运概率分布

速度场 v_theta 接收当前位置 z_t、连续时间 t 和可选条件 c,输出与 z_t 同形状的瞬时变化率 dz_t/dt。它是样本空间或 latent 空间中的几何切向量:方向表示各分量接下来怎样变化,长度表示单位时间内变化多快。对这条常微分方程沿正向或反向积分,就能在两个端点分布之间搬运样本;本模块生成时固定从 t=1 的噪声反向走到 t=0 的数据。

时间 t 的中间样本或 latent
state at continuous time t
神经网络表示的速度场
learned neural velocity field
类别或文本条件;无条件时可省略
optional class or text condition
Euler、Heun 等数值积分过程
numerical ODE integration

局部规则如何形成完整生成

模型每次只回答当前位置应该往哪里走;把许多局部速度连续积分,才得到从噪声到数据的完整轨迹。

current z_t -> v_theta(z_t,t,c) -> small update repeat over t -> generated z

速度不是 MLP,MLP 可以学习速度

Flow Matching 规定网络输出的数学含义是 velocity,并不规定网络必须是哪一种结构。二维点可以用 MLP,图像可以用 U-Net,latent patch tokens 可以继续使用 No.12 的 DiT。

2D: [x,y] + t -> MLP -> [v_x,v_y] latent: [B,C,H,W] + t,c -> U-Net / DiT -> [B,C,H,W]

高维速度仍然是几何向量

在二维空间中可以把速度画成箭头;在图像 latent 中,每个输出数字表示对应 latent 分量的瞬时变化率。它不是物体在画面中的物理移动,也不等同于 optical flow 或 Attention 指向哪个 patch。

z_t.shape == v_theta(z_t,t,c).shape VAE Decoder 把高维 latent 变化显现为轮廓、边缘与语义变化
5

直线路径:从 clean latent 走向 Gaussian noise

本模块固定 z_0 为 clean data latent、z_1 为 Gaussian noise,t=0→1 表示加噪方向。线性插值的条件速度对同一对端点是常量;生成时从 t=1 的噪声反向积分回 t=0。部分资料会交换两个端点,数学等价,但符号方向必须前后一致。

干净数据或 VAE latent
clean data endpoint
从标准高斯采样的噪声端点
Gaussian noise endpoint
连续时间,训练时从 [0,1] 均匀采样
continuous time
给定一对端点时的真实条件速度
conditional target velocity
6

逐步演算:一个二维样本的路径与反向生成

计算真实条件速度
u = z1 - z0
  = [-1,3] - [2,1]
Initial Variables
z0_data
[2, 1]
z1_noise
[-1, 3]
t
0.25
Step 1 Variables
u
[-3, 2]
Step 1 / 4
7

Flow Matching 与 Rectified Flow:相近,但不是两个同义词

Flow Matching 是更广的训练框架:先指定一族连接源分布与目标分布的概率路径,再回归能产生这条路径的速度场。路径可以来自 diffusion,也可以采用 optimal-transport 风格或其他插值。

Rectified Flow 强调直线端点插值以及对生成耦合进行重新训练。第一次训练时,数据与噪声通常独立配对;模型学到的是许多条件直线速度在同一位置上的平均,因此实际 ODE 轨迹仍可能弯曲。

初始训练:data z0 与 independent noise z1 配对 ↓ 学到第一代 flow 从同一 noise z1 生成 z0_hat,形成模型自己的 coupling ↓ Reflow 用 (z0_hat, z1) 重新训练直线路径 ↓ 轨迹通常更直,少步积分误差可能更小
8

训练目标:回归路径速度,而不是回归噪声

训练程序能直接采样 clean z_0、Gaussian z_1 与时间 t,因此既知道中间点,也知道这对端点的条件速度。网络只需做一个普通 MSE 回归。对相同中间位置可能存在多条端点连线,最优网络学习的是条件速度的平均。

Flow Matching 均方误差
flow matching regression loss
线性条件路径的监督速度
linear conditional target velocity
由 MLP、U-Net 或 DiT 参数化的边际速度场
learned marginal velocity field

为什么速度标签天然已知

训练时 z_0、z_1 和 t 都由程序采样,因此既能构造当前位置 z_t,也能直接对路径求导得到监督答案。真正被优化的是 MLP、U-Net 或 DiT 的参数 theta。

z_t = (1-t) * z_0 + t * z_1 target_velocity = z_1 - z_0 predicted_velocity = network(z_t, t, c) loss = MSE(predicted_velocity, target_velocity)

单对端点速度与网络速度场

一对确定端点的直线速度是常量 z_1-z_0;但同一中间位置附近可能经过许多不同端点连线,因此最优网络学习给定位置、时间和条件后的平均方向。

v_theta(z_t,t,c) ≈ E[z_1-z_0 | z_t,t,c]

不要与 diffusion v-prediction 混淆

Diffusion 中常见的 v-parameterization 是 alpha、sigma、x0、epsilon 的特定线性组合;Flow Matching velocity 是所选概率路径对时间的导数。二者在特定路径和参数化下可以转换,但名字相同不代表监督目标天然相同。

diffusion v target != automatically dz_t/dt 先写清 path,再对 t 求导。
9

ODE Sampling:Euler、Heun 与 NFE

前一张卡已经说明了速度的几何含义;这张卡只解决另一个问题:如何用有限次速度预测走完整条轨迹。可以把速度场看成随时间变化的风向地图:网络负责“预测风”,ODE solver 负责“沿风走路”。

DiT / MLP:给定 z_t, t, c -> 预测局部速度 v_theta ODE solver:把多次局部速度 -> 累积成完整 z_1 -> z_0 轨迹

1. 先固定时间方向

本模块约定 t=0 是 clean data,t=1 是 Gaussian noise。模型监督速度按 data→noise 定义,而生成从 noise→data 反向积分,因此更新式出现减号。

训练:t = 0 -> 1,clean -> noise 生成:t = 1 -> 0,noise -> clean z_next = z_t - dt * velocity

2. Euler:看一眼方向就走

Euler 假设这一小段内速度保持不变。它只在当前点调用一次网络,然后沿当前速度走一步。

dt = 1 / steps k1 = v_theta(z_t, t, c) z_(t-dt) = z_t - dt * k1

二维数值代入

z_t = [1.20, -0.40] dt = 0.25 k1 = [0.80, -0.20] z_0.75 = [1.20, -0.40] - 0.25 * [0.80, -0.20] = [1.00, -0.35]

轨迹接近直线时,这个近似很有效;轨迹弯曲或速度变化很快时,单次起点读数会产生较大积分误差。

3. Heun:先试走,再校正

Heun 先按起点速度试走到临时终点,再询问一次终点速度,最后用两个速度的平均值完成正式更新。

k1 = v_theta(z_t, t, c) z_euler = z_t - dt * k1 k2 = v_theta(z_euler, t-dt, c) z_(t-dt) = z_t - dt * (k1+k2)/2
若 k1 = [0.80,-0.20],k2 = [0.60,-0.10] 平均速度 = [0.70,-0.15] Heun 结果 = [1.025,-0.3625]

Heun 同时参考区间起点与预测终点;一步内速度变化越明显,它通常越有优势。代价是需要更多网络调用。

4. Steps 与 NFE

ODE steps 是时间轴被切成多少段;NFE(Neural Function Evaluations)是速度网络实际被调用多少次,计算成本主要由 NFE 决定。

方法每步速度评估N 步时的 NFE直觉
Euler1N每段只看起点
标准 Heun2约 2N看起点与预测终点
本实验 Heun最后一步省去修正2N-1到 t=0 时少一次评估
12 steps,无 CFG:Euler NFE = 12,Heun NFE = 23 使用 CFG:每次速度评估包含 1 次 unconditional forward + 1 次 conditional forward Euler DiT forwards = 24 Heun DiT forwards = 46

因此 12-step Euler 与 12-step Heun 并不是相同计算预算。公平比较速度与质量时,还应同时观察 NFE。

5. 更多 steps 能修复什么

误差来源含义增加 steps
模型误差v_theta 没有学准真实速度场不能根治
积分误差有限步没有贴紧连续轨迹通常可以减小
4 -> 8 -> 16 steps 持续改善:瓶颈可能是积分精度 8 -> 16 -> 32 几乎不改善:瓶颈可能是模型、VAE 或训练 更多 steps 只能更准确地沿“已经学到的场”走, 不能把错误速度场自动变正确。

6. 为什么 Rectified Flow 关心直轨迹

轨迹越直,一小段内速度变化越少,Euler 的局部常速度假设越接近真实。Reflow 希望让模型自己的 coupling 更直,从而使少步采样更有机会接近高步结果。

观察现象判断建议
Euler 少步明显扭曲轨迹弯或步长过大增加 steps 或使用 Heun
Heun 少步明显更好一步内速度变化较大按相近 NFE 比较
高步数仍是错误类别条件速度场或训练有问题检查 loss、CFG 与数据
Reflow 后少步更接近高步轨迹可能被拉直这是 Reflow 生效信号

7. 把采样循环读成自然语言

z = Gaussian latent noise at t=1 for t from 1 down to 0: 1. 网络预测当前位置的 velocity 2. CFG 合并 conditional / unconditional velocity 3. Euler 或 Heun 更新 latent image = VAE Decoder(z at t=0)
10

二维 Rectified Flow 实验:看见速度场、轨迹与 Reflow

真实训练一个二维神经速度场,把标准高斯噪声搬运到目标分布。训练期间会像 DiT 实验一样实时追加 loss 曲线,并显示当前 Initial Flow / Reflow 阶段与 training step。目标样本会先随机打乱,确保双月等分组生成的数据在图表中被均匀展示。训练完成后,“观察生成 step”滑条会启用,可即时切换已保存的 step 0…N 样本分布与累计轨迹,不会重新训练。Reflow 主要负责拉直第一代轨迹,并不能自动修复第一代模型已经产生的分布偏差。双月推荐从 hidden=96、每轮 2400 steps、Heun 16~32 ODE steps 开始;若对称集合距离仍高于约 0.10,可把训练提高到 4000 steps 或 hidden=128。

Parameter Panel
9 Params
11

条件、DiT 与 CFG:这些部件为什么仍然成立

Flow Matching 规定模型输出的数学含义,但不限制网络内部结构。No.12 的 DiT 仍可把 z_t patchify 成 tokens,用 Self-Attention 建模空间关系,再把连续时间和类别条件通过 adaLN-Zero 注入各个 block。

No.12 DiT output: epsilon_theta(z_t,t,c) No.13 DiT output: v_theta(z_t,t,c) 输入形状不变:[B,C,H,W] 输出形状不变:[B,C,H,W] 改变的是每个输出数字代表什么

为什么叫残差 MLP

普通 MLP 直接输出 F(x);Transformer/DiT block 中的 MLP 分支会把修正量加回当前 token 表示,因此形成 Residual MLP。它不是一种全新的 MLP,而是 MLP 与 skip connection 的组合。

普通 MLP:y = F(x) 残差 MLP:y = x + gate * MLP(LayerNorm(x)) 含义: 保留当前 token 表示 x 只学习这一层需要补充的修正量

残差连接给梯度提供了直接通路,使深层 DiT 更稳定;adaLN-Zero 中的 gate 还可让 Attention 与 MLP 分支从接近零修正开始训练。

更新变化的对象所在轴目的
x ← x + MLP(x)DiT 隐藏 token网络层深度提炼用于预测速度的特征
z ← z - dt·v生成 latentODE 时间从噪声移动到数据

条件与 CFG 仍然成立

文字生成时,No.11 的 Cross Attention 不需要删除:图像 token 继续发出 Query,文字 token 继续提供 K/V。CFG 则把两个速度场方向合并:

随后 ODE solver 使用 v_cfg 更新 latent。Cross Attention 决定条件如何进入,CFG 决定放大哪条条件方向,ODE solver 决定怎样数值积分;三者职责保持分离。

12

Latent Rectified Flow + DiT:完整训练与生成链路

把前面的卡片串起来,完整系统可以拆成四个互不替代的职责:VAE 定义 latent 空间,路径定义监督速度,DiT 学习速度场,ODE solver 在生成时积分速度。

Training

image x -> VAE Encoder -> clean latent z0 noise z1 ~ N(0,I), continuous t ~ Uniform(0,1) zt = (1-t)z0 + t z1 target_velocity = z1 - z0 zt + t + condition -> DiT -> predicted_velocity MSE(predicted_velocity, target_velocity) -> update DiT

Inference

pure latent noise z1 at t=1 ↓ repeated Euler / Heun steps DiT predicts conditional velocity v_theta(zt,t,c) ↓ integrate backward t=1 -> 0 clean latent z0_hat ↓ VAE Decoder generated image
组件训练时生成时
VAE Encoder把真实图像变成 z0通常不用
路径与 target构造 z_t 与 z1-z0不直接执行
DiT回归真实条件速度反复预测当前位置速度
ODE solver不参与 loss把局部速度积分为完整轨迹
VAE Decoder用于检查 latent 质量最后输出图像

遇到问题时按职责排查

  1. 速度含义或输出形状不清楚:回看“连续流 ODE”。
  2. target 符号或 loss 不清楚:回看“直线路径”和“训练目标”。
  3. Euler、Heun、steps 或 NFE 不清楚:回看“ODE Sampling”。
  4. 条件、残差 MLP、Cross Attention 或 CFG 不清楚:回看“条件、DiT 与 CFG”。
13

Toy Rectified-Flow DiT:训练速度场,再用 ODE 从噪声生成

第一步训练 TinyVAE 与 adaLN-Zero Tiny DiT,Training Losses 会随真实训练 step 实时更新;DiT 的监督答案不再是 epsilon,而是线性路径速度 noise-clean。第二步加载当前页面保存的真实权重,使用 Euler 或 Heun 从纯 latent 噪声反向积分,并比较不同 ODE 步数。

Parameter Panel
13 Params
14

把 Toy Flow 代码逐行讲回公式

代码数学含义来自哪个模块
clean = encoder(image)得到数据端点 z0No.4 / No.10
noise = randn_like(clean)得到 Gaussian 端点 z1No.5
zt=(1-t)*clean+t*noise构造直线条件路径No.13
target=noise-clean对插值路径求时间导数No.13
pred=dit(zt,t,label)DiT 参数化条件速度场No.12 + No.13
loss=mse(pred,target)Conditional Flow MatchingNo.13
v=vu+s*(vc-vu)速度场 CFGNo.11
z=z-dt*v从噪声端反向 Euler 积分No.13
image=decoder(z)latent 返回像素空间No.4 / No.10

阅读真实实现时的检查顺序

  1. 先确认 clean/noise 分别对应 t=0 还是 t=1。
  2. 写出实际 interpolation,再对 t 求导,核对 target 符号。
  3. 确认模型输出是 epsilon、diffusion-v、score 还是 flow velocity。
  4. 确认 sampler 的时间方向以及 Euler/Heun 更新符号。
  5. 最后再看 U-Net、DiT、Cross Attention 与 CFG 的实现细节。

理论口径对应三条原始研究线索:Lipman 等人的 Flow Matching for Generative Modeling、Liu 等人的 Flow Straight and Fast / Rectified Flow,以及把 Rectified Flow 与 Transformer 图像生成结合的 Scaling Rectified Flow Transformers for High-Resolution Image Synthesis

AI
问问 LLM:把 Flow Matching 讲回 Diffusion 与 DiT