第 0 站
这句话到底说了什么?
这句话其实是把三件不同的事叠加在一起讲:
1 · 训练目标
"噪声的流动方向(的集合)"
网络要学的不是一张图、不是一个噪声,而是一个速度场 $u_\theta(x, t)$:在每个时间、每个空间点上,告诉粒子"你下一步往哪走"。
2 · 几何形状
"高维球壳"
高维标准正态分布 $N(0, I_d)$ 的几乎所有样本都集中在半径 $\sqrt{d}$ 的一层薄壳上——这是个反直觉但精确的事实。
3 · 条件控制
"固定条件控制下的轨迹"
你给一个 prompt / class / mask(这就是"条件"),同一个噪声会被推向不同的目的地。条件就是"偏置",决定了流的方向。
本文路线:第 1 站讲清"流匹配在学什么";第 2 站揭示"高维噪声是一层壳"这个反直觉事实;第 3 站把前两站拼起来,看流匹配是怎么"在壳上走路"的;第 4 站加入条件,看"偏置"到底偏置了什么;第 5 站把原句重读一遍,每个词都有了形象的画面;最后给一段最小可运行代码和论文索引。
第 1 站
流匹配在学什么?—— 把噪声"运输"到数据
所有生成模型本质上都在做一件事:把一个简单分布(例如 $N(0, I)$)变成一个复杂分布(例如所有自然图像的分布)。
不同的生成模型只是用不同的方式去做"运输":
- GAN:一步把噪声变成图(生成器是一个大函数 $G: z \mapsto x$)
- Diffusion:分很多步,每步去掉一点噪声
- Flow Matching:把整个过程看成一个连续时间的常微分方程(ODE),学这个 ODE 的速度场
具体来说,定义一族中间分布 $p_t$,从 $p_0 = N(0, I)$(纯噪声)连续过渡到 $p_1 = $ 数据分布。每个粒子 $x_t$ 在每个时刻有一个速度 $\frac{dx}{dt}$,所有这些速度合起来就是一个向量场 / 速度场:
网络 $u_\theta$ 输入"位置 + 时间",输出"该往哪个方向走多快"。
最简单也最常用的一种设计,叫 Rectified Flow / Conditional Flow Matching with optimal-transport-style coupling:让粒子走直线。
训练 = 让网络预测"从此刻 $x_t$ 出发,走到目标 $x_1$ 的方向是什么"。这就是"学习噪声的流动方向"的精确含义。
互动演示 A
看噪声变成"两弯月亮"
下面这个 2D 演示里,蓝色点是 $N(0, I_2)$ 噪声,橙色点是目标"双月"分布。拖动时间滑块,你会看到每个粒子沿直线从蓝点滑到对应的橙点——这就是 rectified flow 学的轨迹族。背景的小箭头是平均速度场。
一句话总结:训练好的网络 = 把每一个 "(位置, 时间)" 对映射到 "(下一步该往哪)"。它学的不是一个方向,而是整个空间 × 整个时间区间上的方向——所以是"流动方向的集合"。
第 2 站
反直觉时刻:高维 Gaussian 根本不是"一团云"
问你一个问题:你脑海里的 $N(0, I_d)$(d 很大,比如 1024)长什么样?
大多数人的第一反应:"一团绕着原点的雾,大部分概率密度在原点附近,越远越稀疏"——这在 1 维、2 维、3 维都对,但到了高维,这个图像是错的。
真相是:对于 $x \sim N(0, I_d)$,
$$\mathbb{E}\big[\|x\|^2\big] = d, \qquad \text{Var}\big[\|x\|^2\big] = 2d$$用一阶展开可以得到 $\|x\| \approx \sqrt{d}$,并且波动大约是 $1/\sqrt{2}$,几乎不随 $d$ 改变!
这意味着:维度越高,所有样本都被"挤"到半径 $\sqrt{d}$ 的一层薄壳上。
这是经典的 测度浓度 (concentration of measure) 现象。形象地说:
| 维度 $d$ | 典型范数 $\sqrt{d}$ | 相对厚度(壳厚 / 半径) | 视觉 |
|---|---|---|---|
| 2 | 1.41 | ~50% | 胖团 |
| 10 | 3.16 | ~22% | 稍微集中的云 |
| 100 | 10.0 | ~7% | 初见壳形 |
| 1024 | 32.0 | ~2.2% | 明显的薄壳 |
| 4096 | 64.0 | ~1.1% | 极薄的壳 |
| 16384 | 128.0 | ~0.55% | 几乎是个完美球面 |
SD3 / Flux / DiT 这类现代生成模型,工作维度通常是 latent 的 $4 \times 64 \times 64 = 16384$ 或更大。所谓"采样一个噪声 $x_0$",几何上就是在那层薄薄的 $\sqrt{d}$ 球壳上随机取一个点。
互动演示 B
亲眼看见"球壳"从云里浮现
拖动滑块改变维度 $d$。上图:原始范数 $\|x\|$ 的直方图,竖线标出 $\sqrt{d}$。下图:归一化范数 $\|x\| / \sqrt{d}$ 的直方图。维度越高,下图越收缩成一根针——所有样本都凑到了 1 附近。
一句话总结:当我们说"从高维 Gaussian 采样"时,几何上你不是在原点附近抓一把雾,而是在一个半径 $\sqrt{d}$ 的薄壳上随手一点。"高维球壳"——精确得不能再精确。
第 3 站
把两件事拼起来:流匹配 = 球壳上的散步
现在我们把第 1 站(速度场)和第 2 站(球壳)拼起来。
- 起点:$x_0 \sim N(0, I_d)$,几乎一定满足 $\|x_0\| \approx \sqrt{d}$——位于噪声壳上。
- 终点:$x_1 \sim p_{\text{data}}$。真实数据(图像 latent、speech token、3D 点云……)通常也有自己的典型范数 $\|x_1\| \approx R_{\text{data}}$,所以也大致活在某个"数据壳"上。
- 中途:$x_t = (1-t) x_0 + t x_1$,它的范数会从 $\sqrt{d}$ 平滑过渡到 $R_{\text{data}}$。
所以一整条轨迹的形状是:
从噪声壳出发 → 一段 带方向 的连续运动 → 到达数据流形。
这就是原句里说的"球壳上一段运动轨迹"。
速度场 $u_\theta(x_t, t)$ 在每一点上其实可以分解为两个分量:
- 径向分量 $u_r$:决定范数怎么变(壳半径的演化);
- 切向分量 $u_\perp$:决定在壳上朝哪个方向转(这就是"瞄向哪个目标点")。
对早期 $t$(接近 0),$x_t$ 离 $x_0$ 很近、还在噪声壳附近,所以速度场主要在做切向调整——决定"这粒噪声将来要变成猫还是变成狗"。对后期 $t$(接近 1),径向分量才开始压缩范数,让样本落到数据流形上。
互动演示 C
看高维轨迹的"范数轮廓"
这里我们模拟一个 $d$ 维(可调)的 rectified flow,画出 20 条轨迹的 $\|x_t\|$ 随 $t$ 的变化。你会看到:起点都在 $\sqrt{d}$ 附近抱成一束,中途各自滑行,终点落到一个较小的"数据壳"上。每一条曲线 = 一条"球壳上的运动轨迹"。
一句话总结:训练流匹配 = 教网络在两个球壳之间画出一束有方向的曲线。每一条曲线就是一个"$x_0 \to x_1$"的故事。
第 4 站
"偏置"是什么?—— 条件信息决定壳上选哪条路
现在最后一块拼图:原句里的"有偏置的"和"固定条件控制下"到底什么意思?
同一个噪声出发点 $x_0$,不能同时变成猫、变成狗、变成宇航员。要让它确定地变成"猫",必须告诉网络一个条件 $c$("猫"这个 prompt / class / image / mask)。
训练时改成条件流匹配:
速度场多了一个输入 $c$。同一个 $(x, t)$ 在不同 $c$ 下,速度方向不一样。
几何上:原本"无条件速度场"会把每个噪声粒子推向"所有可能数据的某种平均"(图像里就是模糊的平均脸)。一旦你给了条件 $c$,速度场就被偏置(biased)到指向"$c$ 对应的那一小块数据流形"。
这就是为什么 Classifier-Free Guidance(CFG)work:
$u(x, t \mid c) - u(x, t \mid \varnothing)$ 就是条件特有的"偏置方向",乘上系数 $w$ 再加回去,等于"让方向更偏向条件一点"。
互动演示 D
同一束噪声,三种条件,三套轨迹
三个目标聚类(红 / 绿 / 蓝)放在一个圆上。同一批噪声粒子作为起点。点击不同的"条件"按钮,看同一组粒子被推向完全不同的目的地。这就是"偏置"在做的事。
一句话总结:"偏置"不是模型有 bug,而是条件信号偏置了速度场。同一个噪声壳上的同一个点,在不同条件下走向不同未来——这就是"固定条件控制下的运动轨迹"。
第 5 站
重读那句话
现在你有了 4 个停靠站、4 个互动演示作为锚点,再读一次原句:
flow-matching 倾向于让网络学习噪声的流动方向(的集合) → 第 1 站:网络学的是速度场 $u_\theta(x, t)$,覆盖整个空间×时间,所以是"方向的集合"。
,对应就是 → 这个速度场对应一族 ODE 轨迹。
有偏置的高维球壳 → 第 2 + 4 站:起点在 $\sqrt{d}$ 的噪声壳上;偏置由条件 $c$ 给出,决定壳上"哪一片"被选中。
上一段 → 第 3 站:一段从噪声壳 → 数据流形的连续曲线,参数化在 $t \in [0, 1]$ 上。
在固定条件控制下的运动轨迹 → 第 4 站:条件 $c$ 一旦固定,从同一个 $x_0$ 出发的轨迹就被唯一决定(ODE 是确定性的)。
一句话翻译:训练 Flow Matching = 教一个神经网络速度场,让它能把"$\sqrt{d}$ 球壳上一个随机点"通过一段连续的、被条件信号偏置的轨迹,送到"数据流形上某个具体的点"。
第 6 站
实践中的样子 —— 一段最小可读代码 + 论文索引
下面是最小化的条件 rectified flow 训练 + 采样片段。50 行内就能跑通,可以一对一对应到上面五站的概念:
# PyTorch 风格伪代码 —— 条件 Rectified Flow,最小版本
import torch
import torch.nn.functional as F
def train_step(model, x1, c, optimizer):
# x1: 一个 batch 的真实数据 (B, D);c: 条件 (B, ...)
x0 = torch.randn_like(x1) # ← 高维球壳上的样本(第 2 站)
t = torch.rand(x1.size(0), 1, device=x1.device)
xt = (1 - t) * x0 + t * x1 # ← 一段轨迹(第 3 站)
target = x1 - x0 # ← "噪声的流动方向"(第 1 站)
pred = model(xt, t.squeeze(-1), c) # ← u_θ(x, t, c) 学到的速度
loss = F.mse_loss(pred, target) # ← 条件流匹配损失(第 4 站)
optimizer.zero_grad(); loss.backward(); optimizer.step()
return loss.item()
@torch.no_grad()
def sample(model, c, D, steps=50, cfg_scale=0.0):
# 推理:从噪声壳上一点出发,沿 ODE 积分到 t=1
x = torch.randn(c.size(0), D) # ← 起点:随机一个噪声壳上的点
dt = 1.0 / steps
for k in range(steps):
t = torch.full((c.size(0),), k * dt, device=x.device)
v_c = model(x, t, c) # ← 条件方向
if cfg_scale > 0:
v_u = model(x, t, torch.zeros_like(c)) # ← 无条件方向
v = v_c + cfg_scale * (v_c - v_u) # ← CFG 偏置(第 4 站公式)
else:
v = v_c
x = x + v * dt # ← 欧拉法走一小步
return x
每一行代码都对应到原句的某个词:x0 = torch.randn_like(x1) 在视觉化层面就是选了高维球壳上一个点;target = x1 - x0 就是这一粒噪声的"流动方向";模型的输入 $c$ 就是那个"偏置";从 $t=0$ 走到 $t=1$ 的循环就是那"一段运动轨迹"。
进一步阅读
从入门到现代实践的推荐顺序:
- 入门读物:"An Introduction to Flow Matching" — Cambridge MLG blog (https://mlg.eng.cam.ac.uk/blog/2024/01/20/flow-matching.html)。如果你只读一篇,读这个。
- 原始论文:Lipman et al., Flow Matching for Generative Modeling, ICLR 2023.
- 等价/同期工作:Liu et al., Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flow, 2022/23.
Albergo & Vanden-Eijnden, Building Normalizing Flows with Stochastic Interpolants, 2023. - OT 耦合改进:Tong et al., Improving and Generalizing Flow-Based Generative Models with Minibatch Optimal Transport, TMLR 2024.
- 大规模实践:Esser et al. (Stability AI), Scaling Rectified Flow Transformers for High-Resolution Image Synthesis, 2024 (SD3 paper)。
Black Forest Labs, Flux, 2024。 - 高维几何/浓度测度(理解"球壳"那部分的数学):Vershynin, High-Dimensional Probability, 2018。看第 3 章就够了。
- 蒸馏与一步采样:Liu et al., InstaFlow; Yin et al., One-Step Diffusion Distillation。这些工作都是在尝试"把那段球壳上的轨迹拉直成一步跳"。
留给你的最后一个图像:下次当你看到训练日志上流过的 loss 数字时,记住——网络正在干一件几何上非常优雅的事:它在学怎么在一层维度为几千的薄薄球壳上画地图,每一张地图对应一个 prompt。你看到的每一张 Flux 出图,都是从那层壳上随手摸的一个点,沿着这张地图、走过一段轨迹、最终来到你眼前的图像分布上。