算法可视化与交互学习平台
学习 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 中完成条件生成。
先抓住 Flow Matching 的核心直觉
Flow Matching 的一句话版本:
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 轨迹。
从 No.4、5、10、11、12 走到 No.13
| 已有模块 | 继续保留 | No.13 新变化 |
|---|---|---|
| No.4 VAE | image ↔ 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 DiT | Patchify、Self-Attention、adaLN-Zero、Unpatchify | 输出张量的数学含义变成 dz/dt |
DDPM vs Flow Matching:究竟改变了什么
| 维度 | DDPM / Latent Diffusion | Flow 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 轨迹是确定的 |
连续流 ODE:速度场怎样搬运概率分布
速度场 v_theta 接收当前位置 z_t、连续时间 t 和可选条件 c,输出与 z_t 同形状的瞬时变化率 dz_t/dt。它是样本空间或 latent 空间中的几何切向量:方向表示各分量接下来怎样变化,长度表示单位时间内变化多快。对这条常微分方程沿正向或反向积分,就能在两个端点分布之间搬运样本;本模块生成时固定从 t=1 的噪声反向走到 t=0 的数据。
局部规则如何形成完整生成
模型每次只回答当前位置应该往哪里走;把许多局部速度连续积分,才得到从噪声到数据的完整轨迹。
速度不是 MLP,MLP 可以学习速度
Flow Matching 规定网络输出的数学含义是 velocity,并不规定网络必须是哪一种结构。二维点可以用 MLP,图像可以用 U-Net,latent patch tokens 可以继续使用 No.12 的 DiT。
高维速度仍然是几何向量
在二维空间中可以把速度画成箭头;在图像 latent 中,每个输出数字表示对应 latent 分量的瞬时变化率。它不是物体在画面中的物理移动,也不等同于 optical flow 或 Attention 指向哪个 patch。
直线路径:从 clean latent 走向 Gaussian noise
本模块固定 z_0 为 clean data latent、z_1 为 Gaussian noise,t=0→1 表示加噪方向。线性插值的条件速度对同一对端点是常量;生成时从 t=1 的噪声反向积分回 t=0。部分资料会交换两个端点,数学等价,但符号方向必须前后一致。
逐步演算:一个二维样本的路径与反向生成
u = z1 - z0
= [-1,3] - [2,1][2, 1]
[-1, 3]
[-3, 2]
Flow Matching 与 Rectified Flow:相近,但不是两个同义词
Flow Matching 是更广的训练框架:先指定一族连接源分布与目标分布的概率路径,再回归能产生这条路径的速度场。路径可以来自 diffusion,也可以采用 optimal-transport 风格或其他插值。
Rectified Flow 强调直线端点插值以及对生成耦合进行重新训练。第一次训练时,数据与噪声通常独立配对;模型学到的是许多条件直线速度在同一位置上的平均,因此实际 ODE 轨迹仍可能弯曲。
训练目标:回归路径速度,而不是回归噪声
训练程序能直接采样 clean z_0、Gaussian z_1 与时间 t,因此既知道中间点,也知道这对端点的条件速度。网络只需做一个普通 MSE 回归。对相同中间位置可能存在多条端点连线,最优网络学习的是条件速度的平均。
为什么速度标签天然已知
训练时 z_0、z_1 和 t 都由程序采样,因此既能构造当前位置 z_t,也能直接对路径求导得到监督答案。真正被优化的是 MLP、U-Net 或 DiT 的参数 theta。
单对端点速度与网络速度场
一对确定端点的直线速度是常量 z_1-z_0;但同一中间位置附近可能经过许多不同端点连线,因此最优网络学习给定位置、时间和条件后的平均方向。
不要与 diffusion v-prediction 混淆
Diffusion 中常见的 v-parameterization 是 alpha、sigma、x0、epsilon 的特定线性组合;Flow Matching velocity 是所选概率路径对时间的导数。二者在特定路径和参数化下可以转换,但名字相同不代表监督目标天然相同。
ODE Sampling:Euler、Heun 与 NFE
前一张卡已经说明了速度的几何含义;这张卡只解决另一个问题:如何用有限次速度预测走完整条轨迹。可以把速度场看成随时间变化的风向地图:网络负责“预测风”,ODE solver 负责“沿风走路”。
1. 先固定时间方向
本模块约定 t=0 是 clean data,t=1 是 Gaussian noise。模型监督速度按 data→noise 定义,而生成从 noise→data 反向积分,因此更新式出现减号。
2. Euler:看一眼方向就走
Euler 假设这一小段内速度保持不变。它只在当前点调用一次网络,然后沿当前速度走一步。
二维数值代入
轨迹接近直线时,这个近似很有效;轨迹弯曲或速度变化很快时,单次起点读数会产生较大积分误差。
3. Heun:先试走,再校正
Heun 先按起点速度试走到临时终点,再询问一次终点速度,最后用两个速度的平均值完成正式更新。
Heun 同时参考区间起点与预测终点;一步内速度变化越明显,它通常越有优势。代价是需要更多网络调用。
4. Steps 与 NFE
ODE steps 是时间轴被切成多少段;NFE(Neural Function Evaluations)是速度网络实际被调用多少次,计算成本主要由 NFE 决定。
| 方法 | 每步速度评估 | N 步时的 NFE | 直觉 |
|---|---|---|---|
| Euler | 1 | N | 每段只看起点 |
| 标准 Heun | 2 | 约 2N | 看起点与预测终点 |
| 本实验 Heun | 最后一步省去修正 | 2N-1 | 到 t=0 时少一次评估 |
因此 12-step Euler 与 12-step Heun 并不是相同计算预算。公平比较速度与质量时,还应同时观察 NFE。
5. 更多 steps 能修复什么
| 误差来源 | 含义 | 增加 steps |
|---|---|---|
| 模型误差 | v_theta 没有学准真实速度场 | 不能根治 |
| 积分误差 | 有限步没有贴紧连续轨迹 | 通常可以减小 |
6. 为什么 Rectified Flow 关心直轨迹
轨迹越直,一小段内速度变化越少,Euler 的局部常速度假设越接近真实。Reflow 希望让模型自己的 coupling 更直,从而使少步采样更有机会接近高步结果。
| 观察现象 | 判断 | 建议 |
|---|---|---|
| Euler 少步明显扭曲 | 轨迹弯或步长过大 | 增加 steps 或使用 Heun |
| Heun 少步明显更好 | 一步内速度变化较大 | 按相近 NFE 比较 |
| 高步数仍是错误类别 | 条件速度场或训练有问题 | 检查 loss、CFG 与数据 |
| Reflow 后少步更接近高步 | 轨迹可能被拉直 | 这是 Reflow 生效信号 |
7. 把采样循环读成自然语言
二维 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。
条件、DiT 与 CFG:这些部件为什么仍然成立
Flow Matching 规定模型输出的数学含义,但不限制网络内部结构。No.12 的 DiT 仍可把 z_t patchify 成 tokens,用 Self-Attention 建模空间关系,再把连续时间和类别条件通过 adaLN-Zero 注入各个 block。
为什么叫残差 MLP
普通 MLP 直接输出 F(x);Transformer/DiT block 中的 MLP 分支会把修正量加回当前 token 表示,因此形成 Residual MLP。它不是一种全新的 MLP,而是 MLP 与 skip connection 的组合。
残差连接给梯度提供了直接通路,使深层 DiT 更稳定;adaLN-Zero 中的 gate 还可让 Attention 与 MLP 分支从接近零修正开始训练。
| 更新 | 变化的对象 | 所在轴 | 目的 |
|---|---|---|---|
x ← x + MLP(x) | DiT 隐藏 token | 网络层深度 | 提炼用于预测速度的特征 |
z ← z - dt·v | 生成 latent | ODE 时间 | 从噪声移动到数据 |
条件与 CFG 仍然成立
文字生成时,No.11 的 Cross Attention 不需要删除:图像 token 继续发出 Query,文字 token 继续提供 K/V。CFG 则把两个速度场方向合并:
随后 ODE solver 使用 v_cfg 更新 latent。Cross Attention 决定条件如何进入,CFG 决定放大哪条条件方向,ODE solver 决定怎样数值积分;三者职责保持分离。
Latent Rectified Flow + DiT:完整训练与生成链路
把前面的卡片串起来,完整系统可以拆成四个互不替代的职责:VAE 定义 latent 空间,路径定义监督速度,DiT 学习速度场,ODE solver 在生成时积分速度。
Training
Inference
| 组件 | 训练时 | 生成时 |
|---|---|---|
| VAE Encoder | 把真实图像变成 z0 | 通常不用 |
| 路径与 target | 构造 z_t 与 z1-z0 | 不直接执行 |
| DiT | 回归真实条件速度 | 反复预测当前位置速度 |
| ODE solver | 不参与 loss | 把局部速度积分为完整轨迹 |
| VAE Decoder | 用于检查 latent 质量 | 最后输出图像 |
遇到问题时按职责排查
- 速度含义或输出形状不清楚:回看“连续流 ODE”。
- target 符号或 loss 不清楚:回看“直线路径”和“训练目标”。
- Euler、Heun、steps 或 NFE 不清楚:回看“ODE Sampling”。
- 条件、残差 MLP、Cross Attention 或 CFG 不清楚:回看“条件、DiT 与 CFG”。
Toy Rectified-Flow DiT:训练速度场,再用 ODE 从噪声生成
第一步训练 TinyVAE 与 adaLN-Zero Tiny DiT,Training Losses 会随真实训练 step 实时更新;DiT 的监督答案不再是 epsilon,而是线性路径速度 noise-clean。第二步加载当前页面保存的真实权重,使用 Euler 或 Heun 从纯 latent 噪声反向积分,并比较不同 ODE 步数。
把 Toy Flow 代码逐行讲回公式
| 代码 | 数学含义 | 来自哪个模块 |
|---|---|---|
clean = encoder(image) | 得到数据端点 z0 | No.4 / No.10 |
noise = randn_like(clean) | 得到 Gaussian 端点 z1 | No.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 Matching | No.13 |
v=vu+s*(vc-vu) | 速度场 CFG | No.11 |
z=z-dt*v | 从噪声端反向 Euler 积分 | No.13 |
image=decoder(z) | latent 返回像素空间 | No.4 / No.10 |
阅读真实实现时的检查顺序
- 先确认 clean/noise 分别对应 t=0 还是 t=1。
- 写出实际 interpolation,再对 t 求导,核对 target 符号。
- 确认模型输出是 epsilon、diffusion-v、score 还是 flow velocity。
- 确认 sampler 的时间方向以及 Euler/Heun 更新符号。
- 最后再看 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。