← 返回文章目录
CHAPTER 04 · GENERATIVE MODELS

从噪声到样本:
Flow Matching 与 Diffusion Model

把它看成一套可学习的动力学:先规定粒子群如何从噪声变成数据,再让神经网络学会每一刻应往哪里走。

READING MAP先给出全景图

如果只记住一句话:生成模型不是从零“创造”一张图,而是让一团容易采样的随机噪声,沿着学到的速度场,逐步变成看起来像训练数据的样本。

简单分布容易抽样的高斯噪声
连续变形神经网络给出每处速度
数据分布图像、结构、声音等

1 · THE PHYSICAL PICTURE先分清:vector field、trajectory、ODE 与 flow

把许多树叶放进河里,便能同时看见这四个概念:河中每处的水速规则是 vector field(向量场);其中一片树叶走出的路线是 trajectory(轨迹);把所有树叶的起点一起搬到一段时间后的终点,得到 flow(流);ODE 则写下“树叶必须服从当地水速”的规则。

最核心的关系:向量场是速度地图,trajectory 是一个粒子的路线,flow 是整张空间的搬运过程。

状态向量:粒子此刻在哪里?

二维中,粒子在 t 时刻的位置写作 x(t)=(x1(t),x2(t))T。x 是完整位置向量;x1、x2 是第 1、2 个坐标分量;上标 T 表示列向量。它也可以是“状态”而非几何位置:单摆可写成 x(t)=(θ(t),ω(t))T,分别为摆角和角速度。

\[ \dot{\mathbf{x}}(t)=\frac{d\mathbf{x}(t)}{dt} \]点号 ẋ 读作 x dot,与 dx/dt 相同,表示状态随时间的瞬时变化率。

Vector field:固定位置,读取那里的瞬时速度

向量场是一个规则:输入当前位置,输出当前位置应有的速度。自治系统写作 ẋ=f(x);若 x=(x1,x2)T,那么 f(x)=(f1(x),f2(x))T,也就是两条方程 ẋ1=f1(x1,x2)、ẋ2=f2(x1,x2)。下标只标明速度在第几个坐标方向的分量。

\[ f:\mathbb{R}^{2}\to\mathbb{R}^{2},\qquad (x,y)\mapsto f(x,y)=(-y,x) \]它不是一条路线,而是“位置 → 速度”的规则,如同一张风速图:每个位置一支箭头,方向是风向,长度是风速。

这个旋转场在 (1,0) 给出 (0,1),在 (0,1) 给出 (−1,0),所以整张图表示绕原点逆时针旋转的水流。固定观察各位置的箭头,叫欧拉观点(Eulerian viewpoint)。

Trajectory:固定一片树叶,跟它一起走

选择初始时刻 t0 和初始位置 x0,即 x(t0)=x0。解 ODE 后得到的函数 t↦x(t;t0,x0) 是 trajectory。下标 0 的含义是“初始”,不是第 0 个坐标。

\[ \frac{d\mathbf{x}(t)}{dt}=\mathbf{v}\!\left(t,\mathbf{x}(t)\right),\qquad \mathbf{x}(t_0)=\mathbf{x}_0 \]左边是粒子实际的速度;右边是向量场在粒子当前位置规定的速度。每走一步,必须在新位置重新读取箭头。

因此,轨迹的切向量总等于该点向量场。对旋转场,如果 x(0)=(1,0)T,则 x(t)=(cos t,sin t)T;其速度 (−sin t,cos t)T 正好是 f(x(t))。trajectory 保留何时到达、往哪走、走多快;orbit(轨道)只收集经过的位置,例如这里的单位圆。

Flow:固定一段时间,观察所有起点被搬到哪里

每一个初始点 x0 都有自己的 trajectory。把它们统一写成 Φt(x0),就是 flow map:

\[ \mathbf{x}(t;\mathbf{x}_0)=\Phi_t(\mathbf{x}_0) \]固定 x0、让 t 变化,得到 trajectory;固定 t、让 x0 变化,得到 flow:它把所有初始点整体搬到 t 时刻的终点。

对于旋转系统,Φt(x0,y0)=(x0cos t−y0sin t, x0sin t+y0cos t)T。所以 Φπ/2 会把整个平面逆时针旋转 90°,显然不只是描述一颗粒子。

向量场与 flow 的双向关系

\[ \Phi_t(\mathbf{x}_0)=\mathbf{x}_0+\int_0^t f(\Phi_s(\mathbf{x}_0))\,ds \]\[ f(\mathbf{x})=\left.\frac{\partial}{\partial t}\Phi_t(\mathbf{x})\right|_{t=0} \]第一式:最终位置 = 初始位置 + 所有微小位移之和,s 是临时的时间变量。第二式:vector field 是 flow 的瞬时版本,flow 是 vector field 随时间累积的有限时间版本。

自治系统中,先走 s 再走 t 等于直接走 s+t:Φt+st∘Φs,其中 ∘ 表示先右后左地复合函数。若速度场还依赖绝对时间,例如早晚风向不同,则写 Φt,t₀(x0),以记录从时刻 t0 演化到 t。

这就是生成模型的基本图像:模型学习一个随时间变化的向量场;整团初始噪声在对应的 flow 下被搬运成数据分布;任意一颗噪声粒子走出的路,就是一条 trajectory。

2 · ODE FROM ZERO先弄明白:什么是 ODE?

ODE 是 ordinary differential equation 的缩写,中文叫常微分方程。名字听起来吓人,实际只是在写一条很朴素的规则:如果我知道物体此刻在哪里,就规定它下一瞬间应该怎样变化。

从“位置”到“变化率”

设一辆车在时刻 t 的位置是 x(t)。位置本身回答“车在哪”;速度回答“位置变得有多快”。数学中把这个瞬时速度写作 dx(t)/dt。例如,若车始终以每秒 3 米向前,则:

\[ \frac{dx(t)}{dt}=3 \]左边是位置的变化率,右边是规定好的速度。解出来就是 x(t)=x(0)+3t:从初始位置开始,每秒前进 3 米。

更一般地,速度可以依赖位置。例如山坡上的球,离谷底越远,回到谷底的拉力越大,可粗略写成:

\[ \frac{dx(t)}{dt}=-\theta x(t),\qquad \theta>0 \]θ 是一个正的常数;负号表示:x 在右边时往左推,x 在左边时往右推。因此球会逐渐靠近 0。这里未知的是整条轨迹 x(t),而不是 θ。

这就是 ODE 的两个组成部分:初始条件(从哪里开始)和变化规则(每一刻怎样走)。在生成模型中,我们把位置换成一个很高维的向量,速度规则换成神经网络。

为什么没有解析解也能算?——欧拉法

大多数 ODE 没有像上面那样漂亮的显式答案。计算机不需要硬求公式,只要把时间切成许多很小的格子。若当前时刻为 t、步长为 h,便暂时认为这极短一段里的速度不变:

\[ \mathbf{x}_{t+h}\approx\mathbf{x}_t+h\,\mathbf{v}(\mathbf{x}_t,t) \]v 是速度规则。右边可读作“新位置 = 老位置 + 走了多久 × 此刻速度”。≈ 表示近似;h 越小,近似通常越好。
记下当前位置

从 x0 开始。

查询当前速度

把当前位置和当前时间送进规则 v,得到一支箭头。

沿箭头迈一小步

更新为 xt+h=xt+h·v。

重复直到终点

这就是数值求解 ODE,也叫积分或模拟轨迹。

先抓住一个画面:ODE 不是一条预先画好的轨迹,而是空间里处处都有的“行走指令”。一旦给定起点,粒子每一步问一次“我这里该朝哪走”,轨迹才自然长出来。

3 · GENERATION AS SAMPLING“生成”在数学上是什么意思?

一张 256 × 256 的 RGB 图片可以排成一个很长的数列;一个含 N 个原子的分子,也可用各原子的三维坐标排成数列。于是,不论对象原本看起来多不同,都可暂时表示为一个 d 维向量 z ∈ Rd

数据分布 pdata不是一张“平均图片”,而是一张看不见的地图,指出哪些向量像真实数据、出现得多,哪些向量不像。生成就是从这张地图中随机抽一个样本:z ∼ pdata

难点是:我们没有这张地图的解析公式,只有一批样本(照片、蛋白质结构或材料显微图)。但我们很会从标准高斯分布抽样:令 x0 ∼ N(0, Id),它就是一团各维度独立、均值为零的噪声。生成模型所要学的,是把它变成 x1 ∼ pdata 的连续过程。

\[ \mathbf{x}_0\sim p_{\mathrm{init}}=\mathcal{N}(0,I_d)\quad\longrightarrow\quad\mathbf{x}_1\sim p_{\mathrm{data}} \]init 是 initial(初始)的缩写;下标 01 指人为设定的连续时间起点和终点,并非图像的第 0、1 个像素。

4 · FORWARD PROCESS先看扩散的正向过程:怎样把数据弄成噪声?

这里有一个术语容易造成混乱。生成时我们想从噪声走向数据;但经典 diffusion 的“正向过程(forward process)”通常定义为相反方向:从干净数据逐步加噪,直到它接近简单高斯噪声。这个方向容易设计,因为只要不断掺入随机数即可。

FORWARD · t=0
干净样本 z

例如一张真实训练图像

FORWARD · 中间
部分加噪 xt

轮廓还在,但细节被扰动

FORWARD · t=1
近似纯噪声

容易从高斯分布重新抽取

REVERSE
学习反向修正

每一步猜去掉什么噪声

GENERATE
得到新样本

从新抽噪声开始,而非复原原图

一种连续写法是从一条干净数据 z 取出部分信号,再加入部分标准高斯噪声 ε

\[ \mathbf{x}_t=\alpha_t\mathbf{z}+\beta_t\boldsymbol{\epsilon},\qquad \boldsymbol{\epsilon}\sim\mathcal{N}(0,I_d) \]t=0 时安排 α0≈1、β0≈0,所以 x0≈z;随着 t 增大,αt 变小、βt 变大;终点 x1 接近噪声。α、β 的具体曲线叫噪声调度 schedule。

它可以看作图像混合:原图权重逐渐调低,电视雪花权重逐渐调高。训练时,z 和亲手加入的 ε 都已知,因此我们完全知道每个模糊版本 xt 是怎样形成的。这正是监督信号的来源。

正向过程不负责生成。它的作用是人为制造大量“清晰图 → 不同程度模糊图”的练习题。真正用于生成的是随后学到的反向方向:从纯噪声开始,一小步一小步回到数据区域。

5 · CONDITIONAL AND MARGINAL从“知道终点”到“只看整体云团”

训练时会抽到一条具体样本 z,所以可以问:“已知最终要抵达的是 z,时刻 t 的带噪样本会怎样分布?”这叫条件概率路径 pt(x | z);竖线读作“给定 z”。

\[ p_t(\mathbf{x}\mid\mathbf{z})=\mathcal{N}\!\left(\alpha_t\mathbf{z},\beta_t^2I_d\right) \]固定 z 后,x 仍然随机,因为噪声 ε 仍在变。均值 αtz 是点云中心,βt2Id 表示点云散开程度。

生成时并不知道终点 z,只知道当前位置 x 和时刻 t。因此真正需要推动的是所有条件云团混合后的边缘概率路径

\[ p_t(\mathbf{x})=\int p_t(\mathbf{x}\mid\mathbf{z})\,p_{\mathrm{data}}(\mathbf{z})\,d\mathbf{z} \]先把积分理解为“将所有可能的 z 加起来”,并按其数据概率加权。边缘化就是不指定 z,只保留 x 的整体分布。

条件云团与边缘云团

橙、蓝是已知两个终点时的条件点云;混在一起后是边缘分布。

一句区分:条件路径回答“已知这一条数据 z 时怎样演化”;边缘路径回答“不指定哪条数据时,整个数据集的概率云怎样演化”。前者提供可计算的监督信号,后者才是生成时真正要走的路径。

6 · FROM PHYSICS TO LEARNINGODE 怎样和机器学习连起来?

现在我们已经有两个部分:ODE 告诉我们“只要有速度规则,就能从起点走出轨迹”;正向加噪给出大量“某个带噪状态来自哪条干净数据”的样本。还缺的正是那张复杂的速度地图。它无法手写:对一张百万维图像,在每种噪声等级下、每个可能位置该朝哪走,规则都极其复杂。

神经网络的角色并不神秘:它就是一个参数很多的函数近似器。输入是当前带噪状态和时间,输出是一支同样维度的修正箭头:

神经网络:fθ(xt, t) → 与 xt 同维度的向量θ 是网络中所有可调权重;训练就是反复调整 θ,使输出箭头更接近我们提供的正确答案。图像输入时,输出仍是一张“每个像素应怎么改”的图。

不同模型只是在“正确答案”写成什么上不同。去噪 diffusion 常要求网络猜 ε;Flow Matching 则要求网络猜一条概率路径上的速度。它们都把生成问题化成大量普通的监督学习小题:给定 xt 和 t,预测一个已知目标向量。

训练与生成的区别:训练时有数据集 z,也知道人为加入的 ε,因此有标准答案;生成时没有 z,只有新噪声。此时让训练好的网络反复给方向,再用 ODE/SDE 的小步更新,便能把这个新噪声送向数据分布,而不是某一张记住的训练图。

7 · FLOW MODELSFlow:给空间中的每一点一支“速度箭头”

想象一池染色液。若你知道池中每一个位置、每一时刻的水流速度,就能把一粒墨水放进去,预测它此后如何移动。这张“位置 → 速度”的图在物理中叫速度场,这里称为向量场。

ut(x) : (x, t) ↦ 速度向量
在位置 x、时刻 t,应该朝哪个方向、以多快的速度前进。

若粒子当前位置为 Xt,它始终顺着所在位置的箭头走,便满足常微分方程(ODE):

\[ \frac{d\mathbf{X}_t}{dt}=\mathbf{u}_t(\mathbf{X}_t),\qquad \mathbf{X}_0=\mathbf{x}_0 \]大写 X 表示一个随时间变化的随机粒子;小写 x 表示某个确定的位置。dXt/dt 是瞬时速度:极短时间内的位置变化率。

给定初始位置 x0,这条 ODE 会画出一条轨迹。把所有初始位置一起推进,整个空间像橡皮布一样被平滑拉伸、弯曲,这个总变换叫 ψt(flow):Xt = ψt(X0)。网络学习的是箭头 u,不是一次性直接输出终点。

计算机怎样沿箭头走?

最简单的是欧拉法:把时间切成 n 小段,每一小段都“当前位置 + 小步长 × 当前速度”。步长越小,越接近连续运动;步数也越多。

\[ \mathbf{x}_{t+h}=\mathbf{x}_t+h\,\mathbf{u}_{\theta,t}(\mathbf{x}_t),\qquad h=\frac{1}{n} \]h 是一步的时长;θ 是神经网络的可学习参数;uθ,t 表示同时依赖 θ 和 t 的函数。
Flow model 的采样:先抽噪声 X0,再把上式重复 n 次到 t=1。整个过程没有新的随机掷骰子;同一个初始噪声必然得到同一个结果,所以它是确定性的。

8 · DIFFUSION MODELSDiffusion:水流之外,再加上热运动

真实悬浮在水里的微粒不会只随水流前进,还会被周围分子的无数次撞击随机推来推去。这正是布朗运动的直觉。扩散模型把这部分不可预测的扰动也写进运动规则。

\[ d\mathbf{X}_t=\mathbf{u}_t(\mathbf{X}_t)\,dt+\sigma_t\,d\mathbf{W}_t \]Wt 是布朗运动,可理解为连续的随机游走;σt ≥ 0 是噪声强度。第一项是有目的的漂移 drift,第二项是随机扩散 diffusion。

这叫随机微分方程(SDE)。同一初始点跑两遍,随机碰撞不同,路径也不同。离散模拟时,布朗运动的一小段增量可用高斯噪声表示:

\[ \mathbf{x}_{t+h}=\mathbf{x}_t+h\,\mathbf{u}_{\theta,t}(\mathbf{x}_t)+\sigma_t\sqrt{h}\,\boldsymbol{\epsilon},\qquad \boldsymbol{\epsilon}\sim\mathcal{N}(0,I_d) \]每一步都重新抽取 ε。随机项随 √h 缩放:时间加倍时,典型随机位移只增长 √2 倍。
Flow modelDiffusion model
动力学ODE:只有速度场SDE:速度场 + 布朗扰动
一次采样给定初始噪声后确定每一步可注入新的随机性
关系当 σt = 0 时,SDE 正好退化成 ODE;因此 flow 是 diffusion 的一个特例。

9 · BROWNIAN MOTION AND SAMPLING布朗运动:SDE 里的“每一步都掷一次骰子”

ODE 给定起点后轨迹完全确定;SDE 额外加入布朗运动 Wt,所以同一起点也会走出不同路线。可以想成花粉颗粒在水里:平均水流把它带向某处,水分子的无数次碰撞又让它不断抖动。

\[ \mathbf{W}_{t+h}-\mathbf{W}_t\sim\mathcal{N}(0,hI_d)\quad\Longleftrightarrow\quad\mathbf{W}_{t+h}=\mathbf{W}_t+\sqrt{h}\,\boldsymbol{\epsilon} \]∼ 表示“服从该分布”;h 是时间小步;ε 是重新抽取的标准高斯噪声。方差正比于 h,因此随机位移的典型大小是 √h。

同一初始点:ODE 与 SDE

蓝线没有随机项,重复运行会重合;橙线加入布朗扰动,因此会分叉。点击按钮重新抽取路径。

10 · THE CENTRAL TRICK训练目标从哪里来:先设计“中间帧”

说“让噪声变成数据”还不够,因为中途每一刻的速度应是什么?讲义的核心做法是先指定一条概率路径 pt:它描述的不是某个粒子,而是所有粒子在时刻 t 组成的云团分布。

t = 0
噪声云

简单、近似各向同性

0 < t < 1
混合云

既有数据轮廓,也保留噪声

t = 1
数据云

分布与训练样本一致

TRAIN
学局部速度

网络在各时刻各位置输出箭头

SAMPLE
积分走完全程

将新噪声送往样本

一条很常用的条件路径是:拿一条真实样本 z,把它与独立噪声 ε 线性混合:

\[ \mathbf{x}_t=t\mathbf{z}+(1-t)\boldsymbol{\epsilon},\qquad \boldsymbol{\epsilon}\sim\mathcal{N}(0,I_d) \]z 是训练集抽到的一条干净数据;ε 是新抽取的噪声;当 t=0,xt=ε;当 t=1,xt=z。这个选择常叫 CondOT 路径。这里的“条件”是“已知该终点样本 z”,不要和文字提示词的条件生成混淆。

对固定的 zε,直接对 t 求变化率,得到这条直线的目标速度:

\[ \mathbf{v}_t(\mathbf{x}\mid\mathbf{z})=\mathbf{z}-\boldsymbol{\epsilon} \]竖线 | z 读作“在给定 z 的条件下”。它提醒我们:这个箭头知道具体要抵达哪条训练样本。实际采样时我们不知道 z,因此网络最终必须学会不依赖 z 的平均箭头。
最容易困惑的一点:训练时可以看见 z,采样时不能。答案不是让网络背下某一张图,而是在同一位置 x、同一时间 t 汇集所有可能通向不同 z 的箭头,并学习其条件平均。这个平均后的向量场恰好会把“整体云团”沿概率路径推进。

11 · FLOW MATCHINGFlow Matching:把“会走路”变成一个普通回归问题

网络接收带噪位置 xt 和时间 t,输出一个与数据同维度的速度向量 uθ,t(xt)。训练只需让它接近已知的目标速度 z−ε

\[ L_{\mathrm{CFM}}(\theta)=\mathbb{E}\left[\left\|\mathbf{u}_{\theta,t}(t\mathbf{z}+(1-t)\boldsymbol{\epsilon})-(\mathbf{z}-\boldsymbol{\epsilon})\right\|^2\right] \]L 是损失;CFM 是 Conditional Flow Matching;E 表示对许多随机抽取的 z、t、ε 求平均;‖·‖2 是每个分量误差平方后相加。最小化它就是均方误差回归。
抽一个真实样本 z

例如一张训练图片或一个分子构型。

抽时间 t 和噪声 ε

通常 t 从 [0,1] 均匀抽取;每个批次覆盖不同的“噪声程度”。

构造中间状态 xt

令 xt=tz+(1−t)ε,同时确切知道这条构造路径的速度 z−ε。

回归速度并更新 θ

反向传播降低均方误差。重复后,网络在看不到 z 时也能给出合理的整体速度。

为什么这个“带终点标签的局部练习”能生成整个分布?讲义中的边缘化技巧给出结论:条件损失与真正想学的、不可直接计算的整体速度场损失,只差一个与网络参数无关的常数。因此二者最优解相同。直觉上,这类似在风向复杂的十字路口收集很多目的地不同车辆的速度:不知道每辆车的终点时,最佳预测就是所有可能速度的平均。

# CondOT Flow Matching:一次训练迭代的核心
z = sample_from_dataset()
t = uniform(0, 1)
eps = standard_normal_like(z)
x_t = t * z + (1 - t) * eps
target_velocity = z - eps
loss = mean_square(u_theta(x_t, t) - target_velocity)

代码中的 eps 对应 ε;u_theta 对应 uθ,t。训练结束后只保留网络 uθ,t,不再需要训练样本 z 来生成。

11.1 · WHY THIS LOSS WORKSFlow Matching 的 loss 不是猜出来的

先回到真正目标。我们希望网络 uθ,t(x) 逼近边缘概率路径的真实速度场 ut(x)。若它们在每个时刻、每个常见位置都相同,解 ODE 时整团粒子就会沿正确的概率路径从初始分布到数据分布。

\[ L_{\mathrm{FM}}(\theta)=\mathbb{E}_{t\sim\mathrm{Unif}[0,1],\,\mathbf{x}\sim p_t}\!\left[\left\|\mathbf{u}_{\theta,t}(\mathbf{x})-\mathbf{u}_t(\mathbf{x})\right\|^2\right] \]这就是最朴素的“预测值减真值”的均方误差。t 均匀抽取,等价于让 [0,1] 内每种噪声程度都同等受到训练;x 从 pt 抽取,意味着重点训练生成时实际会经过的位置。

问题是右边的 ut(x) 不可直接算。它包含“在当前位置 x,所有可能终点 z 的条件速度如何加权”的积分;数据集只给了有限样本,无法枚举所有 z。因此我们转而使用已知 z 的条件速度:

\[ L_{\mathrm{CFM}}(\theta)=\mathbb{E}_{t,\,\mathbf{z}\sim p_{\mathrm{data}},\,\mathbf{x}\sim p_t(\cdot\mid\mathbf{z})}\!\left[\left\|\mathbf{u}_{\theta,t}(\mathbf{x})-\mathbf{u}_t(\mathbf{x}\mid\mathbf{z})\right\|^2\right] \]CFM 中的 C 是 conditional。这里的监督目标 ut(x|z) 是人为选定条件路径后可解析得到的量,所以每次训练都算得出来。

需要的背景:条件期望就是“已知部分信息后的最佳平均”

设你只看见当前位置 X,却没看见这颗粒子来自哪个终点 Z。条件速度 V=ut(X|Z) 仍有不确定性;在只知道 X 的前提下,最合理的单一预测就是条件期望 E[V|X]。这不是直觉上的随便平均,而是平方误差下误差最小的预测规则。

平方损失投影定理:对任意只依赖 X 的函数 g(X),令 U=E[V|X],则

E[‖g(X)−V‖²] = E[‖g(X)−U‖²] + E[‖U−V‖²]。

最后一项不依赖 g;因此想拟合 V 时,最佳的只看 X 的函数就是 U。

定理:Conditional Flow Matching 为何等价于 Flow Matching?

定理(边缘化 / conditional flow matching)。若条件向量场 ut(x|z) 确实能把条件路径 pt(x|z) 推进,那么它的条件期望

\[ \mathbf{u}_t(\mathbf{x})=\mathbb{E}\!\left[\mathbf{u}_t(\mathbf{X}\mid\mathbf{Z})\mid\mathbf{X}=\mathbf{x}\right] \]就是边缘路径 pt(x) 的正确速度场,且 LCFM(θ)=LFM(θ)+C,其中 C 与 θ 无关。

证明思路。令 V=ut(X|Z),令网络输出 g(X)=uθ,t(X)。上面的投影定理直接把条件 loss 拆成“网络与边缘速度的误差”加上一个无法消除的条件不确定性 C。训练只能改变第一项,故最小化 CFM 与最小化 FM 得到同一网络。另一方面,概率密度演化满足连续性方程 tpt+∇·(ptut)=0;把所有条件路径按 pdata(z) 加权相加,便得到边缘路径也遵从这个平均速度场。

CondOT 路径为何得到 z−ε 这个目标?

选择 xt=tz+(1−t)ε 后,固定 z、ε 并对 t 求导即可:

\[ \frac{d\mathbf{x}_t}{dt}=\frac{d}{dt}\left(t\mathbf{z}+(1-t)\boldsymbol{\epsilon}\right)=\mathbf{z}-\boldsymbol{\epsilon} \]这并不是说所有位于同一 x 的粒子都具有相同速度;不同的 z、ε 组合可碰巧产生相同 x。网络看不到 z,所以它在该处学到的是这些条件速度的平均。
抽取 z、t、ε

z 来自数据集,t 来自 [0,1],ε 来自标准高斯。

构造 xt

令 xt=tz+(1−t)ε;这保证 xt 正好来自条件路径。

回归条件速度

令网络输出与 z−ε 做平方误差,再对 θ 反向传播。

采样时丢掉 z

从新噪声开始解学到的 ODE;定理保证网络已学到边缘速度场。

11.2 · AFTER TRAININGFlow Matching 训练完以后,网络怎样生成新样本?

训练完成后,数据集中的 z、训练时抽过的 ε 都不再使用。我们只保留学好的网络参数 θ。此时网络是一个可查询的速度地图:输入“当前点 x 在第 t 时刻的位置”,输出“下一瞬间应往哪走”。

阶段已知什么网络要做什么
训练干净数据 z、手动加入的 ε、时间 t。从 xt=tz+(1−t)ε 预测条件速度 z−ε,并调整 θ。
生成只有新抽的噪声 x0,没有 z。反复输出整体速度 uθ,t(xt),由数值积分得到 x1

采样算法:沿学到的 flow 解一次 ODE

\[ \mathbf{x}_0\sim\mathcal{N}(0,I_d),\qquad \mathbf{x}_{t+h}=\mathbf{x}_t+h\,\mathbf{u}_{\theta,t}(\mathbf{x}_t),\qquad h=1/N \]N 是采样步数,不是训练轮数。循环 N 次,让 t 从 0 走到 1,最后的 x1 就是一条新生成样本。
# 训练结束后:Flow Matching 的生成
theta = trained_parameters
x = standard_normal(shape)      # x_0:新噪声,不来自训练集
N = 50
for i in range(N):
    t = i / N
    velocity = u_theta(x, t)    # 网络只看当前 x 和时间 t
    x = x + (1 / N) * velocity # Euler:沿箭头走一小步
return x                         # 约为 x_1:一个新样本

为什么这不是“记住训练图片”?因为起点是全新的随机噪声,网络在途中遇到的位置也几乎不会与某条训练轨迹完全相同。它学习的是覆盖整个概率云的局部运动规则;不同随机种子给出不同 x0,经过同一个 flow 后得到不同但仍落在数据分布中的样本。

实用提醒:Euler 是最容易解释的求解器,但不是唯一选择。把 N 增大通常会降低离散误差;也可以使用 Heun、Runge–Kutta 等更高阶 ODE solver,在相近网络调用次数下得到更准确的轨迹。无论求解器如何更换,训练后的网络 uθ,t 本身不需要重训。

12 · SCORE MATCHINGDiffusion:为什么“预测噪声”就是学习方向?

扩散模型常被描述成“加噪,再去噪”。在高斯路径中,可以写成更一般的形式:

xt = αtz + βtεαt 控制还保留多少信号,βt 控制噪声有多大;它们随时间变化。下标 t 说明这是一个 schedule(调度曲线),不是固定常数。

此时网络常训练去预测当初加入的 ε。它看见模糊的 xt、知道时刻 t,猜测噪声是哪一部分:

\[ L_{\mathrm{noise}}(\theta)=\mathbb{E}\left[\left\|\boldsymbol{\epsilon}_{\theta,t}(\mathbf{x}_t)-\boldsymbol{\epsilon}\right\|^2\right] \]左侧 εθ,t 是网络预测,不是原始随机噪声 ε;θ 是网络参数,t 是当前噪声等级。两个下标服务不同目的,不能省略。

这不只是一个技巧。若能识别“哪些成分是噪声”,就知道该往反方向修正多少。严格地说,diffusion 的另一种表述学习 score,即 x log pt(x):它指向当前分布密度增长最快的方向。可以把它想成在浓雾里感受“哪里更像数据的高密度区域”的上坡方向。对高斯加噪路径,score 与噪声预测只差一个随 t 缩放的负号,因此二者可以互相换算。

不是必须真的“倒放物理扩散”。现代连续时间观点更灵活:只要构造的 ODE/SDE 确实沿着同一条概率路径,把简单分布送到数据分布,就完成了生成。不同采样器主要是在速度、随机性和数值误差之间取舍。

12.1 · WHY DENOISING IS SCORE MATCHING为什么“猜噪声”会学到 score?

score 不是分数,它是概率密度的对数梯度:

\[ \mathbf{s}_t(\mathbf{x})=\nabla_{\mathbf{x}}\log p_t(\mathbf{x}) \]x 表示只对位置 x 求导;log 是自然对数。score 指向“从当前位置往哪个方向走,概率密度上升得最快”。它只关心密度的形状,不需要知道归一化常数。

一个一维直觉:若点云中心在 0,位于 x=3 的点想回到高密度区域,应向左;位于 x=−3 的点应向右。score 正是在每个位置给出这种“回到更像数据区域”的方向。扩散模型需要它,是因为随机扩散会把点云散开,而 score 提供了抵消扩散、重新聚拢的方向。

从高斯条件路径直接算出条件 score

对固定 z,条件路径为 xttz+βtε,即 pt(x|z) 是均值 αtz、方差 βt2I 的高斯。写下其对数密度后对 x 求导:

\[ \log p_t(\mathbf{x}\mid\mathbf{z})=C-\frac{\left\|\mathbf{x}-\alpha_t\mathbf{z}\right\|^2}{2\beta_t^2}\quad\Longrightarrow\quad\nabla_{\mathbf{x}}\log p_t(\mathbf{x}\mid\mathbf{z})=-\frac{\mathbf{x}-\alpha_t\mathbf{z}}{\beta_t^2}=-\frac{\boldsymbol{\epsilon}}{\beta_t} \]C 是与 x 无关的常数,求导后消失。最后一步使用 xttz+βtε。这就是“score 等于负的、按噪声强度缩放的噪声”。

因此若网络 sθ,t(x) 预测 score,条件 score matching 的自然平方损失就是:

\[ L_{\mathrm{CSM}}(\theta)=\mathbb{E}\!\left[\left\|\mathbf{s}_{\theta,t}(\mathbf{x}_t)+\frac{\boldsymbol{\epsilon}}{\beta_t}\right\|^2\right] \]网络目标是 −ε/βt。这解释了“去噪”并非额外技巧,而是高斯条件 score 的直接重写。

为何实践中预测 ε,而非直接预测 score?

当 t 接近干净数据端,βt 很小,−ε/βt 数值会很大,直接回归 score 容易不稳定。于是把网络重新参数化为 εθ,t(x)=−βtsθ,t(x),直接学习原始噪声:

\[ L_{\epsilon}(\theta)=\mathbb{E}\!\left[\left\|\boldsymbol{\epsilon}_{\theta,t}(\mathbf{x}_t)-\boldsymbol{\epsilon}\right\|^2\right] \]与 score loss 相比,它相当于改变不同 t 的权重:不再让 βt 很小时的样本因为除以 βt2 而压倒其他时刻。预测完 ε 后,再用 sθ,t=−εθ,tt 换回 score。

定理:条件 score 训练同样学到边缘 score

定理(denoising score matching)。令条件 score 为 ∇log pt(x|z),则边缘 score 满足

\[ \nabla\log p_t(\mathbf{x})=\mathbb{E}\!\left[\nabla\log p_t(\mathbf{X}\mid\mathbf{Z})\mid\mathbf{X}=\mathbf{x}\right] \]相应地,条件 score loss 与不可直接计算的边缘 score loss也只差一个与 θ 无关的常数。

证明结构与 Flow Matching 完全平行:把条件 score 看成随机目标 V,把只看 x 的网络当作 g(X),再用条件期望的平方损失投影定理。区别仅在于:Flow Matching 回归的是速度,score matching 回归的是“朝高密度区上坡”的方向。

score 如何放回 SDE?

想让带随机项的 SDE 与 flow 的概率路径一致,需要在漂移中加入 score 修正:

\[ d\mathbf{X}_t=\left[\mathbf{u}_t(\mathbf{X}_t)+\frac{\sigma_t^2}{2}\nabla\log p_t(\mathbf{X}_t)\right]dt+\sigma_t\,d\mathbf{W}_t \]这来自 Fokker–Planck 方程:SDE 的随机扩散会使密度摊平,score 项恰好补偿它,使最终密度仍沿选定的 pt 演化。将真实 score 换成网络预测,即得到可采样的 diffusion model。
Flow Matching 与 score matching 的关系:两者都先构造同一类“数据与噪声之间的概率路径”,也都借助条件目标避开不可算的边缘量。差别是前者直接学习把云团搬动的速度,后者学习密度上坡方向,再把它放进 SDE 的漂移项。

12.2 · END-TO-END DIFFUSIONDiffusion 的训练数据怎样造?训练后怎样生成?

这里最常见的误解是:“diffusion 先生成图,再拿生成图训练自己”。不是。训练时的干净样本 z 始终来自真实数据集;我们只是用已知随机噪声把 z 人为破坏,造出一张张带标准答案的练习题。网络学习的是:给我一张处于某种噪声程度的 xk,告诉我当初混进去了多少 ε。

离散时间的正向加噪:构造训练对

实际 DDPM 常把时间切为 k=1,…,T 个离散步骤。为避免和前文连续时间的 βt 混淆,下面的 βk 是第 k 步预设的小噪声量;定义 αk=1−βk,并记 ᾱk1α2…αk

\[ \mathbf{x}_k=\sqrt{\bar\alpha_k}\,\mathbf{z}+\sqrt{1-\bar\alpha_k}\,\boldsymbol{\epsilon},\qquad\boldsymbol{\epsilon}\sim\mathcal{N}(0,I_d) \]k 小时,xk 还接近 z;k 大时,ᾱk 很小,xk 接近纯高斯噪声。这个闭式公式等价于连续加 k 次小噪声,但训练时可一步直接得到任意噪声等级。
# 一次 DDPM / noise-prediction 训练迭代
z = sample_from_dataset()             # 真实图片、结构或其他真实数据
k = random_integer(1, T)              # 随机选择一个噪声等级
eps = standard_normal_like(z)         # 我们自己抽的、已知的答案
x_k = sqrt(alpha_bar[k]) * z + sqrt(1 - alpha_bar[k]) * eps
eps_hat = epsilon_theta(x_k, k)       # 网络猜原始噪声
loss = mean_square(eps_hat - eps)
update(theta, loss)

所以所谓“生成训练样本”更准确应叫构造带噪训练输入:每次随机取 z、k、ε,就得到一个输入 xk 和标签 ε。一个真实样本能产生无穷多个不同噪声等级的训练对。

训练完后的生成:从纯噪声反复去噪

生成时不取任何 z。先令 xT 为新抽的高斯噪声;随后让 k 从 T 倒数到 1。网络在每一步估计当前 xk 中的噪声,采样器据此给出稍微干净一些的 xk−1

\[ \mathbf{x}_{k-1}=\frac{1}{\sqrt{\alpha_k}}\!\left(\mathbf{x}_k-\frac{1-\alpha_k}{\sqrt{1-\bar\alpha_k}}\,\boldsymbol{\epsilon}_{\theta}(\mathbf{x}_k,k)\right)+\sigma_k\boldsymbol{\eta},\qquad\boldsymbol{\eta}\sim\mathcal{N}(0,I_d) \]括号内是依据网络预测去掉噪声的主要修正;最后的 σkη 是可选随机项。σk=0 时得到确定性采样器的一类形式;不同 sampler 主要是在速度、随机性和步数之间取舍。
# 训练结束后:标准离散 diffusion 生成
x = standard_normal(shape)             # x_T:全新噪声
for k in range(T, 0, -1):
    eps_hat = epsilon_theta(x, k)
    eta = standard_normal_like(x) if k > 1 else 0
    x = reverse_step(x, eps_hat, k, eta) # 上面的 x_{k-1} 公式
return x                                # x_0:新样本
时间约定请分开看:标准 DDPM 把真实数据放在 k=0、噪声放在 k=T,故生成是 T→0 的“反向去噪”。前文 Flow Matching 为方便叙述采用相反的连续时间约定:噪声在 t=0、数据在 t=1,生成是 0→1。两者只是给时间轴贴标签的方式不同,核心都是从简单噪声走向数据分布。
与 Flow Matching 对照:Flow Matching 通常训练速度 uθ,t,生成时解 ODE;diffusion 通常训练噪声预测 εθ 或 score,生成时反复运行反向去噪 step。两者训练都只依赖真实数据加人工噪声,生成都从新噪声开始。

13 · CONDITIONAL GENERATION提示词、类别标签如何进入?

若希望生成“红色陶瓷杯”而非任意图像,就把引导信息记为 y,令网络变成 uθ,t(x | y)εθ,t(x | y)。文本先经编码器变成向量,网络在每一步据此调整箭头。请区分两种竖线:

ut(x | z)训练构造中的条件:已知某个干净样本 z,用它造出可监督的目标。
ut(x | y)用户希望的条件:已知提示词、类别或材料性质 y,引导最终生成结果。

实践中常用 classifier-free guidance:训练时偶尔把 y 丢掉,让同一网络同时学有条件与无条件的方向;采样时将有条件方向相对无条件方向放大。这通常使结果更贴合提示词,但权重过大也会牺牲多样性、产生不自然的图像。

带走三层理解

第一层:从噪声反复修正,得到样本。第二层:修正方向来自一个随时间变化的向量场。第三层:Flow Matching 用“构造一条数据-噪声路径并回归其速度”来学习该向量场;Diffusion / score matching 则常用“预测加入的噪声”学习同类信息。

SOURCE NOTE本文依据

本文参考 MIT 6.S184《An Introduction to Flow Matching and Diffusion Models》(Peter Holderrieth、Ezra Erives,2025)中的概率路径、条件 flow matching、score matching 与连续时间 ODE/SDE 描述,个人见解,仅供参考。