广告位 · 页头(后台-模块管理-新建模块后替换此区域)

无分类器引导(Classifier-Free Guidance)与CFG参数是什么关系?

扩散模型在图像生成任务中的核心机制,是让网络学会从一个纯噪声或者带噪图像中估计出需要去除的噪声。对于文生图场景,光有无条件去噪还不够,必须把文本语义作为条件注入去噪过程。Classifier-Free Guidance正是解决这一条件引导问题的常用方法。它的思路很直接:同一个去噪模型,训练时按照一定概率把文本条件置空,让它同时具备条件预测和无条件预测的能力。推理阶段,把条件预测结果与无条件预测结果的差值当作指向文本语义的方向,再用一个标量系数放大或缩小这个方向。这个标量系数就是CFG参数,也叫CFG Scale。

无分类器引导(Classifier-Free Guidance)与CFG参数是什么关系?

无分类器引导为什么能替代分类器

在早期的条件扩散模型里,比较常见的做法是训练一个额外的图像分类器,在采样时通过分类器对生成图像计算类别梯度,再利用梯度引导去噪过程。这种方法最大的问题是要单独维护一个分类器,并且在噪声很大的中间步骤上,分类器给出的梯度不一定可靠。无分类器引导换了一种思路:不依赖外部模型,而是让扩散模型自己同时学会有条件和无条件两种去噪路径。

实现上并不复杂。训练时,每一批数据里有一定概率把文本条件替换成空文本,比如把提示词编码成空字符串对应的嵌入向量。这个概率通常在10%到20%之间。模型于是既看到了带文本条件的样本,也看到了无条件样本。推理时,对同一个带噪潜在向量分别传入真实文本嵌入和空文本嵌入,得到两个噪声预测:一个是条件预测,一个是无条件预测。无分类器引导的更新公式可以写成 guided_noise = uncond_noise + cfg_scale * (cond_noise - uncond_noise)。

当 cfg_scale 等于1时,公式退化为普通条件生成,因为外推项消失,只剩下条件预测。当 cfg_scale 大于1时,条件方向被放大,模型会更激进地靠近文本描述。这种放大可以理解为把条件分布从无条件分布中推出去,进一步强调文本特征。由于整个过程不需要分类器,所以叫无分类器引导。

CFG参数如何左右生成结果

CFG参数的变化对画面影响非常直观。把CFG从1逐渐调高,最明显的变化是图像会变得更锐利、对比度更高、色彩更浓郁,同时文本提示中的物体、颜色、构图约束会被执行得更彻底。例如提示词中写明红色帽子,低CFG时可能帽子颜色偏灰或者被忽略,高CFG时红色会非常醒目。

但这种提升不会一直持续。当CFG高过某个临界值,画面会开始出现过饱和、高光溢出、边缘发硬甚至结构崩坏。原因是噪声预测外推过度,偏离了模型训练时见过的分布范围。不同模型和采样器对这个临界值的敏感度不一样,一般来说SD1.5、SDXL等模型在7到12之间比较稳定,超过15就容易出问题。

反过来,CFG很低时,模型更偏向无条件生成。无条件输出的多样性更强,构图更自由,但很可能不按提示词来。比如要求一只猫坐在沙发上,低CFG生成的图里可能是猫的轮廓模糊,或者沙发完全消失。w等于0时就是完全忽略文本条件,生成结果等同于随机采样。因此CFG参数本质上是语义一致性和生成多样性之间的调节旋钮。

下面列出几个典型取值区间供参考:

  • w=0:完全忽略文本条件,图像与提示无关。
  • w=1至3:文本约束弱,画面自由度高,可能偏离描述。
  • w=5至10:多数扩散模型的推荐区间,质量与语义较平衡。
  • w=12以上:过饱和、伪影风险增加,适合特定风格化测试。

代码实现:在采样循环中应用CFG

在实际的Stable Diffusion推理代码里,CFG并不是一个复杂函数,而是每一步去噪时对噪声预测做一次线性外推。假设已经拿到了文本条件嵌入和空文本嵌入,下面是分开前向传播的实现方式:

def apply_classifier_free_guidance(model, latents, timestep, cond_embeddings, uncond_embeddings, cfg_scale):
    # 分别预测条件噪声和无条件噪声
    noise_pred_cond = model(latents, timestep, cond_embeddings)
    noise_pred_uncond = model(latents, timestep, uncond_embeddings)
    # 核心公式:把条件方向从无条件方向中外推
    guided_noise = noise_pred_uncond + cfg_scale * (noise_pred_cond - noise_pred_uncond)
    return guided_noise

这段代码的关键在于guided_noise的计算。它不是简单地对两个噪声取平均,而是以无条件噪声为基准,沿着条件噪声与无条件噪声的差值方向移动。移动距离由cfg_scale控制。如果cfg_scale为0,返回的就是无条件噪声;如果为1,返回条件噪声;如果大于1,就得到了比普通条件更强的引导信号。

为了节省显存,很多推理框架会把条件嵌入和无条件嵌入在batch维度拼接后一次前向传播。比如把潜在向量复制两份,把条件嵌入和无条件嵌入上下拼接,送入模型后得到两个输出,再拆分。两种写法数值上等价,只是工程上的显存优化。采样器拿到guided_noise后,再根据DDIM、DPM++等对应算法更新潜在向量。

不同采样器对CFG的承受能力并不完全一样。例如DPM++在高CFG下有时比DDIM更容易出现彩色噪点,Euler ancestral在中等CFG下细节丰富但可能引入随机性。因此不能只记住一个固定值,而是要结合采样器一起调整。

调参经验与常见误区

调整CFG参数时,比较可靠的做法是固定随机种子、固定提示词和采样步数,只改变CFG做一组对比。通常建议从5或7开始,然后测试3、10、15。把图像放在一起观察:哪些提示词元素丢失了,哪些地方开始出现伪影和过饱和。对于写实类模型,CFG在6到9之间往往比较安全;对于微调模型或DreamBooth训练的人物模型,CFG可能要降到3到6,否则容易出现过拟合特征和塑料感。

一个常见误区是觉得CFG越高,生成质量就越好。实际上高CFG虽然会强化语义,却会牺牲自然度。另一个误区是忽略negative prompt与CFG的联动。负面提示词通常被编码后当作无条件分支的参考,相当于在uncond_embeddings的位置放入了负面文本。CFG放大的是条件预测与这个负面预测之间的差值,所以负面提示词写得越明确,高CFG下排除效果越明显,但也更容易让画面走向极端。

在采样步数较少时,CFG的影响会更加剧烈。因为步数减少后,每一步的更新幅度相对更大,如果再乘以一个很大的CFG系数,噪声预测很容易过冲。此时可以适当降低CFG,或者使用动态CFG策略:采样早期使用较高CFG快速确定结构,后期降低CFG以恢复细节。像LCM、Turbo这类蒸馏模型则比较特殊,它们通常已经把条件引导信息融合进了权重,推理时CFG往往固定为1,甚至不需要单独走无条件分支。

理解无分类器引导和CFG参数的关系,本质上是理解条件分布与无条件分布之间的外推强度。把这个关系摸清楚,调整提示词、负面提示词、采样步数和采样器时,就能更准确地预判画面变化,而不是盲目滑来滑去。

广告位 · 文章底部(后台-模块管理替换此区域)