从第一性原理理解 Diffusion & Flow Matching(SDE、ODE 大一统视角)— 中文解读
对知乎长文《两万字长文!从第一性原理理解 Diffusion & Flow Matching》的结构化解读:以 SDE/ODE 大一统视角串起加噪、反向生成、Score 学习与采样器。
来源:qingkeai.online 转载自知乎作者「妖妖(尚书尧,中科院自动化所)」 原文链接:https://qingkeai.online/blog/Diffusion-FlowMatching%20 原文发布日:2026-08-15 | 作者:尚书尧(知乎 ID:妖妖) 说明:本文为原文全文转载(中文),附结构化中文解读。原文以中文写就,未作翻译;解读部分为整理归纳,不代表原作者观点。
第一部分:正文(Original Article)
作者:尚书尧 中科院自动化所(知乎ID:妖妖) https://zhuanlan.zhihu.com/p/2070555284918080338
作者:尚书尧 中科院自动化所(知乎ID:妖妖) https://zhuanlan.zhihu.com/p/2070555284918080338
2026 年,我相信几乎没有CVer不知道 Diffusion。不管是做 AIGC 生成,还是做具身智能里的 policy learning,Diffusion 都已经成为绕不开的核心技术。
第一次学 Diffusion 时,你是不是也遇到过这种开场:先给出一条“原信号乘一个系数,再加上高斯噪声乘另一个系数”的公式,接着介绍噪声日程,然后就开始训练网络,公式怎么用说得很清楚。
再往后,SDE、反向 SDE、概率流 ODE、DDIM 一个接一个登场。你可能还听过“Diffusion本质是SDE和ODE”,“DDIM 可以视为欧拉法采样”,或者“换个求解器就能减少采样步数”。这些话各自都有条件和来由,可一旦省略中间的因果链,知识就容易变成一地散落的钥匙。
这个Blog想把中间那根线补上。我们会从一个第一性原理式的问题出发: 从“生成究竟是什么”开始,到“为什么需要中间路径”;从“随机扩散过程”走到“确定性 ODE”;再从“沿速度场生成”自然过渡到 Flow Matching 。我相信不管大家是不是理解这些内容,沿着文章的思路串一遍都很有帮助。
所谓“生成”,在概率上究竟要完成什么?
所谓“生成”,在概率上究竟要完成什么?
答案并不神秘: 我们希望能采样真实分布,但是这个是不可能的,我们只会采样最简单的分布(比如高斯分布)。那我们能不能把一个容易采样的噪声分布,搬运成真实数据分布?
接下来,我们会一步步地看清:为什么要在两个分布之间铺一条路,SDE 如何描述一条随机的路,为什么同一组中间分布又能由 ODE 确定性地搬运,以及“加速采样”为什么会自然变成一个数值求解问题。等这条主线走通后,Flow Matching 也会显得很自然:既然生成可以看成沿一个速度场搬运分布,那么我们干脆直接学这个速度场会怎样?
为了少走一份符号上的冤枉路,先立一块小路标。在 Diffusion 部分,本文采用文献中常见的“加噪时间”约定:
t\in[0,1] 表示加噪进度: t=0 是数据, t=1 是噪声。正向加噪沿 0\to1 运行,反向生成沿 1\to0 运行。
1. 生成的本质:把一个分布搬运成另一个分布
先暂时放下 Diffusion、SDE 和 Score 这些名字,只看生成任务本身。我们手里有一个很容易抽样的基础分布,例如标准高斯分布:
同时,我们还有一批来自真实世界的训练数据:
生成模型的目标,是建立一套随机机制,让它的输出分布尽可能接近 p_{\mathrm{data}} 。如果这套机制用函数 G 表示,那么一次生成可以写成
我们真正检查的是:重复抽取许多个 Z ,再经过 G 之后,整群输出是否具有真实数据中应有的类别、姿态、构图和细节比例。用一句话概括:
这个视角有个很重要的细节:对某一个具体噪声 z ,数据集并没有指定它必须变成哪一张图片。生成任务约束的是大量输出的整体规律。一张单独的生成图看起来很好,仍然可能只是“蒙对了一次”;当一整批样本都兼顾逼真度与多样性时,我们才真正学到了一个生成分布。
文本到图像等条件生成任务也没有改变这个本质。给定条件 c 时,目标变为
条件 c 会缩小合理结果的范围,通常仍会对应许多张可能的图片。因此,相同条件配上不同的 Z ,应当能产生语义一致又各有细节的样本。
1.1 训练集给了样本,没有给出抽样规则
训练集让我们看到了 p_{\mathrm{data}} 产生的一批结果,却没有把这个分布的完整密度函数、生成程序或抽样器一并送给我们。如果任务只是从训练集里抽出一张旧图,存一张名单就够了。生成模型更想做的事情,是从有限样本中学到可以泛化的分布规律,随后抽出训练集里从未出现过的新样本。
于是,“会生成”可以拆成两个层次:
- 单次采样 :从基础分布抽一个随机变量,得到一个具体结果;
- 分布建模 :让所有可能结果的频率与结构,共同逼近真实数据的规律。 后者才是核心难题。它也解释了为什么生成模型要从概率分布谈起:只盯着某一张图片,看不见“多次生成后整体会怎样”。
1.2 只知道起点和终点,还不知道该怎么走
现在,生成问题已经被压缩成一个很干净的目标:
可是,两个端点还不足以确定一套生成规则。就像在地图上圈出北京和上海,你依然可以选高铁、飞机,甚至兴致勃勃地绕一大圈。分布之间也存在许多种搬运方式,它们会带来不同的中间状态、训练难度和采样成本。
一步完成搬运完全可行。GAN 的生成器和 VAE 的解码器,都能用一次网络前向计算得到样本(但是GAN难训练,以及VAE生成的图片很模糊都是众所周知的了~)。Diffusion 选择了另一种组织方式:在数据和噪声之间安排许多个逐渐变化的中间分布:
有了这些中间分布,一次跨度很大的转换,就被拆成了许多个局部小问题:当前样本位于进度 t 时,下一小步应该怎样走?模型可以在每个中间状态上重新读取已经显现的结构,再继续向更清晰的方向修正。这就是迭代去噪的核心形态。
新问题也跟着来了: 这组 p_t 由谁规定?训练时又去哪里找它们?
1.3 用加噪为中间分布铺路
从噪声生成图片很难,把一张已知图片弄得更模糊却很容易。高斯噪声又恰好很听话:我们会采样,知道怎样调整它的强度,也能分析数据被它扰动后的统计规律。
于是,Diffusion 先从数据端出发,主动设计一条逐渐加噪的前向路径:
沿着这条路,真实数据先只混入少量噪声,随后变得越来越模糊,最终接近一个容易抽样的高斯噪声分布。每个噪声程度都自然定义了一个中间分布,训练所需的中间状态也就有了来源。
1.4 路径、轨迹与中间分布
为了把“铺了一条路”说得更准确一点,我们定义一串前后相连的随机状态:
大写的 X_t 表示进度 t 时的随机变量。 X_0 会因抽到的真实样本而变化;在给定 X_0 以后,随机加噪还会让后续的 X_t 继续变化。把所有时刻的随机变量放在一起,
就得到一个随机过程。它规定了随机状态如何沿时间连续演化。
实际运行这个过程一次,把本次用到的随机量都采样出来,便会得到一串具体结果:
小写的 x_0,x_{\Delta t},\ldots,x_1 组成了该随机过程的一条具体轨迹(sample path)。它记录了一个样本在某次加噪中经过的状态。
同一条轨迹里的各个 x_t 前后相连。换一次起点或随机噪声,就会获得另一条轨迹。现在想象我们同时运行了许多条轨迹,再于时刻 t 按下暂停键:画面中所有样本的整体分布,就是 p_t 。
生成时,我们关心的是 整体分布能否沿 p_1\to p_0 正确演化。每个新噪声样本都可以走出自己的生成轨迹,它无须找到某张真实图片当年的加噪原路 。这个区分会在理解反向 SDE 时派上大用场。
1.5 真正要学的,是每一小步应该怎么走
到这里,生成任务的结构已经清楚多了:
- 我们会从高斯分布采样初始噪声;
- 我们用前向加噪规定了中间分布 p_t ;
- 找到一条反向的局部演化规则,让样本从 p_t 一小步走向 p_{t-\Delta t} 。 这条局部规则可以带有随机性,告诉我们下一步的转移分布;它也可以是确定性的,为每个当前位置指定一个速度。前者会引向反向 SDE,后者会引向概率流 ODE 和 Flow Matching。它们共享同一个核心视角:
然而,问题还是非常大。我们一直是模糊的分析,现在还差一块关键拼图: 前向时,怎样用严格的数学语言描述“状态连续变化,并在每一小步加入新的高斯扰动”?而当前向路径确定后,它的反向规则又能否从已知理论中导出?有没有数学工具给我们使用?
2. SDE:从一小步加噪到反向生成
描述这种连续随机演化的数学语言,就是随机微分方程(stochastic differential equation,SDE)!它能同时描述确定性变化与随机扰动,也有成熟的时间反演理论。
我们会沿一条很明确的路往前走: 先写出前向加噪的局部更新,再把无穷多小步累积成任意时刻的直接加噪公式,最后调用时间反演定理得到反向 SDE 。走完这三步,Diffusion 究竟需要学什么就会自己浮出来。
本节的最后,我们再用高斯和双峰分布看清 Score 这张方向地图,为下一节的学习方法做好准备。
2.1 为什么这里选择 SDE?
要让数据与噪声之间的概率路径真正“跑起来”,我们需要一套局部规则,同时说清楚两件事:单个样本的下一小步怎样走,以及整群样本的分布怎样随之变化。
对当前任务来说,SDE 正好很合手。它用一条连续时间的随机动力学规则,在每一小步中同时安排两种变化:
- 一个可控的确定性调整,用来逐渐减弱原信号;
- 一份新采样的随机扰动,用来持续注入高斯噪声。 更关键的是,SDE 已经有成熟的时间反演理论。我们可以先主动设计前向加噪,再从理论中导出反向动力学,无须凭感觉猜一套去噪规则。
2.2 前向 SDE:先用一小步看懂加噪
在 Diffusion 的标准时间约定中, t=0 是数据、 t=1 是噪声,因此加噪沿 t 增大的方向进行。
在写第一条公式之前,先定义马上会用到的四个符号:
- X_t 是加噪进度 t 时的一张随机图片。
- \Delta t>0 是一个很小的加噪步长,因此下一个进度是 t+\Delta t 。
- z\sim\mathcal N(0,I) 是一份与 X_t 形状相同的标准高斯噪声。
- g(t) 是我们预先规定的噪声强度: g(t) 越大,这一小步加入的随机扰动越强。
先试试最朴素的版本:只加高斯噪声
假设当前位于 t ,向噪声端走一个很小的距离 \Delta t>0 ,就会到达 t+\Delta t 。最直接的加噪方式确实是
这条式子每走一步都会重新抽取一份高斯噪声,因此它确实定义了一个合法的随机过程。
这里的 \sqrt{\Delta t} 可不是装饰。高斯扰动的方差要与时间长度 \Delta t 成正比,因此标准差就应该按 \sqrt{\Delta t} 缩放。例如,把单位时间分成 N 步,每步方差约为 g^2\Delta t ;由于 N\Delta t=1 ,累计方差仍保持在有限尺度。正是这个缩放,让时间步越分越细时,随机效果依然不会消失或爆掉。
纯加噪会把整体尺度越吹越大
只加噪声有一个很直观的后果:原数据一直留在原位,新噪声则不断累积。固定一张原始图片 X_0=x_{\mathrm{data}} 后,结果可以理解为
随着噪声累积,每个数据点周围的云团会越来越宽,中心却仍留在 x_{\mathrm{data}} 附近。结果当然会“很含噪”,却未必会落在我们预先选定的标准高斯 \mathcal N(0,I) 上:
- 不同原始数据形成的云团中心仍然不同;
- 噪声方差持续累加,整体方差不再是单位方差。 如果终点本来就是一个大方差高斯,纯加噪也可以工作。但是我们是希望选择尺度固定的标准高斯作为终点(因为标准高斯最好采样),所以需要再加一个可控的确定性调整:它一边淡化原始数据的影响,一边帮我们管住整体尺度。
加一份线性漂移,把信号尺度管住
为了让原始数据的影响逐渐减弱,同时又保持后面的分布容易分析,我们直接采用最常见的一类确定性调整:让它与当前状态 x 成正比,写成
这里, f_{\mathrm{add}} 称为正向加噪过程的漂移函数, c(t) 是预先设定的缩放速率。本文考虑 c(t)<0 的前向路径,此时 c(t)x 会把当前状态缓缓拉向零,让原信号的占比随加噪进度逐渐降低。取 c(t)=0 时,它就回到了前面的纯加噪过程。
因此,在长度为 \Delta t 的一小步中,确定性调整量是 c(t)X_t\Delta t ,完整更新为
这条式子的读法很朴素:
新状态 = 当前状态 + 确定性调整 (信号缩小) + 高斯随机扰动。
新状态 = 当前状态 + 确定性调整 (信号缩小) + 高斯随机扰动。
其中, c(t)X_t\Delta t=f_{\mathrm{add}}(X_t,t)\Delta t 是确定性缩放, g(t)\sqrt{\Delta t}z 是本步新采样的高斯扰动。漂移负责淡化原信号,随机项负责把新噪声撒进来,两者的分工到这里就很清楚了。
换成概率分布的说法:如果已知当前 X_t=x ,那么在这个小步近似下,下一状态的分布是
这行公式还提醒我们:给定当前状态以后,SDE 规定的是下一状态的条件分布。 c(t) 决定这个高斯分布的中心怎样缩放, g(t)^2 决定它散得有多开。把 \Delta t 取得越来越小,再连续重复这条局部规则,就得到正向加噪 SDE。
2.3 从单个随机样本到整体分布
沿用第 1 节的符号, X_t 表示时刻 t 的随机状态, p_t 表示它的边际分布:
从数据集抽取大量图片,再对每张图独立运行同一条 SDE,便会在每个时刻得到一群样本。这群样本的分布就是 p_t 。我们设计前向 SDE 时,希望它搬运出这样一组边际分布:
小步公式控制单个样本的随机移动,所有样本的移动又共同推动 p_t 演化。反向生成要重现的是这组边际分布的变化顺序。至于某个样本当年究竟走了哪条前向轨迹,生成时并不会保留这份记录。
到这里,前向过程中的量都是已知的: c(t) 和 g(t) 由我们选定,每一小步的高斯噪声现场采样。下面开始做第一次“局部到整体”的转换:解出这些无穷多小步累积到时刻 t 时,数据和噪声分别剩下多少。
2.4 从 SDE 的局部规则到直接加噪公式
前面的线性 SDE 从数据样本 X_0 出发,持续执行“线性缩放+高斯扰动”的小步更新。
在长度为 \Delta t 的一小步中,确定性调整量是 c(t)X_t\Delta t ,我们再写一下一步的更新为:
把这些小步从 0 一直累积到 t ,相当于
两个积分分别汇总一路上的线性缩放和 Gaussian 扰动。高斯分布的优美性质告诉我们,独立高斯噪声的加权和仍然是高斯噪声。因此,给定原始样本后,任意时刻的 X_t 都服从高斯分布,所以我们可以直接求解这条线性 SDE!
给定这次抽到的原始样本 X_0 后, X_t 是均值为 a_tX_0 、方差为 b_t^2I 的高斯随机变量。对每个固定的 t ,都可以用一份标准高斯噪声 \epsilon\sim\mathcal N(0,I) 直接采样(这里不展开中间推导,直接给出结果):
这就是文章开头曾经提到、当时特意没有写出的公式!我们现在知道了,它是线性 SDE 的累计结果:先有局部的漂移和随机扰动,解出后才得到 a_t、b_t 以及这条直接采样公式。
a_t 是数据保留系数,由漂移 c(t) 的累计效果决定。 b_t 是累计噪声系数,它同时受 g(t) 和 c(t) 影响:早期加入的噪声,后面也会跟着漂移一起缩放。小噪声并没有“加完就下班”,它还会参与后续演化。
这条公式保证固定时刻的采样分布与原 SDE 一致。一份 \epsilon 足以生成该时刻的 X_t 。
我们注意这里一切参数都是我们可以人为指定的,所以我们会设置
也就是起点仍是抽到的原始数据样本;在噪声端通常令
使 X_1 接近标准高斯噪声。随着 t 从 0 增大到 1,通常让 a_t 逐渐减小、 b_t 逐渐增大。
两组符号的分工可以总结为:
- f_{\mathrm{add}}(x,t) 和 g(t) 描述 SDE 在当前位置的下一小步;
- a_t 和 b_t 描述从数据端走到当前进度后的累计结果。 g(t) 只描述当前一小步的噪声强度, b_t 则汇总了从起点到当前时刻的全部噪声效果。把一个看成“此刻撒多少噪声”,另一个看成“一路上已经攒了多少噪声”,就不容易混了。
这个公式也意味着,训练时不需要真的从 t=0 连续加噪到某个中间进度。可以直接:
- 取一张真实数据 x_{\mathrm{data}} ;
- 随机选择一个加噪进度 t ;
- 采样高斯噪声 \epsilon ;
- 一步构造出具体带噪样本 x_t 。 这就是训练中“当前有一个带噪状态”的来源:它是我们按照已知公式主动制造的,但是本质是一个干净样本沿着SDE的前向轨迹一步步走来的。
2.5 一个数据样本会形成一个高斯云团
固定 x_{\mathrm{data}} 后,只有 \epsilon 是随机的,因此
所以条件分布为
也就是说,一张固定数据在噪声作用下,会变成围绕 a_t x_{\mathrm{data}} 散开的高斯云团。
把所有数据样本产生的高斯云团叠加,就得到进度 t 下的整体分布:
可以把这个积分想成“叠云彩”:每个真实样本都贡献一朵高斯云,所有云团在位置 x_t 的密度相加,就得到整体边际分布 p_t(x_t) 。
2.6 为什么把正向公式移项,得不到反向生成?
前向加噪已经完全确定,于是一个很诱人的快捷键出现了:直接把正向公式移项,行不行?
对同一次前向更新,代数上当然可以写成
其中的 z 必须是当时前向更新真正抽到的那一份噪声。这个等式因此只能回放一条已完整记录的前向轨迹,它需要同时知道:
- 眼前的 X_{t+\Delta t} 当初来自哪个 X_t ;
- 前向这一小步具体抽到了哪一份 z ;
- 整条前向轨迹每一步使用的随机量。 生成时的 X_1 是从高斯分布中新抽到的,这些历史记录全部缺席。它没有对应的原图,也没有一串“刚才都加了什么噪声”的小票据可以查。
因此,反向生成需要构造一条新的随机过程。它关心的是分布层面的目标:当整群样本服从 p_t 时,反向走一小步后,新的样本群应当服从 p_{t-\Delta t} 。时间反演理论就是为这个分布目标提供局部规则。
2.8 反向 SDE:多出的 Score 项在做什么?
现在就体现出我们选择SDE这样的数学工具的好处:数学家很早就知道反向过程是什么了(也就是SDE的时间反演定理)!前向 SDE 已经规定了整组边际分布怎样从数据演化到噪声。对于本文这类扩散系数只依赖时间的 SDE,时间反演定理给出的单个样本反向小步为(我们不推导这个公式,但是会解释其直观思想)
生成时,时间从 1 逐渐减小到 0。这条公式可以拆成三个动作来读。
第一项:沿负时间撤销已知漂移
正向漂移由我们预先设计,沿反向时间运行时符号随之改变。这一项负责处理前向过程中的确定性缩放。
第三项:重新进行随机抽样
表示反向小步会现场采样一份新的高斯扰动。它为完整的反向转移保留了随机性;与前两项共同作用后,样本群才会落到正确的上一个边际分布,并保留多样的生成轨迹。
第一项和第三项都是我们可以从正向公式移项看出来的(noise正负号都是一样的意义),唯一神奇的是第二项(当然,我们自然会意识到反向过程需要一个从噪声到真实分布的“收束数据”的项)。
第二项:用 Score 补回分布方向
反向公式新增的量是
它叫作分布 p_t 在位置 x_t 处的 Score。这项新信息依赖当前的边际分布,并会按照噪声强度 g(t)^2 进入反向修正。
前向噪声的具体历史已经丢失,当前样本需要借助整群样本在时刻 t 的密度结构决定下一小步。Score 与反向漂移、随机项合在一起,才能把整群样本搬到上一个边际分布。
于是,反向 SDE 的三个动作可以概括为
我们先把 Score 本身看清楚:它在当前位置告诉我们什么,又会怎样随着噪声降低而改变。
2.9 Score 是当前分布的局部指南针
分布 p_t 在位置 x_t 处的 Score 定义为
它描述当前边际密度在 x_t 附近上升最快的方向。一维情况下,Score 告诉我们应该向左还是向右才能进入更高密度的区域;在图像空间中,它是一支与图片形状相同的高维向量,每个分量都参与修正当前图像。
Score 只负责提供当前 p_t 的局部密度方向。生成时,它会与反向漂移和随机扰动一起组成完整的反向小步。因此,可以把 Score 想成一枚实时指南针:它告诉样本眼下哪边更“像这个噪声等级的数据”,整段旅程仍由反向 SDE 来安排。
对数让这支指南针只关心相对密度变化:
如果密度整体乘上一个与 x_t 无关的常数,对数梯度保持不变。这一点很省心,因为高维概率分布的归一化常数往往很难计算。
以一维高斯为例,
x>0 时箭头向左, x<0 时箭头向右,所有方向都朝向高斯分布的高密度中心。离中心越远,箭头的绝对值也越大。高斯分布只有一个中心,方向很好猜。数据分布通常复杂得多,Score 也会随着时间改变模样。下面先看一幅动态地图,让这支“指南针”真正动起来。
2.10 Score 地图怎样随时间变细?
用一个一维双峰分布,可以直观看见 Score 如何从粗粒度方向逐渐长出细节。假设数据分布有两个不对称的峰:左峰较高,右峰稍低。前向加噪会逐渐抹平双峰;反向生成则从高斯端出发,让两个模态重新显现。
在 t=1 ,初始状态为 X_1\sim\mathcal N(0,1) . 下面的第一张图从第一个反向小步后的 p_{1-\Delta t} 开始。此时蓝色曲线仍与灰色高斯非常接近,只留下微弱的整体偏斜。随着 t 继续减小,分布先出现肩部,随后分裂成两个清晰的峰。
每一格下方画的是 s_t(x_t)=\nabla_{x_t}\log p_t(x_t) 的方向:绿色箭头表示密度向右升高,橙色箭头表示密度向左升高,黑点是方向发生切换的位置。
高噪声阶段只有很粗的分布结构,Score 先把样本引向大致正确的区域。双峰逐渐形成后,方向场也分成两个吸引区域,中间低密度位置的箭头开始朝两侧展开。它很像一张会随路况实时刷新的导航图: p_t 每变一点,Score 地图也跟着更新一点。
下面的粒子轨迹展示了同一件事。反向早期的粒子云仍接近高斯,随后在随时间变化的动力学作用下逐渐形成两条分支。
这两张图只把 Score 的方向单独画出来,实际的边际分布演化仍由反向漂移、Score 修正和随机项共同完成。随机项让粒子拥有不同轨迹,随时间变化的 Score 则持续提供与当前分布匹配的局部方向。
3. 怎样从数据中学到 Score?
我们现在已经知道,我们先采样一个高斯噪声 x_1 ,然后可以一步步沿着SDE反向移动到生成的数据 x_0 :
生成时,时间从 1 逐渐减小到 0。公式中各项的信息来源也已经清楚:
- f_{\mathrm{add}}(x,t)=c(t)x 与 g(t) 由前向 SDE 预先规定,是我们人为定好的参数;
- 随机项 z 可以在生成时直接采样;
- \nabla_{x_t}\log p_t(x_t) 依赖未知的中间边际密度,暂时无法直接计算。 因此,整个 Diffusion 的学习问题终于收束到一个明确缺口:
上一节已经给出了 Score 的定义和动态直觉,现在可以专心处理它的学习问题。
刚刚讲了这么多对CVer不友好的数学,现在终于引入神经网络了!
但是,反向 SDE 需要边际 Score \nabla_{x_t}\log p_t(x_t) ,可边际密度 p_t(x_t) 通常没有显式公式,无法直接生成监督标签,神经网络能怎么学出这个score呢?
3.1 反向 SDE 需要边际 Score
为与训练代码中的常见记号保持一致,下面用 x_0 表示一份具体的干净数据。固定 x_0 后,前向加噪在时刻 t 产生的条件分布为
每个干净样本都会贡献一朵高斯云,把所有云团按数据分布混合起来,才得到反向过程经过的边际分布:
生成时,网络接收当前状态 x_t 和时间 t 。同一个带噪状态可能由许多不同的 x_0 产生,网络也不会拿到某张原图作为答案提示。因此,反向 SDE 所需的目标是整体混合分布的边际 Score
这里出现了真正的学习难点:我们可以从 p_t 中采样,却通常写不出它在高维空间中的显式密度,更难直接把边际 Score 算出来当标签。
3.2 条件 Score 提供可计算的标签
边际密度很难写,单朵条件高斯却十分听话。对 t>0 ,它的条件 Score 由于是已知的高斯分布,可以直接求导:
训练时,我们主动采样 \epsilon\sim\mathcal N(0,I) ,并构造
把这个具体的 x_t 代入条件 Score,立即得到
x_0 来自训练集, \epsilon 由我们亲手采样, b_t 又是前向过程的已知系数,于是每个带噪样本都会附带一张精确的条件 Score。这里也可以看出score的性质:条件score是从 x_0 加噪来的,那自然“地图” 会指向去噪的方向。
下一步要做的,是把许多条件score变成真正需要的边际 Score。
3.3 条件平均把两种 Score 接了起来
固定时间 t 和当前状态 x_t 后,不同干净样本产生它的可能性由后验分布 p(x_0\mid x_t,t) 描述。为了看清这个后验分布怎样出现,我们从边际密度的混合公式开始:
现在逐步对它求导:
这个直观含义也非常明显:每个可能的干净来源都举着一支条件 Score 箭头,后验概率决定它的“投票权重”,所有箭头的加权平均就是边际 Score。
最关键的一步:MSE 会自己完成后验平均
这里是整套 Score 学习最关键、也最让人兴奋的一步。我们能够计算每个训练样本的条件 Score \nabla_{x_t}\log p_t(x_t\mid x_0) = -\frac{\epsilon}{b_t} ,真正需要的边际 Score \nabla_{x_t}\log p_t(x_t) 却藏在未知的高维密度 p_t(x_t) 里。
看起来还差一道很难跨过去的沟?实际上,我们已经站在对岸了!普通的均方误差回归恰好会自动补上这座桥,而且这个结论在数学上是精确的!
令
作为可计算的条件 Score 标签,并用它训练网络 s_\theta(x_t,t) :
网络只看到 (x_t,t) ,标签背后的 x_0 和 \epsilon 都不会作为输入。对于同一个 (x_t,t) ,训练数据可能给出许多来自不同干净样本的条件 Score 标签。根据 MSE 的经典条件均值结论,固定输入后,最优输出就是这些标签的条件平均。那还记得我们上面推导的,条件score的平均是边际score吗?因此,网络的最优输出就是边际score!也就是:
这正是神经网络在这里很厉害的地方。它从未显式写出 p_t(x_t) ,也无须逐个枚举可能的 x_0 或手工计算后验权重;它只需反复观察“带噪输入 (x_t,t) —> 条件 Score 标签”这样的训练对。MSE 的回归性质负责给出正确的条件平均,神经网络则把高维空间中无数位置、无数噪声等级下的平均结果压进同一个函数 s_\theta(x_t,t) 。
所以,MSE 提供了“学什么”的数学保证,神经网络提供了“在巨大图像空间里把它学成一张连续方向地图”的表达能力。在数据充分、模型容量足够且优化达到理想解时,我们最终得到
这就是我们能够从样本中学到 Score 的核心原因。这种“用带噪条件标签学习边际 Score”的训练方式,通常称为 (conditional) denoising score matching。
3.4 为什么 DDPM 喜欢预测噪声?
直接预测 Score 完全可行,不过条件标签 -\epsilon/b_t 的尺度会随时间明显变化。DDPM 常用一个更顺手的参数化:让网络预测尺度较统一的标准高斯噪声 \epsilon ,再通过已知的 b_t 换算成 Score。
这个换算可以从一朵条件高斯云看懂。固定 x_0 后,云团中心是 a_tx_0 ,一次加噪把样本推到
b_t\epsilon 是从中心指向带噪样本的位移,反方向便指回这朵云的高密度区域。条件 Score 正好给出这个反向方向,并按方差进行缩放:
令噪声预测网络为 \epsilon_\theta(x_t,t) ,其常见训练目标为
根据上一节的条件平均性质,固定 (x_t,t) 时,最优噪声预测为
这里的 p(\epsilon\mid x_t,t) 是由训练联合分布
诱导出的噪声后验分布。最优噪声预测与边际 Score 的关系为
因此,噪声预测网络输出的是当前位置所有可能噪声的条件平均;采样器再乘上已知系数 -1/b_t ,就得到反向 SDE 所需的边际 Score。 t 也必须输入网络,因为不同噪声等级对应不同的 p_t、b_t 和方向地图。
3.5 一次噪声预测训练怎样进行?
线性高斯 SDE 允许我们直接构造任意时刻的带噪样本,因此训练时无须逐步模拟整条前向轨迹。一次常见的连续时间训练迭代包括:
- 从训练集采样干净数据 x_0\sim p_{\mathrm{data}} ;
- 采样噪声程度 t\sim\mathcal U(0,1) ;
- 采样标准高斯噪声 \epsilon\sim\mathcal N(0,I) ;
- 使用已知系数构造 x_t=a_tx_0+b_t\epsilon ;
- 计算预测 \widehat\epsilon=\epsilon_\theta(x_t,t) ;
- 最小化均方误差 |\widehat\epsilon-\epsilon|_2^2 。 这里的小写 x_0,x_t 表示本次训练抽到的具体张量;大写 X_0,X_t 表示相应的随机变量。 a_t 和 b_t 由前向加噪过程预先确定,训练期间保持固定。
离散 DDPM 会先均匀采样
再使用第 k 个噪声等级对应的 a_k,b_k 。文本生成图像等条件模型还会把文本条件 c 输入网络,得到 \epsilon_\theta(x_t,t,c) ;训练的概率逻辑保持相同。
训练完成后,噪声预测与 Score 网络之间的接口为
至此,反向 SDE 中原本空着的 Score 项已经有了可计算的神经网络近似。
3.6 预测 x_0 也是一种输出参数化
网络也可以直接预测干净数据,常见损失写成
由 x_t=a_tx_0+b_t\epsilon 可知,给定预测结果 \widehat x_0 后,可以换算出
进而得到
直接 Score 预测、噪声预测和 x_0 预测都在描述同一个带噪关系,只是选择了不同的输出坐标。已知 a_t , b_t 后,它们可以相互转换;不同参数化的数值尺度可能有所不同。
3.7 a_t 和 b_t 由噪声日程确定
a_t 控制保留多少数据信号, b_t 控制累计多少高斯噪声。它们属于前向路径的已知系数,通常满足
并随 t 平滑地从数据端过渡到噪声端。
一类常见的连续时间设计使用正的噪声日程 \beta(t) :
代入第 2 节的线性 SDE 解,可以得到
因此
这类路径称为 variance-preserving SDE(VP-SDE)。当数据已被缩放到单位方差附近时,信号逐渐减少、噪声逐渐增加,整体方差仍保持在相近尺度。
离散 DDPM 通常先规定 \beta_1,\ldots,\beta_T ,再定义
对应的累计系数为
linear schedule、cosine schedule 等名称,描述的就是信号与噪声怎样沿时间重新分配。它们会改变各个时间区域的训练难度和信噪比,却不会改变本节建立的接口:前向路径给出 a_t,b_t ,网络预测噪声或干净数据,采样器再将预测转换成 Score。
到这里,反向 SDE 中的所有量都已经可以计算!
4. 万事俱备:沿着反向 SDE 开始采样
第 3 节已经训练好了 Score 网络,反向生成需要的零件也终于凑齐了:
- scheduler 给出前向漂移 f_{\mathrm{add}}(x,t) 和噪声强度 g(t) ;
- 网络 s_\theta(x_t,t) 近似当前分布的 Score;
- 初始状态可以直接从 x_1\sim\mathcal N(0,I) 采样。 接下来的任务很具体:从这团高斯噪声出发,沿反向 SDE 一步步走回数据分布。方程负责告诉我们局部方向,采样器负责把这些方向变成一串真正算得出来的状态。
4.1 方程已经有了,还差一个求解器
反向 SDE 描述的是连续时间中的演化规律。把真实 Score 换成网络预测后,它已经是一条可计算的方程:
这里的 t:1\to0 提醒我们,生成沿着时间减小的方向进行。方程规定了每个位置附近应该怎样变化,却还没有替计算机选好具体的落脚点。为了得到一张图片,我们需要选取离散时间网格
然后从
出发,依次计算
这串状态构成一条实际的采样轨迹。换一份初始噪声,或者在随机求解器中换一组途中噪声,就会得到另一条轨迹。
因此,生成过程可以分成三个紧密衔接的环节:
可以把它想成看地图和走路:反向 SDE 给出沿途的局部路标,数值求解器负责一步步把脚迈出去。
4.2 Euler–Maruyama:沿反向 SDE 迈出一小步
上一节已经得到可计算的反向 SDE:
Euler–Maruyama 在这里做的事情很朴素:从 t 走到 t-\Delta t 时,暂时把当前位置的反向漂移和噪声强度当作常量。
这一步的时间增量为
所以确定性位移是
随机位移仍然写成
把两部分合起来,便得到最基础的反向 SDE 采样小步:
每一步都很简单:网络先看一眼当前位置,给出 Score;求解器再沿这个方向走一小步,并补上一份新的高斯扰动。重复这套动作,噪声便会一点点长出结构。
4.3 换成扩散代码里常见的 noise prediction 形式
实际模型往往预测噪声 \epsilon ,scheduler 则保存前向路径的 a_t,b_t 。下面把 Euler–Maruyama 更新改写成这套更熟悉的语言。
记网络的噪声预测为
第 3 节已经得到噪声预测与 Score 的换算关系:
代入反向小步公式,有
现在只需把 f_{\mathrm{add}} 和 g 也写成 a_t,b_t 。对于线性前向路径
对应的漂移系数与扩散系数满足
以及
其中 \dot a_t=\mathrm da_t/\mathrm dt,\dot b_t=\mathrm db_t/\mathrm dt 。于是反向小步可以完全写成
公式虽然长了一点,里面的东西却很规整: a_t,b_t 来自 scheduler, \widehat\epsilon_t 来自网络, z 是本步新抽取的高斯噪声。
在 VP 日程下,它就是熟悉的 DDPM 小步
直接切换到 DDPM 的离散时间记号。令
DDPM 的前向边际分布为
与本文一直使用的线性高斯路径
逐项对照,立即得到
把 b_t=\sqrt{1-\bar\alpha_t} 直接代入离散反向更新,并采用 DDPM 原论文的 fixed-large variance \beta_t ,便有
这就是 Ho、Jain 和 Abbeel 在 DDPM 原论文 Denoising Diffusion Probabilistic Models 中给出的采样更新!换言之,把 VP 路径的 a_t,b_t 换成 DDPM 的 \bar\alpha_t,\beta_t 后,前面得到的反向去噪小步就是熟悉的 DDPM sampler。
4.4 为什么 DDPM 步数多,DDIM 又怎样迈大步?
Euler–Maruyama 每次只使用当前位置的局部信息。样本一移动,网络给出的 Score 也可能跟着改变,于是 DDPM 通常走一小步就重新调用一次网络。时间网格越密,轨迹越容易及时校正,代价则是昂贵的网络前向次数。
DDIM 想解决的正是这个速度问题:能不能从 t 直接走到更早的 s<t ,把中间许多小步合成一个大步?
跳步,其实是在计算一段 t\to s 的积分 把反向 SDE 从 t 积分到 s ,形式上有
这行公式把“跳一步”写得很诚实:我们需要知道整个区间内的反向漂移,而漂移又依赖沿途的 Score
其中, f_{\mathrm{add}}、g、a_u 和 b_u 都由 scheduler 给出,布朗增量也可以直接采样。从信息来源看,唯一需要神经网络补充的函数,就是沿途各个位置上的 Score。若严格沿原反向 SDE 前进,状态每变化一点,都要重新调用网络估计一次 s_\theta(X_u,u) 。这便是小步采样很慢的根源。
第一个核心思想:让 t 时刻的预测负责整段
DDIM 在区间起点 x_t 上调用一次网络:
由前向关系 x_t=a_tx_0+b_t\epsilon ,同一次预测还会给出干净数据估计
现在把 \widehat x_{0,t} 暂时当成整个 t\to s 区间的去噪锚点(我们在这个步数里面都信任这个预测)。对于任意中间时刻 u\in[s,t] 和中间状态 x ,用
估计沿途 Score。这份近似沿用的是同一个 \widehat x_{0,t} ,Score 本身仍会随着中间状态 x 改变。
把这份 Score 近似代入反向 SDE,可得
此时 \widehat x_{0,t} 已经固定,其余系数全部来自 scheduler。原来依赖神经网络的非线性问题,就变成了一个系数已知的线性 Gaussian SDE。它可以从 t 整段求解到 s ,中间无须再次调用网络。
gDDIM 从这个数值求解视角解释了 DDIM:用区间起点的网络预测建立局部 Score 近似,再精确求解近似后的动力学。对于 VP 路径,记这条参考反向 SDE 在 t\to s 上产生的随机尺度为
它的解析大步解为
这一步已经完成了真正的跳步:只在 t 调用一次网络,随后直接计算 x_s^{\mathrm{ref}} 。可以把它想成出发前看一次地图,然后让这次判断先管完整个大步;到达 s 后,网络再根据新位置更新路线。
但是问题在于,在很少步数的时候,我们还需要有加噪 \sigma_{t\to s}^{\mathrm{ref}}z 。对于多步生成,我们可以一步步修补这个加的噪声,但是如果步数很少,这样的“随机性”很可能乱了我们少步生成的阵脚,怎么办?
第二个核心思想:保留边际分布,重新选择时间连接
第一个核心思想已经给出了一条可以从 t 跳到 s 的参考反向过程。接下来,DDIM 把目光从“怎样求解这条过程”移到“生成过程究竟需要保持什么”。
生成最终希望得到正确的数据分布 p_0 。同时,采样器会在若干中间时刻继续调用同一个网络,因此这些时刻的状态也应该落在训练时见过的边际分布 p_u 上。只要整组边际
保持一致,网络在每个噪声等级看到的输入分布就没有跑偏。也就是说,一组边际分布只给出了许多张“时间切片”。它告诉我们每个时刻整群样本长什么样,还没有规定同一个样本怎样从一张切片走到下一张。因此,所有单时刻边际并不能唯一确定整个随机过程:
回到 Diffusion,前向加噪规定了每个时刻的单时刻条件分布
这些分布确定了各个噪声等级应该长什么样。我们只需要保证这个分布能保持就行,其他的是不是有自己修改发的发挥空间?也就是说:能不能在保证这个分布不变的同时,让“随机性”小一点?
\eta 显式分配“相信预测”和“重新抽样”的配额
DDIM 用一个可控参数 \eta 缩放参考随机尺度:
相应的大步更新为
目标时刻的总噪声预算是 b_s^2 。DDIM 把这份预算分给两个方向:
因此, \sigma_{t\to s}^{(\eta)} 可以看成一只反向刻度的“信任旋钮”:
\eta 让这份配额可以被我们显式控制。
为什么改变这份配额以后,目标时刻的边际分布仍然不变?回到 DDIM 的理想过程构造,固定一份 x_0 ,此时 s 时刻可以写成
它的条件均值与条件协方差分别为
\sigma_{t\to s}^{(\eta)} 虽然随着 \eta 改变,两部分方差加起来始终是 b_s^2 。因此,对所有合法的 \eta ,都有
这就是我们可以自由选择 \eta 的关键:它会重新安排“沿用预测方向”和“抽取新方向”的比例,同时保持目标时刻的单时刻边际分布。在精确模型下,不同 \eta 经过所有噪声等级后都会到达同一个目标分布!
下图把这件事画得很直观:五组轨迹的连接方式不同,每个时刻的整体分布依然对齐。
当 \eta=1 时,
随机尺度回到前面解析求解参考反向 SDE 得到的数值。当 \eta=0 时,
全部噪声预算都沿用网络当前识别出的方向,大步更新化为
代入 \widehat x_{0,t}=(x_t-b_t\widehat\epsilon_t)/a_t ,还可以写成
这就是 deterministic DDIM。给定同一个 x_t 和网络输出,下一状态 x_s 完全确定;生成的多样性仅仅来自最初采样的
为什么降低 \eta 往往更适合少步生成?
少步采样意味着 t\to s 的跨度很大,而整个区间只使用 t 时刻的一次网络判断。若这时加入较多的新随机量 z ,中间状态会偏离当前预测所依据的方向;网络要等到大步结束后才能重新观察位置并修正路线。步子跨的越大,这种“走出去以后暂时没人纠偏”的影响越明显。
降低 \eta 会把更多噪声配额留给 \widehat\epsilon_t 。轨迹在一个大步内更忠实地沿用当前判断,局部 Score 近似也更容易撑完整段。原始 DDIM 论文 的实验展示了这一趋势。在 CIFAR-10 上,固定采样步数后,较小的 \eta 在少步设置中取得了明显更低的 FID:
10 步时,每个区间都很长,降低 \eta 带来的改善格外明显。到 1000 步时,网络可以频繁更新判断,不同 \eta 的差距便缩小了。这是原论文在特定模型、数据集和采样设置中的经验结果;长链采样还可以从合适的随机方差选择中获益。
DDIM 的两步逻辑至此完整闭环:
第一步减少网络调用,第二步选择大步里有多少配额交给当前预测。两件事配在一起,DDIM 才能在很少的采样步骤中依然走得又快又稳。
5. 从 deterministic DDIM 到概率流 ODE
前面的 DDIM 已经悄悄递来一个很强的暗示:当采样步数很少、每一步都跨得很大时, \eta=0 的确定性路径往往走得更稳。原因也很直观——每次重新注入噪声,样本都会被推到一个新位置,网络给出的去噪方向也会跟着变化;如果中间只剩寥寥几次网络调用,采样器来不及频繁“看路”,随机扰动就更容易积成偏差。
这自然引出一个问题:
既然少步采样中确定性路径这么有用,那么在连续时间里,是否存在一条真正确定性的反向生成方程?
既然少步采样中确定性路径这么有用,那么在连续时间里,是否存在一条真正确定性的反向生成方程?
答案是有!这条与正向 SDE 共享同一组边际分布的确定性动力学,叫作 probability flow ODE(概率流 ODE)。它会把上一节的 deterministic DDIM 接到连续时间里,也会把“怎样采样”变成一个熟悉的数值积分问题。
5.1 正向过程明明随机,反向为什么可以确定?
正向训练仍然使用随机加噪。把一个很小的时间步记成 \Delta t>0 ,正向从 t 走到 t+\Delta t 时,状态近似更新为
第一项是当前位置,第二项是这一步的 drift,第三项是新加入的 Gaussian 扰动。这里出现 \sqrt{\Delta t} ,是因为 Brownian 随机增量的方差与时间长度 \Delta t 成正比。
训练时,我们随机抽取 x_0 、噪声和时刻 t ,让网络学习该时刻的 Score
下面把它简写成
这个量描述的是:站在时刻 t 的位置 x_t ,往哪个方向移动,当前分布的密度会上升得最快。它关心整团样本在这一刻怎样分布,却不会记录某个样本此前经历了哪条随机轨迹。
把所有样本想成一团会变形的“概率云”就很好理解了。SDE 里的粒子一边随漂移移动,一边被随机噪声抖散;我们也可以换一套不抖的交通规则,让每个位置都有一个确定速度。粒子的个人路线会变,整团云却可以在每个时刻保持同样的形状。上一节讨论的“边际分布相同、跨时刻连接可以不同”,正是在这里派上用场。
Score-Based Generative Modeling through SDEs 证明,可以构造下面这条 probability flow ODE:
上式写的是正向小步。生成时把时间倒过来,从 t 走到 t-\Delta t :
沿 0\to1 的方向反复执行第一条更新,它与正向 SDE 在每个时刻都有相同的边际分布 p_t ;生成时反复执行第二条更新,让时间从 1 回到 0。在 Score 精确、步长也足够小的理想条件下,终点就是数据分布 p_0 。
ODE 是 ordinary differential equation,即常微分方程。把右侧记成
用这个记号,上面的两条更新就是
给定初始噪声 x_1 以后,速度场会确定每个位置下一刻怎样移动,途中无须再抽取随机数。因此,同一个初始噪声会对应唯一一条 ODE 轨迹。deterministic DDIM 正是这条连续轨迹的离散版本;后面要做的,就是研究怎样用尽量少的大步把它积分出来。
1/2 的直观意义:别让 Score 一个人太用力
看到这里很容易冒出一个小问号:反向 SDE 里的 Score 系数明明是 1,为什么概率流 ODE 里变成了 1/2?
继续使用刚才的 s_t ,反向 SDE 从 t 到 t-\Delta t 的小步可以写成
在这条反向 SDE 里,完整的 Score 修正和新加入的 Gaussian 扰动是一对搭档,它们一起决定整团概率云怎样变化。
现在我们想把轨迹改成确定性的,于是拿掉了随机项。可如果 Score 仍然保留原来的完整强度,方向盘就几乎全交给了 Score:样本会被过快地拉向高密度区域,整团概率云也会偏离原本应该经过的边际分布 p_t 。
probability flow ODE 的目标,是让确定性轨迹在每个时刻依然保持相同的 p_t 。因此,随机项消失以后,Score 的控制也要随之减弱;它前面的系数从 1 调整为 1/2,重新平衡整团概率云的移动速度。
于是,两套动力学可以这样并排理解:
箭头表示两边产生相同的边际分布演化。左边的单条轨迹会随机抖动,右边的轨迹平滑且确定;到了任意固定时刻,把大量样本放在一起观察,两边的概率云形状一致。
所以,这里的 1/2 可以先这样记:
5.2 怎样阅读常见的 SDE/ODE 图?
这张图把刚才那团“概率云”画了出来。背景颜色表示不同时刻的概率密度,彩色曲线是会抖动的 SDE 轨迹,白色曲线是平滑的 probability flow ODE 轨迹。单看一条线,它们走得很不一样;横着切开任意一个时刻,样本的整体分布却相同。
图中的时间约定与本文一致:
概率流 ODE 告诉我们轨迹应该满足什么方程,真正生成一张图片时,还要把这条轨迹算出来:从初始噪声 x_1 出发,依次得到 x_{1-\Delta t},\ldots,x_0 。这一步就是数值求解。
为什么这个是好事?因为对于ODE,我们有非常多的已知数值分析方法来做采样。Euler、Heun、Runge–Kutta 等方法都能求 ODE。那就是意味着,我们采样的问题可以变为被研究了很久的ODE数值求解的数学问题!这时,大家常说的“DDIM本质不过是欧拉法解ODE”就能理解了。
我们以DPM-Solver 这个经典工作举例,也是因为他的一阶形式和DDIM一模一样,我们也可以认识到DDIM的ODE形式。
DPM-Solver意识到,在ODE的情况下,Diffusion 送给我们一份“已知答案”:scheduler 决定的信号缩放、噪声缩放以及对应的积分权重都能解析计算。我们完全可以把这些已知部分整段算准,只把真正未知的网络输出交给数值近似。这样一来,每次昂贵的网络调用都花在刀刃上。
先认识 Euler 法:只看起点斜率的一阶方法
先不考虑 Diffusion。假设当前状态是 y_t ,规则 F(y_t,\lambda_t) 告诉我们此刻的移动方向。现在想从 \lambda_t 一步走到 \lambda_s=\lambda_t+h ,Euler 法只在起点看一次方向:
它的几何意义很直接:在起点看一眼方向,然后沿着这条切线走完整步。如果真实轨迹中途拐弯,Euler 还会乖乖沿着旧方向前进,终点自然会有偏差(这些都是数值分析课程的最简单内容)。
Euler 每个大步只读取一次起点信息。它的单步局部误差是 O(h^2) ,沿固定长度的轨迹累计后,整体误差是 O(h) ,因此属于一阶方法。
如果把原始 probability flow ODE 直接交给 Euler,并仍用原来的 Diffusion 时间 t ,就会得到最朴素的小步更新:
vanilla Euler 会把 ODE 右侧的所有变化一起近似掉。可在 Diffusion 里, a_t、b_t 以及它们随时间的变化早已由 scheduler 规定,丢掉这些结构就有点可惜了。
DDIM 与一阶 DPM-Solver 仍然遵循“一个大步只在起点看一次网络”的 Euler 思路,同时把 scheduler 决定的线性变化和积分权重解析算完。更准确地说,它们属于针对 Diffusion ODE 的 exponential-Euler 型一阶方法。DPM-Solver 论文也指出,DPM-Solver-1 的更新与 DDIM 相同。
先把方程拆成“解析部分+网络积分”
前面已经有
代入概率流 ODE,从 t 向生成方向走到 t-\Delta t 时,有
其中, c(t)、g(t)、a_t 和 b_t 都由前向加噪过程确定。真正会沿轨迹变化、又无法提前写出解析表达式的,是网络输出 \epsilon_\theta(x_t,t) 。为了把已知部分单独拿出来,我们换一把更顺手的“信噪比刻度尺”:
a_t/b_t 是信号系数与噪声系数之比,所以 \lambda_t 越大,状态越干净。生成时从 t 走到更早的 s<t ,噪声逐渐减少,于是 \lambda_s>\lambda_t 。下面的 x_\lambda 仍是同一条轨迹上的状态,只是时间标签从 t 换成了 \lambda 。
在一个很小的正向时间步里,前向过程给出的系数满足
把状态除以已知的信号系数 a_t ,同一个小步可以整理成
把从 t 到 s 的所有小变化累加起来,并改用 \lambda 记录位置,就得到整段 t\to s 的精确解:
为了看清求解器究竟在近似什么,把积分写成“总权重 × 加权平均”。定义
那么精确解就等价于:
现在,谜底一下子变小了:整步里唯一需要近似的,就是网络沿未知轨迹的加权平均预测 \bar\epsilon_{t\to s} 。一阶与二阶方法的区别,也都藏在怎样估计这个平均值里。
DDIM / DPM-Solver-1:解析处理已知项的 Euler 型方法
在起点 t 调用一次网络:
一阶方法作出最简单的假设:从 t 到 s 的这段路上,网络预测暂时不变。
这等价于用 \hat\epsilon_t 近似未知的加权平均值 \bar\epsilon_{t\to s} 。网络输出暂时按常数处理,前面的指数权重 e^{-\lambda} 仍会完整积分。代回精确解便得到:
这正是前面的 deterministic DDIM 更新!也是 DPM-Solver-1:已知部分整段精确计算,网络部分由起点的一次预测代表。它沿用了 Euler 的一阶近似思路,同时保留了 Diffusion 的解析指数权重,因此也常被理解成 exponential-Euler 方法。
为什么 deterministic DDIM 在这里是一阶方法?
“一阶”描述的是:当步长逐渐缩小时,整条采样轨迹的数值误差会以多快的速度下降。
把这一个 \lambda 区间的长度记成
若网络预测沿 ODE 轨迹足够平滑,那么在长度为 h 的小区间内,它相对起点预测的变化量也是 O(h) :
deterministic DDIM 把这段网络输出近似成常数 \hat\epsilon_t 。区间内忽略的预测变化是 O(h) ,再乘上长度为 h 的累计区间,单个大步的局部误差就是 O(h^2) 。
走完整条轨迹大约需要 O(1/h) 个区间,因此累计误差为
整体误差与步长的一次方成正比,所以 deterministic DDIM 在这个 ODE 数值意义下是一阶方法:
因此,阶数由网络输出怎样近似整段积分来决定。这里讨论的是 \eta=0 的确定性 DDIM,也正是上一节通向 probability flow ODE 的那条路径。
DPM-Solver-2:走到半路,再看一眼方向
DPM-Solver-1 在起点看一次网络,就让这份预测管完整个大步。步长较小时,这样很省事;步长一大,网络方向可能已经在途中悄悄拐弯了。
数值分析中的二阶显式中点法(Runge–Kutta2, RK2)提供了一个很自然的补救办法。令 F(y,\lambda) 表示当前位置的移动方向,并记 h=\lambda_s-\lambda_t 。它先用起点方向预测中间状态,再用中点方向完成整步:
一句话记忆就是:起点负责把我们送到半路,中点负责告诉我们整步该往哪儿走。
DPM-Solver-2 把同样的两阶段结构放进前面的指数积分公式。令
第一阶段在起点调用网络,并用 DPM-Solver-1 预测 \lambda 中点的临时状态:
这个 x_r^{(1)} 是一块“探路石”:它的任务只是把网络送到这段轨迹的中部。第二阶段在这里重新看一次方向,随后完成整步:
这正是 DPM-Solver-2 在中点选择下的更新:scheduler 对应的指数权重依然解析计算, \hat\epsilon_r 用来近似整段网络作用。它也可以写成对一阶结果的修正:
若起点与中点的预测接近,这个修正很小;若方向在半路发生了明显变化,第二次调用就会及时把整步掰回来。
在网络输出沿轨迹足够平滑时,中点近似的单步局部误差为 O(h^3) ,沿固定长度的轨迹累计后得到 O(h^2) 的整体误差。因此,“二阶”说的是误差随步长缩小的速度:步长减半,整体误差大约降到四分之一。
5.4 DDIM 的训练与推理算法
最后用两张算法清单把这一章收好。这里继续使用全文的 VP scheduler 记号
算法一:DDIM 训练
DDIM 沿用 DDPM 的噪声预测训练。模型照常学习各个噪声时刻的去噪方向;跳过哪些时刻,是 inference 阶段才会做的选择。
输入:训练数据分布 p_{\mathrm{data}}、scheduler {a_t,b_t}_{t=0}^{T} 、噪声预测网络 \epsilon_\theta 。
重复执行下面的步骤,直到网络收敛:
从数据集中采样一张干净图片:
随机选择一个训练时刻,并采样一份 Gaussian noise:
使用 scheduler 直接构造时刻 t 的带噪样本:
把 x_t 和 t 输入网络,预测其中的噪声:
计算噪声预测损失:
根据 \nabla_\theta\mathcal L(\theta) 更新网络参数 \theta 。
输出:训练完成的噪声预测网络 \epsilon_\theta 。
训练完成后,网络掌握的是“给我任意噪声时刻的 x_t ,我来判断其中的噪声方向”。至于 inference 时经过全部 T 个时刻,还是挑出一条更短的时间子序列,训练目标都没有把它写死。于是,同一个网络可以搭配 DDPM,也可以搭配不同采样步数的 deterministic DDIM。
算法二:deterministic DDIM inference
输入:训练好的网络 \epsilon_\theta、scheduler {a_t,b_t}_{t=0}^{T} 、采样步数 S 。
从完整的 T 个噪声时刻中选择一个递增子序列:
生成时按照 \tau_S\rightarrow\tau_{S-1}\rightarrow\cdots\rightarrow\tau_0 反向行走。 S 可以远小于训练时的 T ,DDIM 的“跳步”就在这里落到了算法上。
从标准 Gaussian distribution 中采样初始噪声:
对 i=S,S-1,\ldots,1 ,重复执行一次 DDIM 大步。令
首先在当前状态调用一次网络:
然后估计当前状态对应的干净图片:
最后直接执行 deterministic DDIM 大步:
代入 \widehat x_{0,t}=(x_t-b_t\widehat\epsilon_t)/a_t ,也可以把同一个更新写成
循环结束后,输出生成样本
整个 inference 过程只在开头采样一次 x_{\tau_S} 。初始噪声给定以后,每个后续状态都由当前状态和网络预测唯一确定,整条轨迹一路确定地走到 x_0 。
6. Flow Matching:从概率流 ODE 自然走向直接学习速度
走到上一节,我们已经把 deterministic Diffusion 看成了一件很朴素的事:给每个位置一支速度箭头,再沿着箭头把噪声一步步搬成数据。
只是,Diffusion 得到这支箭头的路线稍微绕了一圈。它先设计前向加噪路径,让网络学习 Score 或噪声预测,再把网络输出与 scheduler 组合成 probability flow 的速度
生成时,从 t 走到 t-\Delta t :
整条 Diffusion 路线可以压缩成
看到这里,一个很自然的念头就冒出来了:
既然确定性生成最后需要的就是速度场,我们能不能直接训练速度网络?
既然确定性生成最后需要的就是速度场,我们能不能直接训练速度网络?
可以!这就是 Flow Matching 的出发点。为了让方向一眼就能看懂,下面使用 \tau 表示从噪声走向数据的生成进度:
速度网络直接负责从 \tau 走到 \tau+\Delta\tau :
这里真正棘手的地方是监督标签:我们知道起点是噪声分布、终点是数据分布,却不知道整团样本在中间每个位置应该以什么速度移动。Flow Matching 的小妙招,是先为单个“噪声—数据”配对设计一条容易计算的条件路径,再用这些条件路径教会网络整体的速度场:
下面先从最容易画在脑海里的直线路径开始。
6.1 最简单的直线路径
先独立抽取一份 Gaussian noise 和一份数据:
然后用一条直线把它们连起来:
当 \tau=0 时,我们站在噪声端;当 \tau=1 时,刚好抵达数据端:
更妙的是,这条路每前进一小步 \Delta\tau ,状态的变化都能直接算出来:
因此,这一对样本的条件速度标签就是
对固定的噪声—数据配对,这支箭头从头到尾都不变:方向指向数据,长度等于两个端点的距离。直线路径的监督标签就这么轻松地拿到了。
6.2 直接训练速度网络
对于条件生成任务,再把文本或类别等条件记作 c ;无条件生成时直接省略它。训练时随机选择进度 \tau ,构造对应的 X_\tau ,再让速度网络拟合刚才的条件速度:
这里有一个非常关键、也很漂亮的地方:同一个 (X_\tau,\tau,c) 可能由许多不同的噪声—数据配对产生,每一对样本都带来一支自己的条件速度箭头。网络在这个位置应该听谁的呢?
答案由 MSE 自动给出。均方误差的经典条件均值结论告诉我们,它的最优输出是
也就是说,神经网络会把所有能够到达当前位置的条件速度自动平均,得到真正负责搬运整体边际分布 p_\tau 的速度。这正是 Flow Matching 能够成立的关键:我们只需提供容易计算的单条路径速度,MSE 会帮我们汇总成难以直接计算的整体速度场。 Flow Matching 论文 证明了这种条件训练与直接回归边际速度场具有相同的优化目标。
这和前面的 Score 学习有着同一份“神经网络魔法”:
6.3 生成时求解 ODE
训练完成后,从 Gaussian noise 出发:
然后让时间从 \tau=0 逐渐走到 1。最简单的 Euler 更新是
每一步,网络只看当前位置和当前进度,再给出下一小段的移动方向。时间走到 1 时,样本分布也抵达数据端。
线性路径下: Flow Matching 就是Deterministic DDIM
线性 Flow Matching 与 deterministic DDIM 的联系,可以直接从端点表示中看出来。在线性路径
上,条件速度为(直接对 \tau 求导即可)
把这两个等式联立,可以用当前状态 X_\tau 和速度 v 反推出路径的两个端点:
因此,给定速度网络 v_\theta(X_\tau,\tau) ,可以把它解释成同时给出了一份数据端点预测和一份噪声端点预测:
现在想从当前生成进度 \tau 一步走到更干净的 \rho>\tau 。如果暂时固定这一次网络判断,那么线性路径在 \rho 处的状态应该写成
把上面的 \widehat x_{\mathrm{data},\tau} 和 \widehat\epsilon_\tau 代入:
最后一行正是从 \tau 到 \rho 的 Euler 更新:
这说明,对线性路径而言,下面两种说法其实完全等价:
这是因为他们本质都是用欧拉法在解ODE。
再把 Flow Matching 的生成进度换回前文的 Diffusion 时间:
那么 \rho>\tau 就对应 s<t ,而线性路径变成
也就是说,此时
在 Diffusion 记号里,数据端点预测写作 \widehat x_0 。于是刚才的目标状态变成
这与 deterministic DDIM 的端点重组形式完全相同:
这条逐项对应依赖两个条件:线性路径 a_t=1-t,b_t=t ,以及使用起点速度的 Euler 更新。前文的标准 VP scheduler 满足 a_t^2+b_t^2=1 ,deterministic DDIM 会解析保留它的非线性权重,因此属于 exponential-Euler 型方法。
当然,Flow Matching 给出速度场以后,也可以使用 midpoint、Heun 或 Runge–Kutta 等更高阶的更新。无论选哪一种求解器,线性 FM 的 Euler 与 deterministic DDIM 仍共享同一个一阶直觉:
最后还有一个容易被直线图骗到的小地方:每个噪声—数据配对的条件路径确实是直线,许多条件速度汇总成的边际速度场却可能弯曲。网络生成时沿着后者前进,因此实际采样通常仍会保留多个计算点。
6.4 Diffusion 与 Flow Matching 的关系
现在可以把两条路线并排放在一起了。它们都想完成同一件事:
它们选择了不同的中间语言:
所以,Flow Matching 是从 probability flow ODE 继续向前迈出的自然一步:既然生成阶段最终沿速度场移动,就把“学习速度”本身变成训练任务。Diffusion 的概率路径也可以放进 Flow Matching 框架中;直线只是这一节为了建立直觉而选用的最简单例子,当然也是最常用的。
6.5 Flow Matching 的训练与 inference 算法
最后把线性 Flow Matching 收进两张清单:训练负责学习箭头,inference 负责沿着箭头前进。继续使用
算法一:Flow Matching 训练
输入:训练数据分布 p_{\mathrm{data}} 、噪声分布 \mathcal N(0,I) 、速度网络 v_\theta 。对于条件生成任务,还会同时输入条件 c 。
重复执行下面的步骤,直到网络收敛:
采样一份数据及其条件,并独立采样一份 Gaussian noise:
对于无条件生成,直接省略 c 。
随机选择一个生成进度:
在线性条件路径上直接构造中间状态:
根据直线两端,直接计算监督速度:
让网络根据当前状态、时间和条件预测速度:
计算 Flow Matching loss,并根据梯度更新 \theta :
输出:训练完成的速度网络 v_\theta 。
算法二:Flow Matching deterministic inference
输入:训练好的速度网络 v_\theta 、条件 c 、采样步数 S 。
选择一个从噪声到数据的时间网格:
从标准 Gaussian distribution 中采样初始状态:
对 i=0,1,\ldots,S-1 ,令
并在当前位置调用一次速度网络:
然后执行一个 Euler 大步:
循环结束后,输出生成样本:
整个 inference 过程只在初始化时采样一次 Gaussian noise。给定 X_{\tau_0} 和条件 c 后,后续状态由速度网络与求解器逐步确定。
参考资料
原始论文
- Hyvärinen. Estimation of Non-Normalized Statistical Models by Score Matching , 2005.
- Vincent. A Connection Between Score Matching and Denoising Autoencoders , 2011.
- Ho, Jain, Abbeel. Denoising Diffusion Probabilistic Models , 2020.
- Song et al. Score-Based Generative Modeling through Stochastic Differential Equations , 2020⁄2021.
- Song, Meng, Ermon. Denoising Diffusion Implicit Models , 2020⁄2021.
- Zhang, Tao, Chen. gDDIM: Generalized Denoising Diffusion Implicit Models , 2022⁄2023.
- Kingma et al. Variational Diffusion Models , 2021.
- Salimans, Ho. Progressive Distillation for Fast Sampling , 2022.
- Karras et al. Elucidating the Design Space of Diffusion-Based Generative Models , 2022.
- Lipman et al. Flow Matching for Generative Modeling , 2022⁄2023.
- Liu, Gong, Liu. Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flow , 2022.
辅助阅读
- Fu, Wang. A Tutorial on Diffusion Theory: From Differential Equations to Diffusion Models , 2026:区分反向动力学、Score 学习与数值采样,并从微分方程视角统一常见扩散方法。
- 零推导理解 Diffusion 和 Flow Matching :信号、噪声坐标与直线路径的几何直觉。
- Denoising Diffusion Probabilistic Models :高斯扰动、噪声预测与反向采样。
- Generative Modeling by Estimating Gradients of the Data Distribution :score 与去噪方向。
- Score-Based Generative Modeling through Stochastic Differential Equations :score、SDE 与 ODE 的统一。
- Probability Flow ODE :确定性概率流与数值求解视角。
第二部分:解析(深度解读)
以下为基于原文的结构化中文解读,仅供学习交流,不代表原作者观点。
一、这篇文章在讲什么
这是一篇约两万字的长文,目标是用「第一性原理」把 Diffusion(扩散模型)与 Flow Matching(流匹配) 讲透,并把它们统一到 SDE(随机微分方程)与 ODE(常微分方程) 的框架下。作者刻意不堆砌结论,而是沿着「生成的本质 → 加噪铺路 → 反向生成 → 学 Score → 采样器」的因果链一步步推导,避免知识变成「一地散落的钥匙」。
二、核心主线(按原文的章节骨架)
- 生成的本质(第 1 部分):生成不是「凭空造物」,而是把一个分布「搬运」成另一个分布。训练集只给了样本、没给抽样规则;我们只知起点(数据)与终点(噪声),却不知中间的路径——于是用「加噪」构造一连串中间分布,把从数据到噪声的连续轨迹铺出来,真正要学的,是每一步该怎么走。
- SDE:从一小步加噪到反向生成(第 2 部分):前向 SDE 用「一小步加噪 + 线性漂移」把信号尺度管住(纯加噪会把整体尺度越吹越大);把局部规则推到整体分布后,得到可直接加噪的公式。反向 SDE 相比前向多出一个 Score 项——它像当前分布的局部指南针,用来补回分布方向;而「把正向公式移项得不到反向生成」的坑,正说明 SDE 框架的必要性。
- 怎样学到 Score(第 3 部分):反向 SDE 需要边际 Score,但直接不可得;用条件 Score 提供可计算标签,再用条件平均把两者接起来——最关键的一步是:MSE 损失会自己完成后验平均。这也是 DDPM 喜欢预测噪声、以及「预测 x0 也是一种参数化」的统一来源。
- Flow Matching / 概率流 ODE(后续部分):把 Diffusion 中的随机轨迹换成确定性 ODE(概率流 ODE),采样即可视为对 ODE 的求解;「换个求解器就能减少采样步数」「DDIM 可视为欧拉法」等说法,都在这个大一统视角下自然成立。
三、为什么这篇值得读
- 因果链完整:它把「噪声日程 → 前向/反向 SDE → Score 匹配 → 采样器」之间的推导缺口补齐,读完能解释很多「只记结论」时想不通的点(例如为什么要 Score、为什么 DDPM 预测噪声、为什么 ODE 采样能加速)。
- 统一视角:SDE 与 ODE 不再是两个割裂故事,而是同一连续时间生成过程的概率/确定性两面;Flow Matching 则是从「向量场」角度直接构造这条路径的工程化写法。
- 对实践的指向:采样步数、求解器选择、噪声/ x0 预测的参数化,本质上都是在「轨迹保真度」与「采样成本」之间做权衡——理解底层 ODE/SDE,才能理性地选采样策略而非盲调。
四、与本站其他文章的衔接
- AI 硬件 / 推理系列:Diffusion 是 AIGC 与具身智能 policy learning 的核心,其采样成本直接映射到端侧/数据中心推理算力需求;理解采样器(ODE 求解、步数)有助于评估推理效率上限。
- 数学基础系列:文中的 SDE/ODE、条件期望、MSE 后验平均,是概率与微分方程在生成模型里的直接应用,可与本站「从泰勒级数到硅」「蒙特卡洛」等数学向文章互为映照。






