第 4 讲 · 引导:怎样按提示生成 · Guidance

Generative AI with Stochastic Differential Equations · Lecture 04。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应 Maps to:MIT 6.S184 Generative AI with Stochastic Differential Equations(IAP 2026),Lecture 3-B · 23-Jan-2026 · Classifier-free Guidance;Lab 3 中条件生成与无分类器引导的部分(原课用 MNIST,这里换成代码画出来的”像素数字”)。 阅读材料:原课讲义 Holderrieth & Erives, An Introduction to Flow Matching and Diffusion Models(2026 版,arXiv:2506.02070)第 5 章;Lecture 3 slides 的后半部分;原始论文 Dhariwal & Nichol (2021) Diffusion Models Beat GANs on Image Synthesis(分类器引导)、Ho & Salimans (2021/2022) Classifier-Free Diffusion Guidance。 依据说明:本讲以原课讲义第 5 章为主线:条件生成与引导向量场、分类器引导(贝叶斯公式 + 放大系数)、无分类器引导及其训练算法(Algorithm 5)、扩散模型的引导。“带标签的高斯混合上的闭式引导场""CFG 的样本 vs 倾斜分布的精确样本""一维两高斯的 CFG""标签丢弃概率的影响""像素数字上的 CFG(含’画错的笔画’)“等实验是本讲义补充的。其中”CFG 采样的不是倾斜分布”有近年的论文支持(§3.2);像素数字的实验结果依赖于数据的设计,§4 如实说明。 配套代码 Code:code/lecture04/(4 个脚本 + 2 个模块;PyTorch + matplotlib;每个脚本 3–35 秒,都完整运行过) 预计阅读时间:4 小时(含运行代码)


0. 本讲导航 · How to read this lecture

0.1 学习目标 Learning goals

学完这一讲,你应该能够:

  1. 写出引导向量场 ut(x∣y)u_t(x\mid y) 的训练目标,解释为什么”只把提示当作额外输入”(vanilla guidance)得到的是 p(x∣y)p(x\mid y),而 p(x∣y)p(x\mid y) 本身往往”不够像 yy”。
  2. 用贝叶斯公式推导 ut(x∣y)=ut(x)+bt∇log⁡pt(y∣x)u_t(x\mid y) = u_t(x) + b_t\nabla\log p_t(y\mid x),理解分类器引导和它为什么需要一个”认识噪声”的分类器。
  3. 推导无分类器引导(CFG)u~t=(1−w)ut(x∣∅)+w ut(x∣y)\tilde u_t = (1 - w)u_t(x\mid\varnothing) + w\,u_t(x\mid y),实现它的训练(标签丢弃,Algorithm 5)和采样。
  4. 说清 CFG 的代价:提示遵循度上升、多样性下降、离数据分布越来越远;知道 CFG 不是在倾斜分布 p(x∣y)wp(x)1−wp(x\mid y)^w p(x)^{1-w} 里采样。
  5. 在一个图像数据集上训练 CFG 模型,并用分类器准确率、风格多样性、Fréchet 距离评估引导强度 ww 的影响。

0.2 先修与本讲范围

需要的背景在哪里
条件流匹配、边缘化技巧、Algorithm 3第 2 讲 §3–§4
得分函数、换算公式 u=α˙αx+bt∇log⁡ptu = \frac{\dot\alpha}{\alpha}x + b_t\nabla\log p_t第 3 讲 §1–§2
贝叶斯公式、后验前置讲 P1 §3
条件期望 = 回归的最优解P1 §4.2

本讲的”提示”是类别标签。真实的文生图模型怎样把一段文字变成网络的输入(文本编码器、交叉注意力)是第 5 讲的内容。

0.3 本讲地图 Map

§1  条件生成:引导向量场 u_t(x|y);为什么只这样做不够            ← 代码 01
§2  分类器引导:贝叶斯公式;放大分类器项;含噪分类器              ← 代码 01
§3  无分类器引导:推导、训练(Algorithm 5)、它采样的到底是什么    ← 代码 02、03
§4  图像上的 CFG:像素数字                                        ← 代码 04
§5  全景:引导在大模型里
§6  小结   §7  常见误区   §8  练习   §9  延伸阅读   §10 下一讲预告

0.4 记号 Notation(新增的部分)

记号意思
yy提示(prompt):类别标签、一段文字的嵌入……
∅\varnothing空提示(“什么都不指定”),ut(x∣∅)=ut(x)u_t(x\mid\varnothing) = u_t(x)
pdata(x∣y)p_{\text{data}}(x\mid y)条件数据分布
ut(x∣y)u_t(x\mid y)引导向量场(guided vector field):沿 pt(⋅∣y)p_t(\cdot\mid y) 走的边缘向量场。注意和第 2 讲的条件向量场 ut(x∣z)u_t(x\mid z) 区分:那里的条件是一个数据点 zz,这里是一个提示 yy
pt(y∣x)p_t(y\mid x)含噪分类器:给定时刻 tt 的带噪样本 xt=xx_t = x,它的提示是 yy 的概率
btb_t换算公式里得分的系数 α˙tβt2αt−β˙tβt\frac{\dot\alpha_t\beta_t^2}{\alpha_t} - \dot\beta_t\beta_t(CondOT:1−tt\frac{1-t}{t},第 3 讲 §2.1)
ww引导强度(guidance scale);w=1w = 1 是不引导的条件生成
qwq_w倾斜分布 ∝p(x∣y)wp(x)1−w\propto p(x\mid y)^w p(x)^{1-w}

0.5 本讲的玩具数据:带标签的六峰圆环

条件生成与分类器引导

(最左:六个峰排成半径 4 的圆,标准差 0.9,三种颜色是三个类别,相邻的峰属于不同类别。中间两张:含噪分类器 pt(y=0∣x)p_t(y = 0\mid x)(背景)和它的梯度方向(箭头)。最右:分类器引导的样本。)

类别 0 = 0° 和 180° 的两个峰,类别 1 = 60° 和 240°,类别 2 = 120° 和 300°。六个峰的权重是 0.22、0.12、0.20、0.13、0.18、0.15,所以 p(y)=(0.35,0.30,0.35)p(y) = (0.35, 0.30, 0.35),类别 0 内两个峰的比例是 0.63 : 0.37。这样设计是为了:

  • 相邻的峰相距约 4.4 个标准差,类别之间有一片”说不清属于谁”的区域,引导”把样本推离别的类别”的效果看得出来;
  • 同一类别的两个峰在圆的两侧,可以观察引导会不会改变类内的比例(多样性的一种)。

它仍然是高斯混合,所以 ut(x∣y)u_t(x\mid y)、ut(x)u_t(x)、pt(y∣x)p_t(y\mid x) 都有闭式解(guidance_lib.GuidanceOracle),学到的东西可以和”真相”逐点比较。


1. 条件生成 · Conditional generation

1.1 从”随便画一张”到”画一只猫”

到第 3 讲为止,我们的模型只会从 pdatap_{\text{data}} 里随便采一个样本。真正有用的生成模型要能按提示生成:给一个提示 yy(“一只戴帽子的猫”),从条件分布 pdata(⋅∣y)p_{\text{data}}(\cdot\mid y) 中采样。第 1 讲 §1.6 已经把这件事写成了”条件生成 = 从 pdata(⋅∣y)p_{\text{data}}(\cdot\mid y) 采样”。

原课讲义把这叫作引导(guidance)。名字的来历是:提示”引导”着生成过程走向它描述的那类样本。

1.2 引导向量场,以及最直接的训练方法

对每个固定的 yy,pdata(⋅∣y)p_{\text{data}}(\cdot\mid y) 就是一个普通的数据分布,第 2 讲的一切都可以照搬:

  • 条件概率路径 pt(⋅∣z)p_t(\cdot\mid z) 不变(它只依赖于数据点 zz,不依赖于 yy);
  • 边缘路径变成 pt(x∣y)=∫pt(x∣z)pdata(z∣y)dzp_t(x\mid y) = \int p_t(x\mid z)p_{\text{data}}(z\mid y)dz;
  • 它的边缘向量场就是引导向量场 ut(x∣y)=E[ut(x∣z)∣xt=x,y]u_t(x\mid y) = \mathbb{E}[u_t(x\mid z)\mid x_t = x, y]。

训练时把 yy 作为网络的额外输入,对 (z,y)(z, y) 对做条件流匹配:

L(θ)=E(z,y)∼pdata, t, ϵ∥utθ(xt∣y)−ut(xt∣z)∥2,xt=αtz+βtϵ.\mathcal{L}(\theta) = \mathbb{E}_{(z, y)\sim p_{\text{data}},\ t,\ \epsilon}\big\lVert u_t^\theta(x_t\mid y) - u_t(x_t\mid z)\big\rVert^2,\qquad x_t = \alpha_t z + \beta_t\epsilon.

注意回归目标 ut(xt∣z)u_t(x_t\mid z) 只依赖于 zz。网络看到 (xt,y)(x_t, y),学到的是目标在给定 (xt,y)(x_t, y) 时的条件期望(P1 §4.2),正好是 ut(x∣y)u_t(x\mid y)。原课讲义把这种做法叫作 vanilla guidance(“普通的引导”)。

01 号脚本第 1 部分用闭式的 ut(x∣y)u_t(x\mid y) 采样(欧拉 200 步),与真实的 p(x∣y)p(x\mid y) 比较:

准确率平均 p(y∣x)p(y\mid x)p(y∣x)>0.99p(y\mid x) > 0.99平均半径类内比例峰内散度能量距离
y=0y = 0:真实97.4%0.96178.0%4.100.621.00−0.002
y=0y = 0:生成97.7%0.96276.7%4.050.651.000.004
y=1y = 1:真实97.0%0.95775.9%4.090.401.00−0.001
y=1y = 1:生成96.6%0.95273.8%4.090.411.02−0.002
y=2y = 2:真实97.6%0.96076.7%4.100.561.000.001
y=2y = 2:生成97.8%0.96477.7%4.090.581.00−0.002

(“准确率”= 贝叶斯最优分类器 arg⁡max⁡y′p(y′∣x)\arg\max_{y'}p(y'\mid x) 判为 yy 的比例;“类内比例”= 落在该类第一个峰附近的比例。)

条件向量场给出的就是 p(x∣y)p(x\mid y):每一项指标都和真实样本一致。

1.3 为什么这样还不够

注意表里的”准确率”不是 100%。类别之间本来就有重叠,真实样本里也有 2–3% 被贝叶斯最优分类器判给别的类,只有约 77% 的样本”非常确定”(p(y∣x)>0.99p(y\mid x) > 0.99)。p(x∣y)p(x\mid y) 本身就包含”不太像 yy“的样本。

原课讲义指出,在图像上也是这样:用 vanilla guidance 训练出来的模型,生成的图像常常和提示对不上。原因有两个:一是数据本身就”嘈杂”(网上的图文对里,文字常常只描述了图像的一部分);二是网络学得不完美,条件信号 yy 对输出的影响被低估了。人们想要的其实是”比真实数据更像 yy“的样本。这就需要某种办法放大提示的作用。

📌 代码 01(第 1 部分):python3 01_conditional_and_bayes.py。


2. 分类器引导 · Classifier guidance

2.1 贝叶斯公式:条件得分 = 无条件得分 + 分类器的梯度

对时刻 tt 的边缘路径用贝叶斯公式:pt(x∣y)=pt(x) pt(y∣x)p(y)p_t(x\mid y) = \frac{p_t(x)\,p_t(y\mid x)}{p(y)}。取对数、对 xx 求梯度(p(y)p(y) 与 xx 无关,消失了):

 ∇log⁡pt(x∣y)=∇log⁡pt(x)+∇log⁡pt(y∣x) \boxed{\ \nabla\log p_t(x\mid y) = \nabla\log p_t(x) + \nabla\log p_t(y\mid x)\ }

其中 pt(y∣x)p_t(y\mid x) 是一个含噪分类器:给它一个时刻 tt 的带噪样本 xtx_t,它判断这个样本的提示是什么。

再用第 3 讲的换算公式 ut(x)=α˙tαtx+bt∇log⁡pt(x)u_t(x) = \frac{\dot\alpha_t}{\alpha_t}x + b_t\nabla\log p_t(x)(条件版本的 xx 系数相同),把得分换成向量场:

 ut(x∣y)=ut(x)+bt ∇log⁡pt(y∣x) \boxed{\ u_t(x\mid y) = u_t(x) + b_t\,\nabla\log p_t(y\mid x)\ }

含义:引导向量场 = 无条件向量场 + 一个”把粒子推向 yy 类”的修正,修正的方向是含噪分类器的梯度,大小由换算系数 btb_t 决定。

01 号脚本第 2 部分用 autograd 对闭式的 log⁡pt(y∣x)\log p_t(y\mid x) 求导(一个独立的算法),在 t=0.2,0.5,0.8t = 0.2, 0.5, 0.8 核对两个等式:最大差都在 10−1410^{-14} 量级。

上一页图的中间两张画出了 pt(y=0∣x)p_t(y = 0\mid x) 和它的梯度方向。值得注意的是它的形状:类别 0 的后验在一个”蝴蝶结”形的楔形区域里接近 1(沿着 0° 和 180° 方向向外延伸),而不是只在两个峰附近。离圆心越远,离相邻的别类峰相对越远,属于类别 0 的把握越大。§2.2 会看到这个形状的后果。

2.2 放大分类器项

既然条件向量场 = 无条件 + 分类器项,一个自然的想法是把分类器项放大(Dhariwal & Nichol 2021):

u~t(x∣y)=ut(x)+w bt ∇log⁡pt(y∣x),w>1.\tilde u_t(x\mid y) = u_t(x) + w\,b_t\,\nabla\log p_t(y\mid x),\qquad w > 1.

在得分的语言里,这相当于把 pt(x) pt(y∣x)p_t(x)\,p_t(y\mid x) 换成 pt(x) pt(y∣x)wp_t(x)\,p_t(y\mid x)^w:分类器”说话的分量”更重了。原课讲义强调,这已经不再是某个数据分布的向量场,它是一个启发式。

01 号脚本第 3 部分(类别 0,欧拉 200 步):

引导强度准确率p(y∣x)>0.99p(y\mid x) > 0.99平均半径类内比例峰内散度与 p(x∣y)p(x\mid y) 的能量距离
w=0w = 0(无条件)34.3%26.6%4.090.482.710.676
w=1w = 1(= 条件场)97.6%77.3%4.080.611.00−0.001
w=2w = 2100%99.8%4.470.690.820.147
w=4w = 4100%100%5.080.771.040.871
w=8w = 8100%100%5.980.861.642.700

三个现象:

  1. 提示遵循度迅速饱和:w=2w = 2 时 99.8% 的样本”非常确定”是类别 0。代价是样本不再服从 p(x∣y)p(x\mid y)。
  2. 样本被推向”最不像别的类”的地方:平均半径从 4.1 增大到 6.0。这正是蝴蝶结形后验的后果:引导沿着 ∇log⁡pt(y∣x)\nabla\log p_t(y\mid x) 走,而它指向楔形区域的外侧。w=2w = 2 时峰内散度 0.82(峰被压窄、样本更”典型”);ww 再大时整团样本被推离峰中心,散度又变大。
  3. 类内的多样性也被改变:类别 0 的两个峰本应是 0.63 : 0.37,w=8w = 8 时变成 0.86 : 0.14。第一个峰的邻居权重较小(0.12、0.15),第二个峰的邻居较大(0.20、0.18),所以第一个峰附近 p(y=0∣x)p(y = 0\mid x) 更高,引导就更偏爱它。在图像上,这相当于”猫”这个提示只生成某一种最典型的猫。

2.3 分类器必须”认识噪声”

公式里的分类器是 pt(y∣x)p_t(y\mid x):它的输入是时刻 tt 的带噪样本。如果偷懒,拿一个只在干净数据上训练的分类器 p(y∣x)p(y\mid x) 在所有时刻使用,会怎样?01 号脚本第 3 部分的最后两行(btb_t 在 t<0.05t < 0.05 时按 t=0.05t = 0.05 计算以免除以 0):

准确率平均半径类内比例峰内散度能量距离
w=1w = 1,干净分类器100%4.780.530.690.484
w=4w = 4,干净分类器100%5.390.531.110.934

w=1w = 1 时也不再给出 p(x∣y)p(x\mid y)(能量距离 0.48)。tt 较小时粒子还是一团噪声,干净分类器对这种输入给出的梯度和真正的 ∇log⁡pt(y∣x)\nabla\log p_t(y\mid x) 相去甚远。这就是 Dhariwal & Nichol(2021)要专门在带噪图像上训练分类器的原因。

2.4 分类器引导的麻烦

分类器引导在 2021 年第一次让扩散模型在 ImageNet 上超过了 GAN,但它有明显的缺点:

  • 要另外训练一个分类器,而且必须在所有噪声水平上训练(现成的图像分类器不能用);
  • 对文生图来说,“分类器”要能判断任意一段文字和一张带噪图像是否匹配,这本身就是一个很难的模型;
  • 沿分类器梯度走,有点像对分类器做”对抗攻击”:网络的梯度可能指向”让分类器高兴、但人看来没有意义”的方向。

能不能不要分类器?

📌 代码 01(第 2、3 部分)。


3. 无分类器引导 · Classifier-free guidance

3.1 推导:隐式的分类器

关键的一步只是把 §2.1 的等式反过来用:

bt∇log⁡pt(y∣x)=ut(x∣y)−ut(x).b_t\nabla\log p_t(y\mid x) = u_t(x\mid y) - u_t(x).

分类器的梯度本来就藏在条件场和无条件场之差里。代入分类器引导:

u~t(x∣y)=ut(x)+w(ut(x∣y)−ut(x))= (1−w) ut(x∣∅)+w ut(x∣y) \tilde u_t(x\mid y) = u_t(x) + w\big(u_t(x\mid y) - u_t(x)\big) = \boxed{\ (1 - w)\,u_t(x\mid\varnothing) + w\,u_t(x\mid y)\ }

这就是无分类器引导(classifier-free guidance, CFG;Ho & Salimans 2021)。只需要条件场 ut(x∣y)u_t(x\mid y) 和无条件场 ut(x∣∅)=ut(x)u_t(x\mid\varnothing) = u_t(x),不需要任何分类器。直觉:从无条件场出发,沿着”条件减去无条件”的方向多走 ww 倍。w=1w = 1 是普通的条件生成,w=0w = 0 是无条件生成,w>1w > 1 是”外推”。

一个网络学两个场。CFG 不需要训练两个网络:把”空提示” ∅\varnothing 当作一个额外的类别,训练时以概率 puncondp_{\text{uncond}} 把标签换成 ∅\varnothing。被换掉标签的样本,网络能看到的只有 (xt,t)(x_t, t),它学到的最优预测就是对所有 yy 平均的无条件场(P1 §4.2)。这就是原课讲义的 Algorithm 5:

Algorithm 5  无分类器引导的训练(高斯路径)
输入:带提示的数据集 {(z, y)},网络 u^θ,丢弃概率 p_uncond
for 每个小批量:
    抽 (z, y);以概率 p_uncond 令 y ← ∅
    抽 t ~ Unif[0, 1],ε ~ N(0, I);x ← α_t z + β_t ε
    L(θ) ← ‖u^θ_t(x | y) − (α̇_t z + β̇_t ε)‖²
    θ ← 梯度更新(L(θ))
采样时:ũ_t(x) = (1 − w) u^θ_t(x | ∅) + w u^θ_t(x | y),用欧拉法从 t = 0 模拟到 1

对应的 Python(guidance_lib.py,节选):

drop = torch.rand(batch, generator=g) < p_uncond
y = torch.where(drop, torch.full_like(y, model.n_classes), y)   # 第 C 个"类别"就是 ∅
...
# 采样时把条件和无条件拼成一个批,一次前向算完
out = model(torch.cat([x, x]), t, torch.cat([y, null]))
cond, uncond = out[:n], out[n:]
return uncond + w * (cond - uncond)

最后两行也说明了 CFG 的计算代价:每一步要算两次前向(条件和无条件),实际实现里把它们拼成一个两倍大小的批。

CFG 不依赖于参数化。如果网络预测的是噪声或得分,把同样的组合用在 ϵ^\hat\epsilon 或 ss 上:ϵ~=(1−w)ϵ^(x∣∅)+w ϵ^(x∣y)\tilde\epsilon = (1 - w)\hat\epsilon(x\mid\varnothing) + w\,\hat\epsilon(x\mid y)。因为第 3 讲的换算公式对预测值是仿射的(u=α˙αx+btsu = \frac{\dot\alpha}{\alpha}x + b_t s,条件和无条件用的是同一个 xx 和同一组系数),在哪种参数化里做 CFG 都得到同一个向量场(练习 2)。原课讲义在扩散模型的部分就是这样写的。

3.2 CFG 采样的到底是什么分布?

在得分的语言里,CFG 的场对应

∇log⁡[pt(x)1−w pt(x∣y)w],\nabla\log\big[p_t(x)^{1-w}\,p_t(x\mid y)^w\big],

每个时刻都是一个”倾斜”过的分布的得分。于是很容易以为:CFG 采样到的是倾斜分布

qw(x)∝p(x∣y)w p(x)1−w∝p(x) p(y∣x)w.q_w(x) \propto p(x\mid y)^w\,p(x)^{1-w} \propto p(x)\,p(y\mid x)^w.

在二维里,qwq_w 可以在网格上精确采样(guidance_lib.tilted_sample)。02 号脚本先扫描 ww(第 1 部分,闭式的 CFG 场;结果和 §2.2 的分类器引导一致,因为两者在闭式的场下完全相同),再把 CFG 的样本和 qwq_w 的精确样本放在一起比(第 2 部分):

ww能量距离 CFG vs qwq_w地板(qwq_w vs qwq_w)半径 CFG / qwq_w类内比例 CFG / qwq_w峰内散度 CFG / qwq_wp(y∣x)>0.99p(y\mid x) > 0.99 CFG / qwq_w
10.002+0.0104.08 / 4.130.63 / 0.641.00 / 0.9877% / 79%
1.50.043−0.0024.29 / 4.110.66 / 0.630.84 / 0.9797% / 80%
20.155+0.0014.47 / 4.130.69 / 0.630.82 / 0.9599.7% / 81%
30.519−0.0024.80 / 4.170.75 / 0.620.90 / 0.94100% / 83%
51.359−0.0025.34 / 4.150.80 / 0.621.20 / 0.93100% / 83%
82.696+0.0005.98 / 4.160.87 / 0.641.64 / 0.90100% / 85%

(地板本身有约 ±0.01\pm0.01 的波动:类别 0 的两个峰在圆的两侧,峰的比例的抽样误差对能量距离影响很大。)

CFG vs 倾斜分布

CFG 不是在 qwq_w 里采样,而且差得很远。qwq_w 几乎不随 ww 变化:qw∝p(x)p(y∣x)wq_w\propto p(x)p(y\mid x)^w,而类别 0 的大部分质量所在之处 p(y∣x)p(y\mid x) 本来就接近 1,倾斜只削掉了类别之间重叠的那一小片。CFG 却把每个峰压成沿径向的一根细条,推出去很远,还改变了类内比例。CFG 比”倾斜”激进得多。

一维的例子更干净(第 3 部分):p(x∣0)=N(−1.5,1)p(x\mid 0) = \mathcal{N}(-1.5, 1),p(x∣1)=N(1.5,1)p(x\mid 1) = \mathcal{N}(1.5, 1),各占一半,对 y=0y = 0 做 CFG(4 万个粒子);qwq_w 的均值和标准差在细网格上数值积分:

wwCFG 的均值qwq_w 的均值CFG 的标准差qwq_w 的标准差
1−1.501−1.5000.9951.000
2−2.149−1.6640.7190.889
3−2.553−1.7380.6280.848
5−3.136−1.8240.5480.807

w=5w = 5 时两者的均值之差(1.3)比 qwq_w 的标准差还大。

为什么? CFG 在每个时刻 tt 用的是 pt(x)1−wpt(x∣y)wp_t(x)^{1-w}p_t(x\mid y)^w 的得分。但”先倾斜、再加噪”和”先加噪、再倾斜”不是一回事:对 qwq_w 沿高斯路径加噪,得到的分布族不等于每个时刻的 ptp_t 各自倾斜。CFG 沿着一族”每一刻都是倾斜分布”的快照走,而这族快照并不是任何一条概率路径——它们之间不满足连续性方程,终点也就不是 qwq_w。原课讲义说 CFG 是一个启发式,正是这个意思。Bradley & Nakkiran(2024)、Chidambaram et al.(2024)等工作从理论上分析了 CFG 到底采样什么,结论都是”不是 qwq_w“,而且 CFG 倾向于把样本推向分布支撑的”边缘”——和本节的实验一致。

3.3 训练 CFG:丢弃标签的概率

03 号脚本按 Algorithm 5 训练四个条件 MLP(4×128,5000 步),只改变 puncondp_{\text{uncond}},和闭式的场比较:

puncondp_{\text{uncond}}条件场相对误差无条件场相对误差w=1w = 1 vs p(x∣y)p(x\mid y)w=3w = 3 vs 闭式 CFGw=3w = 3:半径w=3w = 3:类内比例
00.33%11.4%0.00171.8437.510.72
0.10.36%0.45%0.00230.05884.890.73
0.30.38%0.41%0.00350.04304.780.72
0.50.41%0.41%0.00390.05254.760.72

(闭式 CFG w=3w = 3:半径 4.81、类内比例 0.74;两批闭式 CFG 样本之间的能量距离 −0.0016。)

  • 必须丢弃标签:puncond=0p_{\text{uncond}} = 0 时网络从没见过 ∅\varnothing,它对 ∅\varnothing 的输出只是”碰巧”的(无条件场误差 11%),CFG 完全走样:样本被推到半径 7.5 的地方。
  • 丢弃概率不敏感:0.1、0.3、0.5 差别不大。条件场的误差随丢弃概率略增(条件样本少了),无条件场略减。原课 Lab 和很多论文取 0.1–0.2:无条件场只是”参照”,不需要很多样本。
  • CFG 放大网络的误差:w=1w = 1 时网络的样本和 p(x∣y)p(x\mid y) 只差 0.002–0.004,w=3w = 3 时和闭式 CFG 却差 0.04–0.06。CFG 场的误差是 (1−w)δ∅+w δy(1 - w)\delta_\varnothing + w\,\delta_y;如果两个误差彼此独立,w=3w = 3 时标准差放大约 4+9≈3.6\sqrt{4 + 9}\approx 3.6 倍。CFG 的样本又挤在很窄的区域里,位置上的小偏差在能量距离里很显眼。不过半径、类内比例这些宏观性质都学对了。

📌 代码 02、03:python3 02_cfg.py(约 4 秒);python3 03_train_cfg.py(约 35 秒;--quick 是冒烟测试)。


4. 图像上的 CFG · CFG on images

4.1 像素数字

原课 Lab 3 在 MNIST 上训练带 CFG 的流模型。本讲义不下载数据,改用代码画出来的 12×12”像素数字”(pixel_digits.py):按七段数码管的笔画画出 0–9,每张图的大小、位置、倾斜、笔画粗细都随机;另外每一段有 4% 的概率被画错(该有的没画、不该有的画了),模拟潦草的手写——约 25% 的图至少错一段,其中一部分本身就说不清是哪个数字。

评估用一个在真实数字上训练的小分类器(在新图上准确率 89.3%,上限受”画错”限制):

  • 分类器判对的比例:提示遵循度;
  • 风格多样性:同一个数字的”墨水量、重心横坐标、重心纵坐标”的标准差,除以真实图像的(1 = 一样多样);
  • Fréchet 距离:在分类器的 64 维特征上,生成图像与真实图像的 Fréchet 距离(FID 的玩具版,Heusel et al. 2017);
  • 过饱和像素:∣|像素∣>1.25| > 1.25 的比例(真实像素都在 [−1,1][-1, 1] 内)。

4.2 结果

04 号脚本训练一个条件 MLP(144 + 1 + 11 → 512 → 512 → 512 → 144,约 68 万参数,3000 步、批大小 256,puncond=0.1p_{\text{uncond}} = 0.1,约 18 秒),每个 ww 生成 1000 张(欧拉 50 步,同一批初始噪声):

引导强度分类器判对平均置信度风格多样性Fréchet 距离过饱和像素
w=0w = 0(无条件)10.3%0.1040.9614.564.9%
w=1w = 1(条件)90.2%0.7800.782.444.9%
w=1.5w = 1.597.9%0.9080.734.376.0%
w=2w = 299.2%0.9520.7013.267.5%
w=3w = 399.9%0.9790.6740.8611.1%
w=5w = 5100%0.9900.64108.4017.3%
真实图像89.4%0.8381.080.35(两批真实之间)0.0%

像素数字上的 CFG

(每张小图里一行是一个数字 0–9。w=0w = 0:无条件生成,数字之间的”混合体”;w=1w = 1:大多可辨认,但有些模糊、有些画错;w=2w = 2:干净整齐;w=5w = 5:对比度过高,背景出现亮斑。)

和二维实验完全一致:

  1. w=1w = 1 忠实地复现了数据:判对的比例和真实数据差不多(90.2% vs 89.4%),Fréchet 距离最小。“有一成图像说不清是哪个数字”是数据分布的一部分,条件模型把它也学来了。
  2. ww 增大,提示遵循度超过真实数据(99–100%),代价是风格多样性下降(大小、位置、粗细越来越统一)、离真实分布越来越远(Fréchet 距离从 2.4 涨到 108)、过饱和越来越严重。
  3. 训练 3000 步的小网络本身就比真实数据单调一些(w=1w = 1 时风格多样性 0.78 而不是 1):学到的分布偏向”典型”的样本,CFG 在此基础上进一步牺牲多样性。

一个依赖于数据的结论。写这一节时,第一版数据没有”画错”的笔画。那时条件模型(w=1w = 1)的判对率已经是 99.9%,CFG 在提示遵循度上毫无用处,只让 Fréchet 距离变差(w=1,2,5w = 1, 2, 5:12.3、26.0、109;练习 6)。CFG 的价值在于数据里的提示本身就有噪声、条件信号偏弱的时候——真实的图文数据正是这样。

4.3 实践中的 ww

ww 是”提示遵循度 vs 多样性 / 真实感”的旋钮。实践中常用几倍的量级(文生图模型一般在 3–8 之间),按应用调。围绕它有不少改进,这里只点名:

  • 负面提示(negative prompt):把 ut(x∣∅)u_t(x\mid\varnothing) 换成 ut(x∣yneg)u_t(x\mid y_{\text{neg}}),既推向 yy、又推离 ynegy_{\text{neg}}(练习 5)。
  • 过饱和的处理:Imagen(Saharia et al. 2022)的”动态阈值”在每一步把预测的干净图像裁剪回合理范围,缓解大 ww 下的过饱和。
  • 只在一段时间里引导:Kynkäänniemi et al.(2024)发现只在中间的一段噪声水平上用 CFG,能在保持遵循度的同时减少多样性损失。本讲的二维例子里,引导的效果几乎全部来自前半段(练习 4)。

📌 代码 04:python3 04_pixel_digits_cfg.py(约 25 秒;--quick 是冒烟测试)。


5. 全景 · The big picture

引导在今天的大模型里无处不在。原课 slides 的说法是:几乎所有生成的图像和视频都用了 CFG。Stable Diffusion 3、Meta Movie Gen 等模型的训练都按 Algorithm 5 随机丢弃提示(文本嵌入被替换成”空文本”的嵌入),采样时用 CFG。

方法需要什么场代价
vanilla guidance条件网络 utθ(x∣y)u_t^\theta(x\mid y)ut(x∣y)u_t(x\mid y)提示遵循度受数据限制
分类器引导无条件网络 + 含噪分类器ut+w bt∇log⁡pt(y∣x)u_t + w\,b_t\nabla\log p_t(y\mid x)另训分类器;梯度可能”对抗”
无分类器引导一个带 ∅\varnothing 的条件网络(1−w)ut(x∣∅)+w ut(x∣y)(1-w)u_t(x\mid\varnothing) + w\,u_t(x\mid y)每步两次前向;多样性下降;放大误差

本讲的提示是 3 个或 10 个类别,用独热编码喂给网络。真实的提示是一段文字:先用文本编码器(CLIP、T5 等)变成一串向量,再通过交叉注意力等方式注入网络。网络还要处理几百万维的图像。这些是第 5 讲的内容。


6. 小结 · Summary

  1. 条件生成:对 (z,y)(z, y) 对做条件流匹配,网络以 yy 为额外输入,学到引导向量场 ut(x∣y)u_t(x\mid y),采样得到 p(x∣y)p(x\mid y)(vanilla guidance)。p(x∣y)p(x\mid y) 本身就包含不太像 yy 的样本,提示遵循度往往不够。
  2. 贝叶斯公式:∇log⁡pt(x∣y)=∇log⁡pt(x)+∇log⁡pt(y∣x)\nabla\log p_t(x\mid y) = \nabla\log p_t(x) + \nabla\log p_t(y\mid x),换成向量场 ut(x∣y)=ut(x)+bt∇log⁡pt(y∣x)u_t(x\mid y) = u_t(x) + b_t\nabla\log p_t(y\mid x)。
  3. 分类器引导:把分类器项放大 ww 倍。提示遵循度迅速饱和,样本被推向”最不像别的类”的地方,类内比例被扭曲。分类器必须在带噪数据上训练。
  4. 无分类器引导:bt∇log⁡pt(y∣x)=ut(x∣y)−ut(x)b_t\nabla\log p_t(y\mid x) = u_t(x\mid y) - u_t(x),所以 u~=(1−w)ut(x∣∅)+w ut(x∣y)\tilde u = (1-w)u_t(x\mid\varnothing) + w\,u_t(x\mid y)。一个网络、训练时以概率 puncondp_{\text{uncond}} 丢弃标签(Algorithm 5);不依赖于参数化。
  5. CFG 是启发式:它不采样倾斜分布 qw∝p(x∣y)wp(x)1−wq_w\propto p(x\mid y)^w p(x)^{1-w},而且比 qwq_w 激进得多;它会放大网络的误差。
  6. 图像上:ww 增大,提示遵循度超过真实数据,多样性下降、离真实分布越来越远、过饱和;CFG 的价值在于数据里条件信号偏弱的时候。

7. 常见误区 · Common pitfalls

  1. “条件生成模型学到的是 ut(x∣z)u_t(x\mid z)。” zz 是数据点,yy 是提示,两者完全不同。ut(x∣z)u_t(x\mid z) 有公式、不用学;网络学的是对 zz 平均后的 ut(x∣y)u_t(x\mid y)(§1.2)。
  2. ”w=1w = 1 就是 CFG 的默认值。” w=1w = 1 是不引导的条件生成;引导要 w>1w > 1。(有的代码库把 ww 定义为 u∅+w(uy−u∅)u_{\varnothing} + w(u_y - u_\varnothing),也有的定义为 uy+w(uy−u∅)u_y + w(u_y - u_\varnothing),后者的 w=0w = 0 才是不引导,读代码时要看清楚。)
  3. “CFG 采样的是 p(x∣y)wp(x)1−wp(x\mid y)^w p(x)^{1-w}。” 不是,而且差得很远(§3.2)。
  4. “训练 CFG 要两个网络。” 一个网络,训练时随机丢弃标签(§3.1)。
  5. “不丢弃标签也能做 CFG。” 网络从没见过 ∅\varnothing,无条件场是错的,CFG 完全走样(§3.3)。
  6. “现成的图像分类器可以拿来做分类器引导。” 必须是在所有噪声水平上训练的含噪分类器(§2.3)。
  7. ”ww 越大越好。” 遵循度很快饱和,之后只剩多样性下降和过饱和(§4.2)。
  8. “CFG 的效果在每个时刻都一样重要。” 至少在本讲的例子里,效果几乎全部来自噪声较大的前半段(练习 4)。

8. 练习 · Exercises

练习 1(分类器引导的得分)。证明分类器引导 u~t=ut+w bt∇log⁡pt(y∣x)\tilde u_t = u_t + w\,b_t\nabla\log p_t(y\mid x) 对应的”得分”是 ∇log⁡[pt(x) pt(y∣x)w]\nabla\log\big[p_t(x)\,p_t(y\mid x)^w\big],并说明 w=1w = 1 时为什么回到 pt(x∣y)p_t(x\mid y)。

参考答案

由换算公式,向量场 α˙αx+bts\frac{\dot\alpha}{\alpha}x + b_t s 对应得分 ss。u~t=α˙αx+bt[∇log⁡pt(x)+w∇log⁡pt(y∣x)]\tilde u_t = \frac{\dot\alpha}{\alpha}x + b_t[\nabla\log p_t(x) + w\nabla\log p_t(y\mid x)],所以对应的得分是 ∇log⁡pt(x)+w∇log⁡pt(y∣x)=∇log⁡[pt(x)pt(y∣x)w]\nabla\log p_t(x) + w\nabla\log p_t(y\mid x) = \nabla\log[p_t(x)p_t(y\mid x)^w]。w=1w = 1 时由贝叶斯公式 pt(x)pt(y∣x)=p(y) pt(x∣y)p_t(x)p_t(y\mid x) = p(y)\,p_t(x\mid y),常数 p(y)p(y) 不影响梯度。

练习 2(CFG 不依赖于参数化)。设网络预测噪声 ϵ^\hat\epsilon,换算 u=Atx+Btϵ^u = A_t x + B_t\hat\epsilon(第 3 讲 §2)。证明对 ϵ^\hat\epsilon 做 CFG 与对 uu 做 CFG 得到同一个向量场。

参考答案

(1−w)u∅+wuy=(1−w)(Atx+Btϵ^∅)+w(Atx+Btϵ^y)=Atx+Bt[(1−w)ϵ^∅+wϵ^y](1-w)u_\varnothing + w u_y = (1-w)(A_t x + B_t\hat\epsilon_\varnothing) + w(A_t x + B_t\hat\epsilon_y) = A_t x + B_t[(1-w)\hat\epsilon_\varnothing + w\hat\epsilon_y],正是用 ϵ~=(1−w)ϵ^∅+wϵ^y\tilde\epsilon = (1-w)\hat\epsilon_\varnothing + w\hat\epsilon_y 换算出的速度。关键是 (1−w)+w=1(1-w) + w = 1,AtxA_t x 那一项没有被放大。

练习 3(高斯的例子:CFG vs 倾斜分布)。设 p(x)=N(0,4)p(x) = \mathcal{N}(0, 4)、p(x∣y)=N(1,1)p(x\mid y) = \mathcal{N}(1, 1)(一维),CondOT 路径。(a) 求 q3∝p(x∣y)3p(x)−2q_3\propto p(x\mid y)^3 p(x)^{-2} 的均值和方差。(b) CFG 的场对 xx 是线性的,所以终点仍是高斯;证明 CFG 终点的方差是 41−w⋅1w4^{1-w}\cdot1^{w},并数值求出 w=3w = 3 时的均值。

参考答案((b) 的均值来自作者的数值积分)

(a) 精度相加:3⋅1−2⋅14=2.53\cdot1 - 2\cdot\frac14 = 2.5,方差 0.4;均值 =(3⋅1⋅1+(−2)⋅14⋅0)/2.5=1.2= (3\cdot1\cdot1 + (-2)\cdot\frac14\cdot0)/2.5 = 1.2。 (b) 对数据 N(m,s2)\mathcal{N}(m, s^2),CondOT 的边缘场是 ut(x)=m+ct(x−tm)u_t(x) = m + c_t(x - tm),ct=v˙t2vtc_t = \frac{\dot v_t}{2v_t},vt=t2s2+(1−t)2v_t = t^2s^2 + (1-t)^2。CFG 场的 xx 系数是 (1−w)v˙t(1)2vt(1)+wv˙t(2)2vt(2)(1-w)\frac{\dot v^{(1)}_t}{2v^{(1)}_t} + w\frac{\dot v^{(2)}_t}{2v^{(2)}_t},方差满足 dVdt=2×(系数)×V\frac{dV}{dt} = 2\times(\text{系数})\times V,积分得 log⁡V1−log⁡V0=(1−w)log⁡v1(1)v0(1)+wlog⁡v1(2)v0(2)=(1−w)log⁡4+wlog⁡1\log V_1 - \log V_0 = (1-w)\log\frac{v^{(1)}_1}{v^{(1)}_0} + w\log\frac{v^{(2)}_1}{v^{(2)}_0} = (1-w)\log4 + w\log1,V0=1V_0 = 1,所以 V1=41−wV_1 = 4^{1-w}:w=3w = 3 时是 0.0625,远小于 q3q_3 的 0.4。数值积分(20 万步)给出 w=3w = 3 时均值 1.50(q3q_3 是 1.2)。CFG 把方差按”几何平均”组合(σ∅2(1−w)σy2w\sigma_\varnothing^{2(1-w)}\sigma_y^{2w}),倾斜分布按”精度相加”组合,两者在 w≠1w\neq1 时不同。

练习 4(编程:只在一段时间里引导)。在 02_cfg.py 里,让 CFG(w=3w = 3)只在 t∈[tlo,thi)t\in[t_{\text{lo}}, t_{\text{hi}}) 内生效,其余时间用条件场 ut(x∣y)u_t(x\mid y)。比较 [0,1)[0, 1)、[0,0.5)[0, 0.5)、[0.5,1)[0.5, 1)、[0.2,0.8)[0.2, 0.8)。

参考答案(作者机器上的结果,类别 0,欧拉 200 步)
引导区间p(y∣x)>0.99p(y\mid x) > 0.99平均半径类内比例峰内散度与 p(x∣y)p(x\mid y) 的能量距离
[0,1)[0, 1)(全程)100%4.800.750.900.531
[0,0.5)[0, 0.5)99.9%4.790.750.900.528
[0.5,1)[0.5, 1)91.1%4.110.630.880.001
[0.2,0.8)[0.2, 0.8)100%4.510.650.750.125

CFG 的效果几乎全部来自前半段(噪声大、“决定去哪个峰”的阶段):只在前半段引导和全程引导几乎一样;只在后半段引导,分布几乎不变(能量距离 0.001),但”非常确定”的比例从 77% 升到 91%——它只是把样本往峰的”安全”一侧挪了一点。中间一段的折中:遵循度 100%,类内比例几乎没被扭曲(0.65)。这和 Kynkäänniemi et al.(2024)“在高噪声段关掉引导可以保住多样性”的发现方向一致。

练习 5(思考:负面提示)。把 CFG 里的 ut(x∣∅)u_t(x\mid\varnothing) 换成 ut(x∣yneg)u_t(x\mid y_{\text{neg}})。用贝叶斯公式解释这个场在做什么。

参考答案

u~=ut(x∣yneg)+w[ut(x∣y)−ut(x∣yneg)]\tilde u = u_t(x\mid y_{\text{neg}}) + w[u_t(x\mid y) - u_t(x\mid y_{\text{neg}})],差项 =bt[∇log⁡pt(y∣x)−∇log⁡pt(yneg∣x)]=bt∇log⁡pt(y∣x)pt(yneg∣x)= b_t[\nabla\log p_t(y\mid x) - \nabla\log p_t(y_{\text{neg}}\mid x)] = b_t\nabla\log\frac{p_t(y\mid x)}{p_t(y_{\text{neg}}\mid x)}。它推动样本去”更像 yy、更不像 ynegy_{\text{neg}}“的地方:一个”yy 对 ynegy_{\text{neg}}“的对比分类器的梯度。

练习 6(编程:没有画错的数字)。把 pixel_digits.make_digits 的默认 flip 改成 0,重新运行 04_pixel_digits_cfg.py。CFG 还有用吗?

参考答案(作者机器上的结果)

分类器在新图上的准确率 100%。w=0,1,2,5w = 0, 1, 2, 5 时:分类器判对 9.9%、99.9%、100%、100%;Fréchet 距离 51.2、12.3、26.0、109.0;风格多样性 1.265、0.870、0.803、0.765。w=1w = 1 已经几乎全对,CFG 在提示遵循度上没有好处,只让生成的分布离真实数据更远、更单调。数据里的条件信号很强时,CFG 是多余的。


9. 延伸阅读 · Further reading

  • 原课讲义第 5 章和 Lab 3(https://github.com/eje24/iap-diffusion-labs ,2026 分支)。
  • Dhariwal & Nichol, Diffusion Models Beat GANs on Image Synthesis(NeurIPS 2021):分类器引导、含噪分类器。
  • Ho & Salimans, Classifier-Free Diffusion Guidance(NeurIPS 2021 Workshop;arXiv:2207.12598)。
  • Bradley & Nakkiran, Classifier-Free Guidance is a Predictor-Corrector(2024);Chidambaram et al., What does guidance do? A fine-grained analysis in a simple setting(NeurIPS 2024):CFG 到底采样什么。
  • Kynkäänniemi et al., Applying Guidance in a Limited Interval Improves Sample and Distribution Quality in Diffusion Models(NeurIPS 2024)。
  • Saharia et al., Photorealistic Text-to-Image Diffusion Models with Deep Language Understanding(Imagen,NeurIPS 2022):大 ww 与动态阈值。
  • Heusel et al., GANs Trained by a Two Time-Scale Update Rule Converge to a Local Nash Equilibrium(NeurIPS 2017):FID。

10. 下一讲预告 · Next lecture

本讲的网络是一个吃”展平的像素 + 时间 + 独热标签”的 MLP,图像只有 12×12。真实的模型要处理 1024×1024 的彩色图像、一段任意长的文字。第 5 讲要回答:

  1. 时间 tt 和提示 yy 怎样喂给网络?(傅里叶时间嵌入、文本编码器、adaLN、交叉注意力)
  2. 网络长什么样?(U-Net 与 Diffusion Transformer)
  3. 为什么几乎所有大模型都不在像素空间、而在一个 VAE 的潜空间里生成?潜空间要满足什么条件才”好学”?
  4. Stable Diffusion 3、Meta Movie Gen 是怎样把前四讲的东西组装起来的?
← 返回课程目录