条件生成与 Guidance#
本页内容4 个部分
1. 从无条件到有条件生成#
1.1 发展脉络#
2014
cGAN 条件生成起点
Mirza & Osindero 在 GAN 上加入类别标签 ,训练时把 拼到生成器和判别器输入。有条件生成的思路首次出现,但 GAN 训练不稳定、模式崩塌,无法做到"任意文本→图像"。
2020
DDPM 扩散模型登场
Ho et al. 提出 DDPM,训练稳定、生成质量高,但完全是无条件生成 ——给噪声只能生成随机图,无法控制内容。扩散模型的时代开始,但还不实用。
2021 · 上半年
CLIP 文本-图像桥梁
OpenAI 用 4 亿图文对训练对比学习模型,把文本和图像映射到同一个 embedding 空间。这是"文本→图像"生成的关键基础设施——有了 CLIP,才能把文字条件转化为模型能理解的向量。
2021 · 下半年
Classifier Guidance 第一个条件扩散
Dhariwal & Nichol(OpenAI)在扩散模型上加入噪声分类器,用分类器梯度引导采样方向,第一次让扩散模型做到有条件生成并在 ImageNet 上超过 GAN。但需要单独训练分类器,且不能处理文本等连续条件。
2022 · 初
CFG 无需分类器
Ho & Salimans 提出 Classifier-Free Guidance:同一个网络训练时随机丢弃条件,推理时用"有条件预测 − 无条件预测"的差值放大条件效果。不再需要额外分类器,且天然支持文本条件,成为此后所有主流模型的标配。
2022 · 中
Latent Diffusion / Stable Diffusion 1.x 效率突破
Rombach et al.(LMU Munich)把扩散过程从像素空间移入 VAE 的隐空间,计算量压缩约 48 倍。结合 CLIP 文本编码器 + Cross-Attention 条件注入 + CFG,组成了完整的文生图技术栈,并开源。Stable Diffusion 时代正式开始。
2022 · 下 — 2023 · 中
DALL-E 2 · Imagen · SDXL 能力跃升
DALL-E 2(OpenAI)引入 unCLIP,先生成 CLIP 图像 embedding 再解码;Imagen(Google)用大型语言模型 T5-XXL 做文本编码器,效果更好。SDXL 增大 U-Net 并引入双文本编码器和微调流程,生成质量大幅提升。
2023 · 10
DALL-E 3 数据工程突破
OpenAI 用 LLM 为训练图像重写高质量 caption(详细、准确的描述替代短标签),prompt following 能力大幅超越前代。核心洞察:数据质量 > 模型架构——更好的 caption 比更大的模型更有效。深刻影响了后续所有模型的数据工程策略。
2024
SD3 · Flux.1 架构革新
SD3(Stability AI)用 MM-DiT 替换 U-Net,三路文本编码器(CLIP×2 + T5),切换到 Flow Matching。Flux.1(Black Forest Labs,SD 核心团队出走创建,12B 参数)采用单流+双流混合 Transformer,通过 Guidance Distillation 实现单次前向推理(schnell 版本)。U-Net → DiT、DDPM → Flow Matching 两条主线完成切换。
**一条主线读懂演进:**无条件(DDPM)→ 需要外挂分类器(Classifier Guidance)→ 用同一网络隐式做引导(CFG)→ 搬到隐空间省算力(LDM)→ 用 Transformer 替换 U-Net(DiT/SD3)。
1.2 无条件生成 vs 条件生成#
无条件生成建模的是数据的边缘分布 :给模型一段纯高斯噪声,它会随机生成某张图像,你无法控制生成的内容。DDPM、Score-based 模型的原始版本都属于这一类。
条件生成建模的是条件分布 :给模型噪声 加上 一个条件 ,让它生成符合条件的图像。例如"一只坐在沙滩上的猫"——这才是实际产品需要的能力。
1.3 条件 的类型#
| 条件类型 | 示例 | 典型编码方式 |
|---|---|---|
| 类别标签 | ImageNet 1000 类("金毛犬"=207) | one-hot / embedding lookup |
| 文本描述 | "a cat sitting on a beach" | CLIP / T5 文本编码器 |
| 图像 | img2img、风格参考 | CLIP 图像编码器 / VAE 编码器 |
| 语义图 / 边缘图 | ControlNet 输入 | 额外卷积编码器 |
| 深度图 / 姿态 | ControlNet depth/pose | 同上 |
1.4 两个先后发生的问题#
把条件注入去噪过程,要回答两个顺序发生的问题——不是"选哪条路",而是"第一步怎么做,第二步怎么做":
问题一:网络怎么接收条件 c?(架构 / 训练阶段)
这解决的是:怎么让 和 产生差异。Cross-Attention 是主流答案——文本 embedding 通过 K、V 进入网络,图像特征通过 Q 去查询文本,让网络每一层都能读到条件信息。这是网络结构层面的事,训练和推理时都在发生,和"引导"无关。
其他方式:拼接(concat c 到输入通道)、加法(AdaGN/AdaLN 用 c 调制归一化层)。
问题二:推理时怎么让条件影响足够强?(采样阶段)
只有 Cross-Attention,网络只是"看到了"条件,但采样出来的图可能依然模糊、不够贴合 prompt。需要在采样时额外放大有条件预测和无条件预测的差距:
- Classifier Guidance:在噪声预测上叠加外部分类器的梯度
- CFG:,放大两者的差值
这是采样层面的事,不改变网络结构,只在推理时操作网络输出。
**依赖关系:问题一是问题二的前提。**没有 Cross-Attention, 和 就没有差别,CFG 的差值为零,放大也没有意义。先让网络能理解条件,再谈如何放大条件的影响。
Stable Diffusion 对两个问题都给出了答案:Cross-Attention 解决问题一(让 U-Net 读取文本 embedding),CFG 解决问题二(推理时用 控制贴合强度)。本章先讲问题二的两种方案(Classifier Guidance → CFG),再讲问题一的实现(Cross-Attention),最后串联成完整推理流程。
2. Classifier Guidance(分类器引导)#
来自 Dhariwal & Nichol, 2021(OpenAI 的 "Diffusion Models Beat GANs" 论文)。这是第一个让扩散模型在 ImageNet 上超过 GAN 的方法。
2.1 训练方式:分开训练,完全独立#
Classifier Guidance 由两套完全独立的训练组成,互不干扰:
第一步:正常训练扩散模型(无条件,不需要标签)
for each step:
x_0 = 真实图像(不需要标签 y)
t, ε ~ 随机采样
x_t = sqrt(ᾱ_t)·x_0 + sqrt(1-ᾱ_t)·ε
loss = MSE(ε_θ(x_t, t), ε)
反向传播更新 U-Net
分类器全程不参与,U-Net 学的是无条件 。
第二步:单独训练噪声分类器(输入必须是带噪声的 x_t)
for each step:
x_0, y = 带标签的真实图像
t ~ 随机采样(覆盖所有噪声程度 1…T)
x_t = 用前向公式加噪到 t 步
loss = CrossEntropy(p_φ(y | x_t, t), y)
反向传播更新分类器
关键:分类器输入是 ,因为推理时它要对各个噪声程度的中间图分类。用干净图像训练的普通分类器在这里完全不管用。
推理时:两个网络组合,但没有任何训练在发生
for t = T, T-1, ..., 1:
ε_θ = U-Net(x_t, t) # 无条件噪声预测(U-Net 冻结)
grad = ∇_{x_t} log p_φ(y | x_t, t) # 分类器梯度(分类器冻结)
ε̃ = ε_θ - s · sqrt(1-ᾱ_t) · grad # 合并:贝叶斯公式
x_{t-1} = 用 ε̃ 做去噪步骤
分类器梯度不是训练信号,不更新任何权重。它只是在每步采样时给去噪方向加一个"指向类别 的偏转"。
**grad 是一个向量,和 形状完全一样。**分类器本身输出的是标量概率("这张噪声图属于金毛犬的概率是 0.23"),但对 求梯度之后,得到的是和 同维度的向量——每个位置的值告诉你"把这里往哪个方向动一点,分类器会觉得更像目标类别"。
数字例子:假设 只有 2 维#
x_t = [0.5, -0.3] # 当前带噪声的图(简化成 2 维)
# 分类器前向:输出标量概率
logit = classifier(x_t, t) # 比如 [金毛犬: -1.2, 猫: 0.8, ...]
prob_y = softmax(logit)[金毛犬] # = 0.23 ← 这是个标量
# 对 x_t 反向传播,得到梯度(和 x_t 同形,是个向量)
grad = ∇_{x_t} log(0.23) # = [+0.1, +0.4]
# 含义:x_t[0] 往正方向动 → 金毛犬概率升高
# x_t[1] 往正方向动 → 金毛犬概率更高
# 假设 ε_θ = [0.6, 0.2],s = 3,sqrt(1-ᾱ_t) = 0.5
ε̃ = [0.6, 0.2] - 3 · 0.5 · [0.1, 0.4]
= [0.6, 0.2] - [0.15, 0.6]
= [0.45, -0.4] ← 去噪方向向"金毛犬更集中"的区域偏转
为什么加了分类器梯度不会破坏扩散模型?U-Net 的权重完全冻结,不被修改。分类器梯度修改的是每步的去噪轨迹(走哪条路),而不是 U-Net 学到的能力(怎么走路)。数学上这正好对应贝叶斯分解:无条件 score + 分类器梯度 = 条件 score,完全合法。
2.2 核心思路#
训练一个单独的噪声分类器 ——注意它的输入是带噪声的图像 ,而非干净图像。然后利用它的梯度来引导去噪方向,使生成图像属于目标类别 。
2.3 数学推导#
我们想采样自条件分布 ,需要条件 score:
贝叶斯公式取 log 求梯度:, 与 无关
引入引导强度 (guidance scale):
- :退化为无条件生成
- :标准贝叶斯条件生成
- :放大分类器梯度,生成更"典型"但多样性更低的图像
Classifier Guidance 的三大缺点
- 需要额外训练一个能在噪声图像上工作的分类器,训练成本不低
- 每步采样需要额外做一次分类器前向 + 反向传播(算梯度),推理速度慢
- 只能处理离散类别条件(有多少类就训练多少类的分类器),无法直接用于文本等连续条件
**面试要点:**Classifier Guidance 的核心贡献是证明了"guidance scale 可以用多样性换质量"。这个 quality-diversity tradeoff 的思想被 CFG 继承并发扬光大。
3. Classifier-Free Guidance (CFG)#
来自 Ho & Salimans,NeurIPS 2021 Workshop。CFG 是当前所有主流文生图模型的标准配置。
3.1 原论文实际在做什么#
CFG 原论文演示的是类别标签条件(ImageNet 分类),而不是文本。条件 就是一个整数类别,注入方式和时间步 完全一样——转成 embedding 向量后直接加到 U-Net 的特征上,不需要 cross-attention。
条件注入方式取决于条件的形态
| 条件类型 | 注入方式 | Cross-Attention? |
|---|---|---|
| 类别标签(整数,如 207="金毛犬") | embedding → 加到特征(和时间步 一样) | 不需要 |
| 文本("一只猫坐在沙滩上") | CLIP 编码成 77 个 token 序列 → cross-attention | 需要 |
类别标签是一个标量,直接转 embedding 就够了。文本是变长的 token 序列,必须用 cross-attention 让图像每个位置去"查询"文本的每个 token。CFG 本身只是一个训练+推理策略,对两种方式都适用。
同期(2021 年底),OpenAI 的 GLIDE 第一次把 cross-attention 加进 U-Net 做文本条件,并同时应用了 CFG——这才是"文本 + CFG"的首次合体。Stable Diffusion(2022)继承了这套架构并搬到隐空间、开源。所以:
- CFG 策略本身:Ho & Salimans,2021,类别标签条件
- Cross-Attention for 文本:GLIDE,2021,同期
- 两者合体 + 开源:Stable Diffusion,2022
3.2 核心思想#
不需要单独的分类器——用同一个去噪网络同时学习有条件去噪和无条件去噪,然后在采样时利用两者的差值做引导。
3.3 训练技巧:条件丢弃#
训练时以概率 (通常 10%–20%)随机把条件 替换为空标记 (null embedding):
- 80%–90% 的时间:网络学习 (有条件去噪)
- 10%–20% 的时间:网络学习 (无条件去噪)
这样一个网络就同时具备了有条件和无条件的能力。
3.4 CFG 采样公式#
等价形式:
3.5 直觉理解#
把噪声预测想象成二维向量:
- :无条件预测——"我觉得这个噪声应该往 方向去"
- :有条件预测——"加上 prompt 后应该往 方向去"
- 差值 ——这就是**"条件的影响方向"**
CFG 的做法:从无条件预测出发,沿着"条件影响方向"走 步:
数字例子()#
可以看到, 把"条件的方向"放大了 7.5 倍。最终噪声预测远远偏离了无条件预测,强烈地朝着条件要求的方向走。
3.6 的取值含义#
| 值 | 含义 | 效果 |
|---|---|---|
| 完全忽略条件 | 无条件生成 | |
| 标准条件生成 | 不做额外引导 | |
| (SD 默认) | 强引导 | 图像高度符合 prompt |
| 过度引导 | 颜色过饱和、细节失真 |
3.7 太大为什么会出问题?#
因为 (CFG 合成出来的最终噪声预测,不是网络直接输出的,而是 算出来的)的范数远大于训练时见到的 。训练时噪声服从标准高斯,大部分元素在 范围内;而 时 的元素可以到几十,大大超出网络训练时的"舒适区"。结果就是颜色过饱和、出现伪影。
从 Classifier Guidance 到 CFG 的演进
Classifier Guidance 需要分类器梯度;CFG 用两次前向传播的差值代替了梯度计算。数学上可以证明两者在一定假设下等价,但 CFG 在工程上好得多:
- 不需要额外的分类器网络和训练
- 不需要反向传播(只需前向)
- 天然支持文本等任意形式的条件
- 一个网络搞定所有事
4. CFG 的实际影响和调参#
4.1 典型 guidance scale 取值#
| 任务 | 推荐 范围 | 原因 |
|---|---|---|
| 文本 → 图像 | 7 – 12 | 需要强引导才能准确匹配文本描述 |
| 图像编辑 / img2img | 1.5 – 3 | 已有原图约束,过强引导会破坏原图结构 |
| 超分辨率 | 1 – 2 | 主要靠纹理细节,不需要语义引导 |
| 视频生成 | 3 – 7 | 帧间一致性需要适度引导 |
4.2 Quality-Diversity Tradeoff#
- 小 → 多样性高,但可能不符合 prompt("自由发挥"太多)
- 大 → 高度符合 prompt,但所有生成结果趋同、颜色过饱和
可以类比温度参数: 越大相当于温度越低,分布越尖锐。
4.3 Dynamic CFG(动态引导)#
不同时间步使用不同的 :
- 前期( 大):用大 (如 15),确定整体构图和语义
- 后期( 小):用小 (如 3),添加自然细节、避免过饱和
直觉是:前期决定"画什么",后期决定"画得多自然"。
⚠️ Dynamic CFG 不是默认行为
你在 Diffusers / ComfyUI / WebUI 里看到的 CFG scale 输入框,给的是一个固定值,整个推理过程全程用这个 ——这是最标准、最通用的实现。
Dynamic CFG 需要额外的插件或手动改推理代码(ComfyUI 有专门的 CFGScheduler 节点,WebUI 有 Dynamic Thresholding 扩展)。它是社区里的进阶调参技巧,不是主流框架的默认配置,面试时了解原理即可,不需要当成"标准做法"来记。
4.4 Negative Prompt 的原理#
标准 CFG 公式中,无条件预测 使用空 embedding。Negative prompt 把它替换为负面条件的预测:
= 正面 prompt, = 负面 prompt(如 "blurry, low quality")
具体例子#
正面 prompt = "a beautiful landscape photo",负面 prompt = "blurry, watermark, low quality"
- :网络预测"如果要生成模糊低质量图,噪声方向是 "
- :网络预测"如果要生成美丽风景,噪声方向是 "
- 差值 ,代表"从低质量走向高质量风景"的方向
- :
negative prompt 的效果:起点从"什么都不画"变成了"画得差",引导方向变成了"远离差,走向好"。
**面试要点:**Negative prompt 并不是"删除"某些东西,而是改变了 CFG 的参考基线——从"无条件"变成"负面条件"。引导方向变成"远离负面 + 趋近正面"。