ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

扩散模型机制选择:采样器、无分类器指导与潜在空间设计

扩散模型机制选择:采样器、无分类器指导与潜在空间设计

这个系列的第一篇把扩散模型的前向过程、反向过程、训练目标和生成原理这些地基打完了,第二篇就可以专门聊那些真正影响落地效果的设计选择。扩散模型发展到今天,如果你还停留在“能跑通一个训练脚本、损失曲线也能降下去”的阶段,大概率会对很多现象感到困惑——为什么同样的模型权重,换个采样器结果天差地别?为什么无分类器指导的强度一超过某个阈值,画面就开始发灰发腻?为什么很多人非要把去噪过程塞进一个低维的潜在空间里,反而比直接在像素空间生成效果更好?

这篇梳理就是围绕这些“机制选择”层面的问题展开的。适合已经知道扩散模型基本流程、但想理解模型内部为何这样设计的读者。我会按照从训练目标、采样加速、引导机制、架构演进到工程部署的顺序,把知识体系串起来,尽量做到每个知识点都讲清楚“它解决了什么问题”和“它为什么是这样设计的”。

1. 训练目标的简化:为什么扩散模型只学“预测噪声”就够了

扩散模型的训练目标从表面看特别简单:给定一张加了噪的图片和时间步,让模型预测出加在它身上的噪声。很多初学者心里会犯嘀咕——我们最终想要的是生成干净图片,为什么训练时从头到尾都在跟噪声较劲?

1.1 预测噪声其实是在学习数据分布的梯度方向

把这个问题拆开看。前向过程对样本 (x_0) 逐步加噪得到 (x_t),这个过程本质上是把数据分布逐渐抹平成高斯分布。反向过程要做的,是从高斯噪声里一步步“找回”数据结构。问题在于,怎么知道每一步该往哪个方向修?

这里有一个关键直觉:如果已经知道 (x_t) 里混入了多少噪声,就可以估计出“干净信号”的大致位置;反过来,估算出去的噪声越小,说明这一步对样本的修正越温和。模型预测噪声 (\epsilon_\theta(x_t, t)),等价于在估计条件分布 (\nabla_{x_t}\log q(x_t)) 的一个缩放版本,也就是数据分布的得分方向。所以扩散模型本质上是在用神经网络学一个“指向数据高概率区域”的方向场,去噪过程就是沿着这个方向场做随机微分方程的逆过程求解。

1.2 简化损失函数省略了什么

原始推导从变分下界出发,最后会得到一个逐项对比KL散度的训练目标。但如果真按这个目标训练,每一项的权重在时间步上差异很大,收敛慢,而且收益有限。实践中大家用的都是简化版本:只保留一个带噪声的均方误差项,即让模型直接拟合真实噪声,所有时间步权重相同。

这个简化看起来“丢了精度”,实际上非常聪明。扩散模型的每个时间步都在处理不同频率尺度的信息,大时间步对应粗结构,小时间步对应细节纹理。如果按变分下界的权重来训练,模型会把大量容量花在那些难以感知的细微差异上;统一权重反而让模型更均衡地学习从全局结构到局部细节的生成能力。训练目标里去掉的那部分,相当于允许模型在视觉感知不敏感的方向上“偷懒”,这种宽容换来的是训练稳定性和生成质量的整体提升。

1.3 时间步采样策略与损失权重的实践影响

训练时每个batch都要随机采样时间步 (t)。如果你均匀采样,模型会在简单和困难样本之间来回切换,收敛速度尚可但不容易把细节练好。我试过几种策略,感觉比较稳的是前期均匀采样做预热,后期偏重中等时间步,让模型在“结构还没完全成型、细节已经开始显现”的区间多学一些。另外还有加权损失的做法,给中等时间步更大的权重,但收益未必明显,反而多一个超参数要调。训练目标的另一处细节是预测目标的选择,除了直接预测噪声,也可以预测 (x_0) 或者预测速度项。现在主流的训练仍然普遍采用噪声预测目标,因为和采样器结合时数值稳定性更好,这也是一个值得记住的工程经验。

2. 采样器与去噪加速:把上千步迭代压缩到几十步的关键

如果你真的按DDPM原始设定去生成图片,一次生成要迭代1000步,每步都过一次U-Net。在日常消费级显卡上,这基本等于等一杯咖啡的时间才能出图。采样器研究要解决的核心问题就是:在生成质量几乎不掉的前提下,把采样步数从几百上千压缩到两位数甚至个位数。

2.1 DDPM的慢,慢在每一步都在做“无谓的抖动”

DDPM的反向过程每一步都要采样一次随机噪声,形成一个随机微分方程的离散轨迹。随机性带来多样性,但也带来了冗余——相邻两步的预测结果差异很小,却仍然被当作完全独立的步骤来处理。你可以把DDPM采样想象成一个人喝醉了走回家,路线是曲折的,步子多,每一步都有随机偏移。能走到家,但效率低。

DDIM的做法和DDPM不同:它把反向过程变成确定性过程,每一步不额外注入噪声,一旦初始噪声确定,整条轨迹也随之确定。这就像清醒状态下走回家,路线基本是直线,路径短。DDIM还引入了从任何时间步直接跳回 (t=0) 的估计方法,所以步数可以大幅减少,比如50步甚至20步。代价是多样性略降,因为随机性来源被收窄到了初始噪声和采样轨迹本身。

2.2 从随机微分方程视角看高阶采样器

DDIM虽然快,但本质上还是一阶求解器,好比用折线去逼近一条曲线,步数太少误差会累积。后来有人把反向去噪过程改写成一个常微分方程(也就是概率流ODE)的形式,这样就能借用数值求解领域成熟的高阶方法,例如基于龙格-库塔的Heun采样器,以及专门针对扩散模型指数形式积分设计的DPM-Solver。

DPM-Solver的厉害之处在于,它解析地处理了每一步的线性部分,把模型预测的非线性残差单独拎出来做高阶积分近似。在我自己的测试里,对同样一个模型,DPM-Solver在15到20步就能达到DDIM需要50步以上的效果,步数进一步压缩到10步以内也只是牺牲少量细节。理解这些采样器的差异,可以不用深入数学推导,只需要把握三个关键词即可:随机性(有没有额外噪声)、轨迹离散方式(是折线近似还是曲线拟合)、以及是否利用了解析结构(精确处理了指数项)。

2.3 不同采样器的适用场景

选择采样器不能只看步数,还要考虑具体使用场景。需要风格多样性和一定随机性时,保留一些噪声注入的采样器会更合适;做批量生成、要求结果稳定可复现时,确定性采样器明显更友好。我习惯的配置是:快速出图时用DPM类采样器搭配15到20步;较高精度需求时把步数提到30以上或切换到二阶求解器;做实验对比时统一用固定种子的确定性采样器,保证每次结果一致。

采样器类型典型步数随机性适用场景
DDPM原始采样500-1000高小规模验证,追求最大多样性
DDIM20-50低稳定复现,批量生成
DPM-Solver类10-20取决于实现快速出图,工业级部署
Heun/二阶RK类20-30中细节优先,质量优先

3. 无分类器指导:可控生成里最容易被调崩的超参数

扩散模型训练时学到的是数据分布本身,但用户往往希望生成结果满足额外条件,比如“猫坐在沙发上”或者“某个具体人物的正面照”。条件注入的方式有很多种,其中无分类器指导(Classifier-Free Guidance,简称CFG)几乎成了主流方案。但它也是实践中最容易引发问题的环节:指导权重调得太低,模型“不听话”;调得太高,图像会过饱和、发灰、出现伪影。

3.1 从分类器引导到无分类器指导

早期思路是训练一个额外的分类器,用分类器对输入图像的梯度来引导去噪过程偏向目标类别。这个方法容易理解,但有几个硬伤:需要额外训练分类器,而且分类器对带噪图像的鲁棒性很差,梯度容易把生成结果推向对抗样本那种“看着不对但分类器很自信”的方向。

无分类器指导绕开了显式分类器,思路是在同一模型上同时支持条件生成和无条件生成。训练时以一定概率丢弃条件信息,推理时做两次预测:一次带条件,一次不带条件,然后按指导权重外推。公式可以简写成:

[ \hat{\epsilon}\theta(x_t, t, c) = \epsilon\theta(x_t, t, \varnothing) + s \cdot \left( \epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \varnothing) \right) ]

这里的 (s) 就是指导强度。当 (s=0) 时等于纯无条件生成,(s>0) 时把预测方向往带条件的预测方向拉动。因为训练时条件信息只是被随机遮掉,模型本身不需要额外组件,这也是为什么它能迅速普及。

3.2 为什么指导权重过高会导致过饱和

从概率视角看,CFG本质上是在放大条件信息相对于无条件信息的差异,拉高样本在条件分布下的似然。但高似然区域并不总是“视觉上最好看”的区域,它往往对应着数据分布的峰值附近,而分布峰值处的样本倾向于更集中、更“平均”,颜色也会朝中心位置靠拢,于是画面发灰、对比度下降。更直接的解释是,外推系数拉大时,每一步的方向被过度放大,导致更新步长过大,轨迹绕过了数据流形而落在不自然的区域。

实际现象就是:细节被过度强调,局部纹理出现网格状伪影,颜色饱和度过高,甚至边缘出现光晕。很多人第一次调高CFG时都以为模型坏了,其实只是引导强度超出合理区间。经验上,文本生成图像任务里 (s) 在4到8之间比较常用,超过10基本都会出现明显劣化。但具体最优值要看模型训练时的条件丢弃比例,适当调低丢弃比例可以减轻CFG对外推的依赖。

3.3 动态调整指导强度的工程技巧

固定权重虽然简单,但在有些场景效果不够好。我刚接触CFG时候也踩过坑——直接全局拉高,结果前景过去了,背景却糊成一片。后来试了动态调整策略:在前几步用较高指导强度快速确定主体结构和内容,后面逐步降低强度,给细节生成更多自由空间,避免细节被“过度矫正”。还有一种分段策略,对前景区域和背景区域分别控制条件强度,适合做可控构图。这类方案没有统一标准,本质都是让模型“该听话时听话,该自由时自由”。

4. 潜在空间扩散与条件注入:架构如何决定模型的能力边界

扩散模型直接在高分辨率像素空间运行成本极高,一张512甚至1024分辨率的图片,每次前向推理的计算量都相当可观。潜在扩散模型的核心思想是:先用一个自编码器把图片压缩到低维潜在空间,在这个紧凑空间里做扩散去噪,最后再解码回像素空间。

4.1 为什么在低维空间里做扩散反而更好

关键在于感知压缩。自然图片中有大量信息对人类感知来说是冗余的,比如纹理细节里的高频噪声、像素间的微小相关性。自编码器把这些冗余信息剥离掉,只保留语义层面的紧凑表示,扩散模型只需要学会生成这个低维表示即可。这样既极大降低了计算量,又能保持生成质量。另一个好处是,模型在潜在空间中建模的是“抽象结构”,生成结果自然会更稳定,不易陷入像素级别的局部震荡。

当然潜在空间也有代价:自编码器的压缩能力成了整个系统的上限。如果编码器把重要细节压丢了,无论扩散部分多强大都补不回来。所以潜在扩散系统的第一个瓶颈往往不是U-Net,而是那个看起来默默无闻的自编码器。在实践中,同样的结构,用更强的自编码器能带来肉眼可见的清晰度提升。

4.2 条件信息如何注入:交叉注意力与拼接

有了潜在空间,还需要回答一个关键问题:条件信息怎么进入生成过程?不同条件类型有不同注入方式。文本、标签这类全局条件最常用的是交叉注意力层,U-Net在某个特征尺度上把文本嵌入作为Key和Value,图像特征作为Query,让模型在生成时“按需查阅”条件信息。空间类条件(比如粗略的语义分割图、线稿)则通常在输入层面做通道拼接,让模型从第一步就看到空间约束。时间嵌入则通过仿射变换注入到每个残差块里。这套组合机制的演化,几乎定义了条件扩散模型的上限。

值得注意的是,条件注入位置不一定是越早越好。早期或全局注入会强烈约束轨迹方向,适合强控制场景;后期深入注入更好保留细节自由度。多个条件的组合则需要考虑相互间的平衡,否则容易出现某个条件主导、另一个条件被忽略的问题。

4.3 潜在空间的先天偏向与边界效应

潜在空间是经过压缩和量化训练的,它有自己的统计偏向。不同数据域压缩出来的潜在分布差异很大,所以在某个数据集上训练好的潜在扩散模型,直接迁移到另一类完全不同的数据上,效果往往不如预期。另一个实际问题是,潜在表示经过解码器上采样到像素空间时,边界区域容易出现不自然的重复纹理或拼接痕迹。这些问题很难靠调参完全消除,往往需要通过后处理或改进自编码器结构来缓解。

5. 条件控制与可编辑性扩展:从一句提示词到像素级约束

文本条件能控制“画什么”,但控制粒度比较粗。你很难用一句提示词精确指定“人物的手要放在膝盖上”或者“背景里的墙必须是砖红色”。所以在扩散模型之上,又延伸出一系列更细粒度的条件控制方案,这些方案共同构成了“让生成结果真正可控”的能力拼图。

5.1 可训练副本与零卷积的思路

一类主流方案是给模型增加一个可训练的旁路结构,在保留原始权重的前提下,让某些外部条件“介入”生成过程。具体做法是:复制一份模型主干作为可训练分支,外部条件先经过这个分支提取引导特征,再通过一个初始化为零的卷积层把信号融合回主干。零卷积的关键在于,训练初期融合信号的系数为零,模型行为与未加入条件时完全一致,相当于先保护了原始生成能力,再逐步学习条件带来的改变。这个方法让模型能够被精确地控制姿态、边缘或深度结构,却不需要重训整个大模型。

这种“旁路微调”的思想还延伸出了很多变体,比如在某些特定层插入低秩矩阵来实现风格或概念定制。低秩方法的学习参数量很小,训练速度快,在小样本场景下效果尤其好。它们和条件控制的关系是互补的:条件控制管“位置和结构”,低秩微调管“特定的风格或对象”。

5.2 多条件冲突与融合策略

实际使用中经常要同时输入多个条件,比如既要线稿约束结构,又要文本指定内容,还有额外参考图指定色调。条件之间的冲突几乎无法避免。文字说“穿红衣服”,线稿画的是裙装,模型就要自己“协调”。通常的融合方式是按通道拼接或加权相加,不同条件使用不同权重。但权重设置没有万能公式,我的经验是优先保证空间类条件(因为它直接决定构图),再平衡文本条件和参考图条件的权重,必要时对不同条件在不同时间步上的影响范围做切割。早期时间步偏重文本,中后期保留更多空间细节约束,效果往往比全程权重一致更自然。

6. 训练稳定性与部署避坑:从论文里的模型到线上可用的系统

最后一个模块聊工程。很多人自己训练过一个扩散模型之后会感叹:论文里的训练目标看起来简单,真正训练起来却全是幺蛾子。损失曲线不降、生成样本全是噪声、训练中期突然模型崩溃,这些都是常见问题。这背后有明确的机制原因,也有长期积累的工程经验。

6.1 指数移动平均与学习率调度的细节

扩散模型训练对优化器的稳定性要求非常高。一个被验证非常有效的做法是维护一组模型权重的指数移动平均(EMA),用EMA权重做评估和推理。原因是训练后期模型在损失景观底部来回跳动,EMA相当于对多个历史状态做了平滑,最终的权重往往比当前权重更稳。EMA衰减率的设置也很有讲究,通常在0.999到0.9999之间,衰减越大,平滑越强,但跟随训练进度的滞后也越大。

学习率调度同样值得注意。我在早期实验里吃过亏:损失已经降到很低,但生成效果却差,我怀疑是学习率衰减太快导致模型卡在局部状态。后来改成线性预热加余弦退火,并把峰值学习率控制在一个较小区间,生成质量才明显改善。扩散模型不像某些分类任务那样能吃很高的学习率,谨慎一点更稳妥。

6.2 显存优化与训练速度的取舍

训练扩散模型最直接的障碍是显存。常见优化手段包括混合精度训练、梯度检查点、以及在潜在空间训练。梯度检查点以少量重计算换显存,可以节省不少空间,但会增加训练时间。混合精度则是性价比最高的优化方式,几乎不影响最终效果,还能提速。

推理阶段的显存压力不亚于训练。批量生成时,要在批量大小和单张分辨率之间做取舍。一个实用技巧是分阶段生成:先低分辨率快速确定构图,再做局部高分辨率放大优化,而不是一次直接生成超大图。既能省显存,又能在关键区域获得更好的细节。

6.3 部署时容易被忽略的模型一致性问题

模型从训练到部署有一个容易被忽略的坑:训练时的数值精度、采样器版本、条件输入格式,与部署环境不一致,会导致生成结果发生偏移。比如训练时文本编码器是某一种预训练权重,部署时换了版本,生成质量会肉眼可见地下降。我的建议是,训练和部署尽量锁定同一套预处理逻辑和权重版本,任何改动都要回归跑一遍标准测试集。代码层面则要注意随机种子、算子确定性问题,不同硬件或框架版本之间,同一模型的结果可能不完全一样。如果业务对结果一致性要求高,这一点必须提前做好验证。


这套体系我在实际项目里反复验证过,最大的体会是:扩散模型的每一步设计,几乎都建立在“用更多计算换取更好的分布刻画”这个权衡上。训练简化是为了稳,采样器加速是为了省算力,CFG是为了可控,潜在空间是为了能规模化,旁路控制是为了细粒度干预,工程技巧则是把这一切安全落地。下次遇到生成效果不理想,先不要盲目堆步数或调大指导权重,按这条链路的顺序逐步排查,很多问题其实出在那些不起眼的机制选择上。这是我在一次次跑模型、一次次翻车之后形成的排查习惯,希望对你也同样有效。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进