READING MAP先给出全景图
如果只记住一句话:生成模型不是从零“创造”一张图,而是让一团容易采样的随机噪声,沿着学到的速度场,逐步变成看起来像训练数据的样本。
1 · THE PHYSICAL PICTURE先分清:vector field、trajectory、ODE 与 flow
把许多树叶放进河里,便能同时看见这四个概念:河中每处的水速规则是 vector field(向量场);其中一片树叶走出的路线是 trajectory(轨迹);把所有树叶的起点一起搬到一段时间后的终点,得到 flow(流);ODE 则写下“树叶必须服从当地水速”的规则。
状态向量:粒子此刻在哪里?
二维中,粒子在 t 时刻的位置写作 x(t)=(x1(t),x2(t))T。x 是完整位置向量;x1、x2 是第 1、2 个坐标分量;上标 T 表示列向量。它也可以是“状态”而非几何位置:单摆可写成 x(t)=(θ(t),ω(t))T,分别为摆角和角速度。
Vector field:固定位置,读取那里的瞬时速度
向量场是一个规则:输入当前位置,输出当前位置应有的速度。自治系统写作 ẋ=f(x);若 x=(x1,x2)T,那么 f(x)=(f1(x),f2(x))T,也就是两条方程 ẋ1=f1(x1,x2)、ẋ2=f2(x1,x2)。下标只标明速度在第几个坐标方向的分量。
这个旋转场在 (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 个坐标。
因此,轨迹的切向量总等于该点向量场。对旋转场,如果 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:
对于旋转系统,Φt(x0,y0)=(x0cos t−y0sin t, x0sin t+y0cos t)T。所以 Φπ/2 会把整个平面逆时针旋转 90°,显然不只是描述一颗粒子。
向量场与 flow 的双向关系
自治系统中,先走 s 再走 t 等于直接走 s+t:Φt+s=Φt∘Φs,其中 ∘ 表示先右后左地复合函数。若速度场还依赖绝对时间,例如早晚风向不同,则写 Φt,t₀(x0),以记录从时刻 t0 演化到 t。
2 · ODE FROM ZERO先弄明白:什么是 ODE?
ODE 是 ordinary differential equation 的缩写,中文叫常微分方程。名字听起来吓人,实际只是在写一条很朴素的规则:如果我知道物体此刻在哪里,就规定它下一瞬间应该怎样变化。
从“位置”到“变化率”
设一辆车在时刻 t 的位置是 x(t)。位置本身回答“车在哪”;速度回答“位置变得有多快”。数学中把这个瞬时速度写作 dx(t)/dt。例如,若车始终以每秒 3 米向前,则:
更一般地,速度可以依赖位置。例如山坡上的球,离谷底越远,回到谷底的拉力越大,可粗略写成:
这就是 ODE 的两个组成部分:初始条件(从哪里开始)和变化规则(每一刻怎样走)。在生成模型中,我们把位置换成一个很高维的向量,速度规则换成神经网络。
为什么没有解析解也能算?——欧拉法
大多数 ODE 没有像上面那样漂亮的显式答案。计算机不需要硬求公式,只要把时间切成许多很小的格子。若当前时刻为 t、步长为 h,便暂时认为这极短一段里的速度不变:
从 x0 开始。
把当前位置和当前时间送进规则 v,得到一支箭头。
更新为 xt+h=xt+h·v。
这就是数值求解 ODE,也叫积分或模拟轨迹。
3 · GENERATION AS SAMPLING“生成”在数学上是什么意思?
一张 256 × 256 的 RGB 图片可以排成一个很长的数列;一个含 N 个原子的分子,也可用各原子的三维坐标排成数列。于是,不论对象原本看起来多不同,都可暂时表示为一个 d 维向量 z ∈ Rd。
难点是:我们没有这张地图的解析公式,只有一批样本(照片、蛋白质结构或材料显微图)。但我们很会从标准高斯分布抽样:令 x0 ∼ N(0, Id),它就是一团各维度独立、均值为零的噪声。生成模型所要学的,是把它变成 x1 ∼ pdata 的连续过程。
4 · FORWARD PROCESS先看扩散的正向过程:怎样把数据弄成噪声?
这里有一个术语容易造成混乱。生成时我们想从噪声走向数据;但经典 diffusion 的“正向过程(forward process)”通常定义为相反方向:从干净数据逐步加噪,直到它接近简单高斯噪声。这个方向容易设计,因为只要不断掺入随机数即可。
例如一张真实训练图像
轮廓还在,但细节被扰动
容易从高斯分布重新抽取
每一步猜去掉什么噪声
从新抽噪声开始,而非复原原图
一种连续写法是从一条干净数据 z 取出部分信号,再加入部分标准高斯噪声 ε:
它可以看作图像混合:原图权重逐渐调低,电视雪花权重逐渐调高。训练时,z 和亲手加入的 ε 都已知,因此我们完全知道每个模糊版本 xt 是怎样形成的。这正是监督信号的来源。
5 · CONDITIONAL AND MARGINAL从“知道终点”到“只看整体云团”
训练时会抽到一条具体样本 z,所以可以问:“已知最终要抵达的是 z,时刻 t 的带噪样本会怎样分布?”这叫条件概率路径 pt(x | z);竖线读作“给定 z”。
生成时并不知道终点 z,只知道当前位置 x 和时刻 t。因此真正需要推动的是所有条件云团混合后的边缘概率路径:
条件云团与边缘云团
橙、蓝是已知两个终点时的条件点云;混在一起后是边缘分布。
6 · FROM PHYSICS TO LEARNINGODE 怎样和机器学习连起来?
现在我们已经有两个部分:ODE 告诉我们“只要有速度规则,就能从起点走出轨迹”;正向加噪给出大量“某个带噪状态来自哪条干净数据”的样本。还缺的正是那张复杂的速度地图。它无法手写:对一张百万维图像,在每种噪声等级下、每个可能位置该朝哪走,规则都极其复杂。
神经网络的角色并不神秘:它就是一个参数很多的函数近似器。输入是当前带噪状态和时间,输出是一支同样维度的修正箭头:
不同模型只是在“正确答案”写成什么上不同。去噪 diffusion 常要求网络猜 ε;Flow Matching 则要求网络猜一条概率路径上的速度。它们都把生成问题化成大量普通的监督学习小题:给定 xt 和 t,预测一个已知目标向量。
7 · FLOW MODELSFlow:给空间中的每一点一支“速度箭头”
想象一池染色液。若你知道池中每一个位置、每一时刻的水流速度,就能把一粒墨水放进去,预测它此后如何移动。这张“位置 → 速度”的图在物理中叫速度场,这里称为向量场。
在位置 x、时刻 t,应该朝哪个方向、以多快的速度前进。
若粒子当前位置为 Xt,它始终顺着所在位置的箭头走,便满足常微分方程(ODE):
给定初始位置 x0,这条 ODE 会画出一条轨迹。把所有初始位置一起推进,整个空间像橡皮布一样被平滑拉伸、弯曲,这个总变换叫 ψt(flow):Xt = ψt(X0)。网络学习的是箭头 u,不是一次性直接输出终点。
计算机怎样沿箭头走?
最简单的是欧拉法:把时间切成 n 小段,每一小段都“当前位置 + 小步长 × 当前速度”。步长越小,越接近连续运动;步数也越多。
8 · DIFFUSION MODELSDiffusion:水流之外,再加上热运动
真实悬浮在水里的微粒不会只随水流前进,还会被周围分子的无数次撞击随机推来推去。这正是布朗运动的直觉。扩散模型把这部分不可预测的扰动也写进运动规则。
这叫随机微分方程(SDE)。同一初始点跑两遍,随机碰撞不同,路径也不同。离散模拟时,布朗运动的一小段增量可用高斯噪声表示:
| Flow model | Diffusion model | |
|---|---|---|
| 动力学 | ODE:只有速度场 | SDE:速度场 + 布朗扰动 |
| 一次采样 | 给定初始噪声后确定 | 每一步可注入新的随机性 |
| 关系 | 当 σt = 0 时,SDE 正好退化成 ODE;因此 flow 是 diffusion 的一个特例。 | |
9 · BROWNIAN MOTION AND SAMPLING布朗运动:SDE 里的“每一步都掷一次骰子”
ODE 给定起点后轨迹完全确定;SDE 额外加入布朗运动 Wt,所以同一起点也会走出不同路线。可以想成花粉颗粒在水里:平均水流把它带向某处,水分子的无数次碰撞又让它不断抖动。
同一初始点:ODE 与 SDE
蓝线没有随机项,重复运行会重合;橙线加入布朗扰动,因此会分叉。点击按钮重新抽取路径。
10 · THE CENTRAL TRICK训练目标从哪里来:先设计“中间帧”
说“让噪声变成数据”还不够,因为中途每一刻的速度应是什么?讲义的核心做法是先指定一条概率路径 pt:它描述的不是某个粒子,而是所有粒子在时刻 t 组成的云团分布。
简单、近似各向同性
既有数据轮廓,也保留噪声
分布与训练样本一致
网络在各时刻各位置输出箭头
将新噪声送往样本
一条很常用的条件路径是:拿一条真实样本 z,把它与独立噪声 ε 线性混合:
对固定的 z 和 ε,直接对 t 求变化率,得到这条直线的目标速度:
11 · FLOW MATCHINGFlow Matching:把“会走路”变成一个普通回归问题
网络接收带噪位置 xt 和时间 t,输出一个与数据同维度的速度向量 uθ,t(xt)。训练只需让它接近已知的目标速度 z−ε:
例如一张训练图片或一个分子构型。
通常 t 从 [0,1] 均匀抽取;每个批次覆盖不同的“噪声程度”。
令 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 时整团粒子就会沿正确的概率路径从初始分布到数据分布。
问题是右边的 ut(x) 不可直接算。它包含“在当前位置 x,所有可能终点 z 的条件速度如何加权”的积分;数据集只给了有限样本,无法枚举所有 z。因此我们转而使用已知 z 的条件速度:
需要的背景:条件期望就是“已知部分信息后的最佳平均”
设你只看见当前位置 X,却没看见这颗粒子来自哪个终点 Z。条件速度 V=ut(X|Z) 仍有不确定性;在只知道 X 的前提下,最合理的单一预测就是条件期望 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) 推进,那么它的条件期望
证明思路。令 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 求导即可:
z 来自数据集,t 来自 [0,1],ε 来自标准高斯。
令 xt=tz+(1−t)ε;这保证 xt 正好来自条件路径。
令网络输出与 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
# 训练结束后: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 后得到不同但仍落在数据分布中的样本。
12 · SCORE MATCHINGDiffusion:为什么“预测噪声”就是学习方向?
扩散模型常被描述成“加噪,再去噪”。在高斯路径中,可以写成更一般的形式:
此时网络常训练去预测当初加入的 ε。它看见模糊的 xt、知道时刻 t,猜测噪声是哪一部分:
这不只是一个技巧。若能识别“哪些成分是噪声”,就知道该往反方向修正多少。严格地说,diffusion 的另一种表述学习 score,即 ∇x log pt(x):它指向当前分布密度增长最快的方向。可以把它想成在浓雾里感受“哪里更像数据的高密度区域”的上坡方向。对高斯加噪路径,score 与噪声预测只差一个随 t 缩放的负号,因此二者可以互相换算。
12.1 · WHY DENOISING IS SCORE MATCHING为什么“猜噪声”会学到 score?
score 不是分数,它是概率密度的对数梯度:
一个一维直觉:若点云中心在 0,位于 x=3 的点想回到高密度区域,应向左;位于 x=−3 的点应向右。score 正是在每个位置给出这种“回到更像数据区域”的方向。扩散模型需要它,是因为随机扩散会把点云散开,而 score 提供了抵消扩散、重新聚拢的方向。
从高斯条件路径直接算出条件 score
对固定 z,条件路径为 xt=αtz+βtε,即 pt(x|z) 是均值 αtz、方差 βt2I 的高斯。写下其对数密度后对 x 求导:
因此若网络 sθ,t(x) 预测 score,条件 score matching 的自然平方损失就是:
为何实践中预测 ε,而非直接预测 score?
当 t 接近干净数据端,βt 很小,−ε/βt 数值会很大,直接回归 score 容易不稳定。于是把网络重新参数化为 εθ,t(x)=−βtsθ,t(x),直接学习原始噪声:
定理:条件 score 训练同样学到边缘 score
定理(denoising score matching)。令条件 score 为 ∇log pt(x|z),则边缘 score 满足
证明结构与 Flow Matching 完全平行:把条件 score 看成随机目标 V,把只看 x 的网络当作 g(X),再用条件期望的平方损失投影定理。区别仅在于:Flow Matching 回归的是速度,score matching 回归的是“朝高密度区上坡”的方向。
score 如何放回 SDE?
想让带随机项的 SDE 与 flow 的概率路径一致,需要在漂移中加入 score 修正:
12.2 · END-TO-END DIFFUSIONDiffusion 的训练数据怎样造?训练后怎样生成?
这里最常见的误解是:“diffusion 先生成图,再拿生成图训练自己”。不是。训练时的干净样本 z 始终来自真实数据集;我们只是用已知随机噪声把 z 人为破坏,造出一张张带标准答案的练习题。网络学习的是:给我一张处于某种噪声程度的 xk,告诉我当初混进去了多少 ε。
离散时间的正向加噪:构造训练对
实际 DDPM 常把时间切为 k=1,…,T 个离散步骤。为避免和前文连续时间的 βt 混淆,下面的 βk 是第 k 步预设的小噪声量;定义 αk=1−βk,并记 ᾱk=α1α2…α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。
# 训练结束后:标准离散 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:新样本
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 描述,个人见解,仅供参考。