Classifier-Free Guidance(CFG) 如何让扩散模型真的听话
文章目录
-
- 一、为什么模型光会“生图”还不够?它还得“听话”
- 二、先建立直觉:CFG 本质上是在做“方向修正”
- 三、先回顾一个前提:条件扩散模型到底在学什么?
- 四、那为什么还需要 Guidance?直接条件生成不够吗?
- 五、先讲历史前身:Classifier Guidance 是怎么来的?
- 六、Classifier-Free Guidance 的核心妙招:让模型学会“两种说话方式”
- 七、CFG 最重要的一条公式:它到底在算什么?
- 八、为什么 guidance scale 大于 1 会更“听话”?
- 九、但为什么 guidance scale 太大又容易翻车?
- 十、为什么说 CFG 本质上是在近似“条件分布 / 无条件分布”的差异?
- 十一、把它彻底讲形象:CFG 到底在“拉”什么?
- 十二、训练时为什么只需要“丢条件”,不需要额外分类器?
- 十三、极简 PyTorch:CFG 推理骨架长什么样?
- 十四、为什么 Stable Diffusion 里经常用 7.5?
- 十五、Negative Prompt 和 CFG 有什么关系?
- 十六、CFG 的优点到底是什么?
- 十七、CFG 的代价和局限是什么?
- 十八、把它和你已经学过的扩散公式接起来
- 十九、你必须真正记住的 6 句话
- 二十、终极总结:Classifier-Free Guidance 到底在“拉”什么?
本文通过直观的比喻和极简的 PyTorch 代码,彻底拆解扩散模型里最常被提到、也最容易“会背公式但没真正懂”的技巧之一:Classifier-Free Guidance(CFG)。看完你应该能真正回答一句话:为什么一句提示词,真的能把扩散采样轨迹“拉向”你想要的图像?
一、为什么模型光会“生图”还不够?它还得“听话”
假设你已经训练好了一个扩散模型。
它确实会从噪声里生成图片,但这时你会立刻遇到一个现实问题:
我不只是想让它生成“某张图”,我还想让它生成“我指定内容的图”。
比如:
- “一只戴墨镜的柴犬”
- “赛博朋克城市夜景”
- “白底产品图,一只蓝色马克杯”
如果模型只是会从图像分布里随机采样,那它可能生成:
- 狗,但不一定戴墨镜
- 城市,但不一定赛博朋克
- 杯子,但不一定是蓝色
所以我们不只需要 生成能力,还需要 服从条件的能力。
这就是 Guidance 想解决的问题:
让采样过程不只是“往真实图片方向走”,还要“往符合条件的真实图片方向走”。
二、先建立直觉:CFG 本质上是在做“方向修正”
你可以先把扩散采样粗暴理解成一句话:
模型每一步都在回答:“从当前这张带噪图出发,往哪个方向去噪,会更像真实图像?”
而 CFG 在这个基础上,多加了一句:
“不仅要更像真实图像,还要更像‘符合你这句提示词’的真实图像。”
1. 核心比喻:两个修图师,一个讲“像真图”,一个讲“更像提示词”
想象你有两个修图师。
第一个修图师只关心一件事:
- “这张图怎样修,会更像一张自然真实的图片?”
第二个修图师除了关心真实,还额外知道你的提示词:
- “这张图怎样修,会更像‘一只戴墨镜的柴犬’?”
于是每一轮采样时,你不再只听第一个人的意见,而是把第二个人的意见放大一点:
- “真实”很重要
- 但“贴合提示词”也要更强一点
这就是 CFG 的本质:
用条件预测和无条件预测之间的差值,去构造一个更强的“朝条件靠拢”的修正方向。
三、先回顾一个前提:条件扩散模型到底在学什么?
在条件扩散里,模型输入通常不只是带噪图 x_t 和时间步 t,还包括条件 c:
- 文本提示词 embedding
- 类别标签
- 图像条件
- 其他控制信号
于是模型学的是:
ϵ θ ( x t , t , c ) \epsilon_\theta(x_t, t, c) ϵθ(xt,t,c)
也就是:
“给定当前带噪图、当前时间步和条件信息,请预测这次混进来的噪声。”
如果 c = "a dog",模型就会朝“更像狗”的方向去噪。
如果 c = "a cat",模型就会朝“更像猫”的方向去噪。
这就是条件扩散的基本能力。
四、那为什么还需要 Guidance?直接条件生成不够吗?
理论上,直接用条件模型就已经能生成和提示词相关的图了。
但实际中经常会有一个问题:
它会听,但听得不够死。
比如你提示:
- “红色小汽车”
模型可能给你:
- 一辆车,但颜色偏橙
- 或者是一辆很小的红卡车
- 或者背景和主体都对,但“红色”不够明显
也就是说,普通条件模型更像:
“我知道你的意思,我尽量往这个方向靠。”
而 Guidance 想做的是:
“不只是靠,而是更用力地往这个方向靠。”
五、先讲历史前身:Classifier Guidance 是怎么来的?
在 CFG 出现前,先有一个更早的思路:Classifier Guidance。
1. 它的想法很直接
除了去噪模型外,再单独训练一个分类器:
p ϕ ( y ∣ x t ) p_\phi(y|x_t) pϕ(y∣xt)
这个分类器做的事是:
输入一张带噪图 x_t,告诉你它更像哪个类别。
比如:
- 这张带噪图有多像“狗”
- 有多像“猫”
- 有多像“汽车”
2. 为什么分类器能提供 guidance?
因为分类器的梯度:
∇ x t log p ϕ ( y ∣ x t ) \nabla_{x_t} \log p_\phi(y|x_t) ∇xtlogpϕ(y∣xt)
告诉了你一件很重要的事:
如果想让当前图更像类别 y,应该朝输入空间的哪个方向改。
所以在采样时,你可以把这个梯度加到去噪方向里,相当于给模型一个“朝目标类别靠拢”的外力。
3. 但它有个明显麻烦
你得额外训练一个分类器,而且这个分类器还得能处理不同噪声级别的图。
这带来了几个问题:
- 训练更麻烦
- 系统更复杂
- 分类器和去噪模型之间可能不匹配
于是大家就想:
能不能不要额外分类器,直接让扩散模型自己同时扮演“有条件”和“无条件”两个角色?
这就是 Classifier-Free Guidance 的出发点。
六、Classifier-Free Guidance 的核心妙招:让模型学会“两种说话方式”
CFG 的关键设计极其巧妙:
训练时,不是永远把条件喂给模型,而是有时候故意把条件拿掉。
1. 训练时怎么做?
对于每个训练样本,我们有条件 c,比如一句文本提示词。
训练时随机做两种情况:
- 大多数时候:正常喂条件
c - 少数时候:把条件置空,或者替换成 null token
于是同一个模型就被训练成同时会做两件事:
-
有条件预测
ϵ θ ( x t , t , c ) \epsilon_\theta(x_t, t, c) ϵθ(xt,t,c)
它表示:“在知道提示词的情况下,我觉得噪声是什么。” -
无条件预测
ϵ θ ( x t , t , ∅ ) \epsilon_\theta(x_t, t, \varnothing) ϵθ(xt,t,∅)
它表示:“什么提示词都不给时,我觉得噪声是什么。”
2. 这一步的直觉是什么?
无条件预测更像在回答:
- “怎样去噪,能更像一张自然真实的图?”
有条件预测则在回答:
- “怎样去噪,能更像一张符合提示词的真实图?”
于是两者之间的差值,就会暴露出一个非常关键的量:
条件信息到底把去噪方向往哪里拉偏了。
七、CFG 最重要的一条公式:它到底在算什么?
Classifier-Free Guidance 最经典的写法是:
ϵ ^ c f g = ϵ θ ( x t , t , ∅ ) + w ⋅ ( ϵ θ ( x t , t , c ) − ϵ θ ( x t , t , ∅ ) ) \hat{\epsilon}_{cfg} = \epsilon_\theta(x_t, t, \emptyset) + w \cdot \left(\epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \emptyset)\right) ϵ^cfg=ϵθ(xt,t,∅)+w⋅(ϵθ(xt,t,c)−ϵθ(xt,t,∅))
也常写成等价形式:
ϵ ^ c f g = ( 1 − w ) ϵ θ ( x t , t , ∅ ) + w ϵ θ ( x t , t , c ) \hat{\epsilon}_{cfg} = (1-w)\epsilon_\theta(x_t, t, \emptyset) + w\,\epsilon_\theta(x_t, t, c) ϵ^cfg=(1−w)ϵθ(xt,t,∅)+wϵθ(xt,t,c)
其中:
- ϵ θ ( x t , t , ∅ ) \epsilon_\theta(x_t, t, \emptyset) ϵθ(xt,t,∅):无条件噪声预测
- ϵ θ ( x t , t , c ) \epsilon_\theta(x_t, t, c) ϵθ(xt,t,c):有条件噪声预测
- w w w:guidance scale,引导强度
1. 这条式子怎么翻译成人话?
先看这部分:
ϵ θ ( x t , t , c ) − ϵ θ ( x t , t , ∅ ) \epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \emptyset) ϵθ(xt,t,c)−ϵθ(xt,t,∅)
它表示:
“条件 c 到底把去噪方向和无条件情况相比,额外推向了哪里。”
然后乘上一个 w,就表示:
“把这个朝条件靠拢的偏移量,放大 w 倍。”
最后再加回无条件预测,意思就是:
先保证图像仍然往‘自然真实’方向走,再额外更用力地往‘符合提示词’方向拽。
2. 为什么大家常把它叫“拉力”?
因为它真的很像两个力的叠加:
- 无条件预测:把你拉向“真实图片流形”
- 条件差值项:把你拉向“更符合提示词的区域”
所以 CFG 的本质不是凭空创造信息,而是:
在原有去噪方向上,加一个“更贴条件”的偏置。
八、为什么 guidance scale 大于 1 会更“听话”?
这是很多人第一次看到 CFG 公式时最困惑的点。
正常线性插值不是权重加起来等于 1 吗?
为什么这里经常用:
w = 5w = 7.5w = 12
这种看上去“过头了”的权重?
1. 因为这不是普通插值,而是在“外推”
如果 w = 1,那就是普通条件预测:
ϵ ^ c f g = ϵ θ ( x t , t , c ) \hat{\epsilon}_{cfg} = \epsilon_\theta(x_t, t, c) ϵ^cfg=ϵθ(xt,t,c)
如果 w > 1,那其实是在做一件事:
沿着“从无条件预测指向有条件预测”的方向,继续往前多走一段。
这叫 extrapolation(外推),不是 interpolation(插值)。
2. 直观比喻:导航说往东走 10 米,你故意多走到 20 米
无条件预测像在说:
- “往这边走,会更像真实图片。”
有条件预测像在说:
- “往这边再偏一点,会更像提示词要求的图片。”
而当你把 w 调大时,本质上是在说:
- “我知道提示词给的偏移方向了,那我就沿这个方向走得更远一点。”
所以它会让图更“听话”。
3. 为什么这招有效?
因为很多时候,普通条件模型虽然知道条件,但施加得不够强。
CFG 通过放大条件差值项,相当于显式提升了条件信号在采样中的影响力。
于是:
- 主体更明确
- 属性更明显
- 提示词和图像的对应更强
九、但为什么 guidance scale 太大又容易翻车?
因为“更听话”不是免费的。
当你把 w 调得太大时,模型会越来越像在说:
“我宁可过度迎合提示词,也不能偏一点。”
这常常带来几个副作用:
1. 颜色、对比度、饱和度异常
这是很多扩散模型里非常常见的现象。
因为模型被过度拉向某个条件方向后,容易把某些属性推得过头:
- 红色更红
- 高光更亮
- 阴影更重
- 纹理更硬
2. 多样性下降
因为 guidance 太强时,模型更倾向于沿一条很窄的“最符合提示词”的轨道走。
结果就是:
- 图更统一
- 但随机性和变化性更小
3. 容易产生不自然的伪细节
当条件牵引过强时,模型可能会硬凑出一些“看起来像满足提示词、但其实不自然”的结构。
比如:
- 手部细节怪异
- 物体边缘过于锐利
- 局部出现奇怪重复
所以 guidance scale 本质上是在平衡两件事:
- 条件一致性
- 图像自然性
十、为什么说 CFG 本质上是在近似“条件分布 / 无条件分布”的差异?
如果从概率视角看,CFG 背后其实有一个很漂亮的思想。
扩散模型本质上在学习 score / 去噪方向,而条件与无条件之间的差别,近似对应了:
“在满足条件 c 时,图像分布相对于整体图像分布,到底偏向哪里。”
粗暴理解就是:
- 无条件模型知道“自然图片通常长什么样”
- 条件模型知道“满足
c的自然图片通常长什么样” - 两者差值就体现了“条件
c带来的偏移趋势”
所以 CFG 不是乱加,而是利用:
条件分布和边缘分布之间的方向差。
这也是为什么它会这么有效。
十一、把它彻底讲形象:CFG 到底在“拉”什么?
这部分你一定要建立画面感。
想象当前某一步的带噪图 x_t,还很模糊。
1. 无条件模型看到它,会怎么想?
它会说:
- “这团东西更像一张自然图像的话,应该往这边去噪。”
这个方向可能通向:
- 某种动物
- 某种街景
- 某种人像
但并不特指你的提示词。
2. 条件模型看到同一张图,又会怎么想?
如果条件是:
- “一只戴墨镜的柴犬”
那它会说:
- “如果要更像这个提示词,那去噪方向应该再往柴犬、墨镜、特定脸型和颜色分布那边偏一些。”
3. 所以 CFG 真正在拉的,不是像素,而是“去噪方向”
这一点非常重要。
CFG 不是在直接说:
- “这里加一副墨镜”
- “那里加一条狗尾巴”
它做的是更底层的事情:
它在每一步微调噪声预测,从而微调整条采样轨迹。
也就是说,CFG 拉的不是最终图片某一块像素,而是:
整张图在每一步应该朝哪个方向变干净。
这就是为什么一条文本提示词,能够在几十步采样后,最终塑造出完整语义和结构。
十二、训练时为什么只需要“丢条件”,不需要额外分类器?
这正是 CFG 最优雅的地方。
1. 训练阶段
你只需要在训练条件模型时,加一个简单操作:
- 以一定概率
p_uncond - 把条件
c替换成空条件∅
于是模型被迫学会:
- 给条件时怎么预测
- 不给条件时怎么预测
2. 推理阶段
同一张带噪图,在同一个时间步:
- 跑一次无条件预测
- 跑一次有条件预测
- 然后做一次 CFG 组合
整个过程不需要单独的分类器。
这就是“Classifier-Free”这个名字的来源:
不是没有 Guidance,而是不依赖外部分类器。
十三、极简 PyTorch:CFG 推理骨架长什么样?
下面是最经典的 CFG 推理写法。
import torch
@torch.no_grad()
def cfg_denoise_step(model, x_t, t, cond, uncond_cond, guidance_scale):
"""
model: 预测噪声的扩散模型
x_t: 当前带噪图
t: 当前时间步
cond: 有条件输入(如文本 embedding)
uncond_cond: 空条件输入(如 null embedding)
guidance_scale: CFG 强度
"""
eps_uncond = model(x_t, t, uncond_cond)
eps_cond = model(x_t, t, cond)
eps_cfg = eps_uncond + guidance_scale * (eps_cond - eps_uncond)
return eps_cfg
然后你再把 eps_cfg 交给 scheduler,去更新下一步的 x_{t-1}。
所以从工程角度看,CFG 的核心非常朴素:
- 跑两次模型
- 做一次线性组合
- 用组合后的噪声预测继续采样
十四、为什么 Stable Diffusion 里经常用 7.5?
很多人第一次用 Stable Diffusion 时都会看到一个神秘数字:
guidance_scale = 7.5
这不是数学定律,而是经验上比较折中的一个默认值。
它通常意味着:
- 提示词约束已经足够明显
- 但还没有强到特别容易炸细节
当然,不同模型、不同任务、不同提示词,最佳值会不同。
粗暴经验可以这样记:
- 较小的 scale:更自然、更松弛、更多样
- 中等的 scale:通常最平衡
- 过大的 scale:更听话,但更容易过饱和、失真、僵硬
十五、Negative Prompt 和 CFG 有什么关系?
这也是你在实践里非常常见的一个点。
在很多文本到图像系统里,“无条件分支”并不一定真的什么都不给,而是可以喂一个 negative prompt:
比如:
blurry, low quality, deformed hands
这时公式还是类似的,只不过“uncond”分支不再是完全空白,而是:
“往不要这些东西的方向去。”
于是 CFG 的组合效果就变成了:
- 一边朝正向提示词靠
- 一边远离负面提示词
这也是为什么 negative prompt 往往很有效。
十六、CFG 的优点到底是什么?
可以直接总结成 4 点:
1. 不需要额外分类器
系统更简单,训练和部署都更干净。
2. 条件控制很强
对文本、类别、属性等条件的服从度明显提升。
3. 实现简单
本质只是:
- 训练时做条件 dropout
- 推理时做双分支预测和线性组合
4. 通用性强
不只文本到图像,很多条件扩散任务都能用。
十七、CFG 的代价和局限是什么?
同样也要看到它的成本。
1. 推理要跑两次网络
最经典的 CFG 推理通常需要:
- 一次无条件前向
- 一次有条件前向
所以推理成本大约翻倍。
2. scale 调参敏感
不同 prompt 和模型,对 guidance scale 的最佳值不一样。
3. 强 guidance 容易伤自然性
前面已经讲过:
- 过强会过饱和
- 过强会失真
- 过强会降低多样性
所以 CFG 不是“越大越好”。
十八、把它和你已经学过的扩散公式接起来
如果你已经看懂了前面那篇“为什么扩散模型能从噪声里还原图像”,那现在只需要加上一层理解:
原本采样时,我们用的是:
ϵ θ ( x t , t ) \epsilon_\theta(x_t, t) ϵθ(xt,t)
现在换成:
ϵ ^ c f g = ϵ θ ( x t , t , ∅ ) + w ( ϵ θ ( x t , t , c ) − ϵ θ ( x t , t , ∅ ) ) \hat{\epsilon}_{cfg} = \epsilon_\theta(x_t, t, \emptyset) + w \left(\epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \emptyset)\right) ϵ^cfg=ϵθ(xt,t,∅)+w(ϵθ(xt,t,c)−ϵθ(xt,t,∅))
然后再把这个 ϵ ^ c f g \hat{\epsilon}_{cfg} ϵ^cfg 放进 DDPM / DDIM / 其他 scheduler 的更新公式里。
也就是说:
CFG 并没有改变扩散模型的整体框架,它只是把“每一步的噪声预测”换成了一个更偏向条件的版本。
所以你可以把它看成:
- 扩散模型:提供去噪主干
- CFG:给去噪方向加一个条件偏置
十九、你必须真正记住的 6 句话
如果这篇很长,你至少要记住下面 6 句:
-
CFG 的目标不是让模型更会画图,而是让模型更听条件。
-
训练时通过随机丢掉条件,让同一个模型同时学会有条件和无条件预测。
-
无条件预测负责把图拉向“自然真实图片”,有条件预测负责把图拉向“符合提示词的真实图片”。
-
两者差值表示:条件到底把去噪方向往哪里额外推了一下。
-
guidance scale 大于 1 不是普通插值,而是在沿条件方向做外推,所以会更听话。
-
scale 太大时,图会更听话,但也更容易失真、过饱和、缺少多样性。
二十、终极总结:Classifier-Free Guidance 到底在“拉”什么?
现在你可以用一句完整的人话回答了:
Classifier-Free Guidance 不是在直接修改最终图像,而是在每一步采样时,用“有条件预测”和“无条件预测”的差值,构造出一个更偏向提示词的去噪方向,从而把整条生成轨迹逐步拉向你想要的内容。
一句更短的版本:
CFG 拉的不是像素,而是每一步的去噪方向。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)