Classifier-free guidance 和Classifier Guidance

CFG

CFG 在生成阶段( classifier-free guidanc, Inference/Sampling)生效。它的效果是提高生成内容与条件(如文本提示词)的一致性。

具体表现:

假设你输入提示词:“一只穿着宇航服的猫” (A cat in a spacesuit)。

  1. 如果不使用 CFG (或 CFG Scale = 0)

    • 模型只看图像本身的概率分布。
    • 它可能会生成一只很可爱的猫,但可能没有穿宇航服,或者宇航服穿得很奇怪。
    • 图像看起来自然、柔和,但可能偏离提示词。
  2. 如果使用权重较大的 CFG (例如 CFG Scale = 7-15)

    • 模型会强行将生成路径拉向“宇航服猫”的方向。
    • 图像中会清晰地出现宇航服、猫、甚至可能还有星球背景。
    • 效果增强:提示词的各个要素(猫、宇航服)被更紧密地组合在一起。
  3. 如果 CFG 过高 (例如 > 20)

    • 负面效果:图像可能出现伪影(Artifacts)、色彩过饱和、结构扭曲(例如猫有多个头,或肢体融合)。这是因为模型为了强行满足条件,牺牲了图像的自然分布。

既然 CFG 是推理时的技巧,那么训练阶段需要做什么,才能让模型在推理时能玩 CFG 呢?

答案是:你需要在训练数据中随机“丢弃”条件。

在训练扩散模型(如 Stable Diffusion)或流匹配模型时,网络需要学习两件事:

  1. 给定条件ccc,如何生成数据xxx? (p(x∣c)p(x|c)p(xc))
  2. 不给条件,数据xxx长什么样? (p(x)p(x)p(x),即无条件分布)

训练步骤如下:

  1. 准备数据
    你有一批数据,每个样本包含图像xxx和对应的文本提示词ccc

  2. 前向传播(训练循环中)
    对于每一个 batch 的数据,模型以一定的概率(例如 10%-20%)做以下两件事之一:

    • 情况 A (80%-90% 概率):将文本提示词ccc输入到文本编码器中,得到条件向量,送入去噪网络。
    • 情况 B (10%-20% 概率)将文本提示词清空!输入一个空字符串""或特殊的 token(如<uncond>),得到一个“无条件”向量。
  3. 计算损失
    模型同时接收这两种输入,并预测噪声。损失函数(Loss)是将预测噪声与真实噪声做对比。

    • 对于情况 A,模型学习p(x∣c)p(x|c)p(xc)
    • 对于情况 B,模型学习p(x)p(x)p(x)
  4. 结果
    训练结束后,模型内部已经学会了两种模式

    • 当输入有文字时,它知道怎么画具体的物体。
    • 当输入为空时,它知道“一般情况”下的物体长什么样(比如“一般的猫”长什么样)。

在推理阶段,CFG 的公式是:
ϵguided=ϵuncond+w(ϵcond−ϵuncond) \epsilon_{guided} = \epsilon_{uncond} + w (\epsilon_{cond} - \epsilon_{uncond})ϵguided=ϵuncond+w(ϵcondϵuncond)

  • ϵcond\epsilon_{cond}ϵcond:我们输入提示词“宇航服猫”,模型输出基于条件的预测。
  • ϵuncond\epsilon_{uncond}ϵuncond:我们输入“空提示词”,模型输出无条件的预测。

因为模型在训练时见过这两种情况,所以它都能给出准确的预测。我们通过线性组合,放大“条件”与“无条件”之间的差异,从而强行把图像推向符合条件的方向。

CG

**分类器引导(Classifier Guidance, CG)**是扩散模型早期(如 DALL-E 1 或早期 DDPM 论文中)使用的一种主要技术,用于让生成的图像符合特定的文本描述(条件)。
CG需要训练两个独立的模型

1. 分类器引导的效果是什么?

核心效果:通过外部信号强制图像符合特定类别或属性。

  • 高精度类别对齐
    CG 最初主要用于分类任务中的引导。例如,如果你希望生成“猫”,它会极大地提高生成结果中包含“猫”这一特征的概率。在早期的实验ว่า,对于简单的类别引导(如猫 vs. 狗),CG 的效果往往比 CFG 更稳定、更锐利。
  • 计算开销巨大
    为了得到引导后的梯度,你需要在每一步去噪过程中,不仅运行去噪模型(Score Model),还要运行一个额外的分类器模型,并计算梯度。这使得生成速度非常慢(通常是 CFG 的一半或更慢,因为每一步要做两次前向传播和一次反向传播)。

2. 怎么训练分类器引导?

要使用分类器引导,你必须完成两个独立模型的训练

第一步:训练去噪模型 (The Denoising Model / Score Model)
  • 目标:学习从噪声中还原图像分布p(x)p(x)p(x)
  • 输入:带噪声的图像xtx_txt
  • 输出:预测的噪声ϵθ(xt)\epsilon_\theta(x_t)ϵθ(xt)或分数∇xlog⁡p(xt)\nabla_x \log p(x_t)xlogp(xt)
  • 注意:这个模型通常是无条件的,或者在训练时不强制绑定标签。它的主要任务是掌握“什么样的像素分布构成一张好看的图片”。
第二步:训练分类器 (The Classifier)
  • 目标:学习图像与标签之间的映射关系,即学习p(y∣x)p(y|x)p(yx)(给定图像xxx,它属于类别yyy的概率)。
  • 输入:带噪声的图像xtx_txt(注意:是在加噪过程中的图像,而不是干净图像)。
  • 输出:类别概率分布(例如,80% 是猫,20% 是狗)。
  • 训练数据:你需要大量的(x,y)(x, y)(x,y)对,其中xxx是干净图像,yyy是标签。
  • 关键点:这个分类器是在**加噪过程(Forward Process)**中训练的,这意味着它必须能够处理充满噪声的输入,并依然能准确判断图像内容。
训练完成后的推理(采样)过程:

在生成图像时,假设我们要生成“猫”:

  1. 去噪模型预测:首先让去噪模型预测当前步骤的去噪方向∇xlog⁡p(xt)\nabla_x \log p(x_t)xlogp(xt)

  2. 分类器评估:将当前带噪声的图像xtx_txt输入分类器,计算梯度∇xtlog⁡p(y=cat∣xt)\nabla_{x_t} \log p(y=\text{cat} | x_t)xtlogp(y=catxt)

  3. 组合引导:将两个梯度结合。公式如下:
    ∇xtlog⁡p(y=cat,xt)≈∇xtlog⁡p(xt)+σ2∇xtlog⁡p(y=cat∣xt) \nabla_{x_t} \log p(y=\text{cat}, x_t) \approx \nabla_{x_t} \log p(x_t) + \sigma^2 \nabla_{x_t} \log p(y=\text{cat} | x_t)xtlogp(y=cat,xt)xtlogp(xt)+σ2xtlogp(y=catxt)

    • ∇xtlog⁡p(xt)\nabla_{x_t} \log p(x_t)xtlogp(xt)来自去噪模型(保证图像自然)。
    • ∇xtlog⁡p(y=cat∣xt)\nabla_{x_t} \log p(y=\text{cat} | x_t)xtlogp(y=catxt)来自分类器(保证图像是猫)。
    • σ2\sigma^2σ2是引导强度系数。
  4. 更新图像:使用这个组合后的梯度来更新下一步的图像xt−1x_{t-1}xt1

在经典的分类器引导框架下,你几乎无法直接输入“穿宇航服的猫”,或者实现起来极其困难且效果很差。

1. 为什么“穿宇航服的猫”对分类器引导是个难题?

分类器引导依赖于一个预训练的分类器。这个分类器通常是在一个特定的数据集上训练的,比如 ImageNet。

  • ImageNet 的标签体系:ImageNet 中有“猫(cat)”这个类别,也有“宇航服(spacesuit)”这个类别。
  • 但是:ImageNet 中通常没有“穿宇航服的猫(cat in a spacesuit)”这个联合类别。
场景模拟:

如果你想在采样时使用 CG 生成“穿宇航服的猫”,你有以下几种尝试路径,但都会失败或效果极差:

  1. 尝试 1:只使用“猫”分类器

    • 结果:模型会生成一只普通的猫。
    • 原因:分类器只看到了“猫”,它不知道宇航服的存在。它无法引导模型画出宇航服。
  2. 尝试 2:只使用“宇航服”分类器

    • 结果:模型会生成一个宇航员,或者一个穿着宇航服的人/机器人,但不会有猫的特征。
    • 原因:同理,分类器只关注“宇航服”,忽略了“猫”。
  3. 尝试 3:同时运行两个分类器(“猫” + “宇航服”)并相加梯度

    • 逻辑Gradient=∇log⁡p(cat∣x)+∇log⁡p(spacesuit∣x)\text{Gradient} = \nabla \log p(\text{cat}|x) + \nabla \log p(\text{spacesuit}|x)Gradient=logp(catx)+logp(spacesuitx)
    • 结果:这可能会产生一些有趣但通常不连贯语义冲突的结果。
      • 模型可能会生成一个穿着宇航服的猫(这是你想要的)。
      • 但也可能生成一个穿着宇航服的狗,或者一只巨大的猫,或者一个有着猫脸的宇航员。
      • 根本问题:分类器是独立训练的。它不知道“猫”和“宇航服”在空间上是如何组合的。它只分别知道“什么东西像猫”和“什么东西像宇航服”。它缺乏对联合概率分布p(cat, spacesuit∣x)p(\text{cat, spacesuit}|x)p(cat, spacesuitx)的理解。
  4. 尝试 4:重新训练一个“穿宇航服的猫”专用分类器

    • 结果:理论上可行,但工程上不可行。
    • 原因:语义组合是无限的。
      • 你想要“穿宇航服的猫”。
      • 明天你可能想要“戴眼镜的猫”。
      • 后天你想要“在月球上的猫”。
    • 你不可能为每一个可能的形容词+名词组合都训练一个新的分类器。这需要无限的数据和无限的训练时间。

2. 分类器引导的本质缺陷:缺乏语义理解

分类器引导本质上是基于视觉特征的引导,而不是基于语义理解的引导

  • 它问的是:“这张图看起来像猫吗?”和“这张图看起来像宇航服吗?”
  • 它不问的是:“这张图是否描绘了一只猫穿着宇航服?”

由于缺乏对语言语义和物体间空间关系(比如“穿着”表示覆盖关系)的理解,CG 很难处理这种复杂的、多对象的、带修饰关系的自然语言描述。

3. 对比:为什么 CFG 能解决“穿宇航服的猫”?

这就是为什么后来的 Stable Diffusion 和 DALL-E 2 采用**无分类器引导(CFG)**的原因。

  1. 文本编码器(如 CLIP)的作用

    • 在 CFG 中,我们输入的是文本提示词:“a cat in a spacesuit”。
    • 文本编码器将这个短语转化为一个高维向量(Embedding)。这个向量捕捉了“猫”、“宇航服”以及它们之间的语义关系(“in” 表示位置/穿着)。
  2. 模型的统一学习

    • 扩散模型在训练时,不仅学习图像的特征,还学习图像特征与文本向量之间的关联。
    • 当模型看到“猫”和“宇航服”这两个概念在文本向量中同时出现时,它通过学习训练数据中的模式,学会了如何将这些视觉元素组合在一起。
  3. 引导机制

    • 有条件预测:模型看到向量Vcat+spacesuitV_{\text{cat+spacesuit}}Vcat+spacesuit,预测带有这两个特征的图像。
    • 无条件预测:模型看到空向量,预测一般图像。
    • CFG 计算:通过差值放大“带有这两个特征”与“一般图像”之间的差异。
    • 因为模型在训练时见过成千上万张“猫”和“宇航服”的组合(或者通过 CLIP 的泛化能力),它能够理解这种语义组合。

4. 总结

  • 分类器引导 (CG)

    • 输入:类别标签(如 “cat”, “dog”, “spacesuit”)。
    • 处理“穿宇航服的猫”:极其困难。你需要训练一个专门识别“穿宇航服的猫”的分类器,或者尝试组合多个独立分类器的梯度,但效果不可控。
    • 本质:基于视觉特征的逐像素引导。
  • 无分类器引导 (CFG)

    • 输入:自然语言提示词(如 “a cat in a spacesuit”)。
    • 处理“穿宇航服的猫”:非常自然。模型通过理解文本向量中的语义,自动调整像素分布以符合描述。
    • 本质:基于语义对齐的联合概率分布引导。

因此,在现代 AI 绘画中,如果你想要生成“穿宇航服的猫”,你必须使用支持文本条件的模型(如 Stable Diffusion),并依赖 CFG 机制,而不能使用传统的分类器引导方法。