先说一个我踩过的坑。前几年第一次读到扩散模型的论文时我下意识把它当成了一个“加了马尔可夫链的变分自编码器”对着损失函数推了半天公式能看懂但那种“为什么会work”的直觉始终没建立起来。真正让我豁然开朗的反而是翻回大学物理课本的那几天——因为这个东西的骨架几乎就是九十年代非平衡态统计物理里研究过的那套东西一个系统被加热到无序然后我们想办法让它沿着时间的反方向冷却回来每一步都要求我们知道当下的“驱动力”指向哪里。用物理学视角讲解diffusion生成模型尤其是讲到隐扩散模型这一层物理类比不是为了装深刻而是它能一次性把几个绕人的问题讲通为什么前向必须加高斯噪声、为什么反向只需要学“分数函数”而不需要学整个分布、为什么可以把扩散搬到低维潜空间去做而不损失太多东西。我把这篇当成一次完整的工程复盘来写。前半段是原理向的拆解后半段是实打实的训练与采样细节包括噪声调度怎么选、潜空间压缩率怎么定、无分类器引导的系数为什么不能开太大还有我自己在调隐扩散模型时遇到过的那些“loss曲线看着很健康但采样出来一团糊”的怪事。不管你是刚接触生成模型想建立直观理解的新手还是已经跑通过几个开源实现、但对他山之石背后的取舍逻辑没细想过的人应该都能从中拿到点东西。1. 先把扩散模型当成一个物理系统来看1.1 从墨水扩散到高斯加噪同一个数学骨架一滴墨水滴进静止的水里最初是一个浓度极高的点分布随着时间推移墨迹摊开、变淡最后均匀分布在整个容器里。这个过程的宏观描述就是Fick 扩散定律浓度通量正比于浓度梯度写成方程是 $\partial_t p D \nabla^2 p$其中 $D$ 是扩散系数。这个方程有一个漂亮的性质如果初始浓度是一个点源它的解就是一个随时间展宽的高斯分布方差等于 $2Dt$。换句话说扩散过程会把任意一个初始分布逐步磨成越来越宽的高斯分布。现在把“浓度”换成“数据分布”“分子”换成“样本点”。前向扩散做的事情就是给定一张真实的图像 $x_0$我们按照一条预先设定好的时间表一遍一遍地往上加独立的高斯噪声。第 $t$ 步之后得到$$x_t \sqrt{\bar\alpha_t}, x_0 \sqrt{1-\bar\alpha_t}, \epsilon,\qquad \epsilon \sim \mathcal{N}(0, I)$$这里的 $\bar\alpha_t$ 是累积的“信号保留率”。当 $t$ 走到终点$\bar\alpha_T \to 0$$x_T$ 就变成纯噪声一个标准正态分布。这在物理上对应的正是墨水彻底混匀的状态——系统进入了热平衡所有关于初始状态的结构信息都被热噪声抹平了。我喜欢这个类比是因为它把“为什么用高斯噪声”这个常见疑问顺手解决了。不是因为高斯好看而是因为扩散方程的格林函数就是高斯的。你如果换成一个拉普拉斯噪声、均匀噪声前向过程就不再对应一个良定义的扩散方程反向过程的分母也会变得很难处理。加高斯是让整个系统满足一个已知可解的物理定律。顺带说一句上面这个离散递推式正是方差保持型随机微分方程VP-SDE的欧拉离散化$dx -\tfrac{1}{2}\beta(t) x, dt \sqrt{\beta(t)}, dw$。那个 $-\tfrac12 \beta x$ 的漂移项不是随便加的它的作用是持续把信号往原点收缩保证 $x_t$ 的方差始终有界不会像纯随机游走那样方差线性爆炸。物理学里这叫Ornstein–Uhlenbeck 过程描述的是带阻尼的布朗粒子。1.2 温度、熵与“热寂”目标分布如果把 $1-\bar\alpha_t$ 理解成一个随时间单调上升的有效温度那么前向过程就是一条从冷到热的升温曲线。$t$ 小的时候温度低样本还保留着数据的结构$t$ 大的时候温度高结构被热涨落彻底淹没只剩下各向同性的高斯噪声。这条升温曲线带来一个重要的工程后果高噪声段的时间步其信息量极低但数量很多。如果你按均匀步长训练模型会把大量算力浪费在“预测几乎纯噪声里的噪声”这种简单任务上而真正需要精细学习的中低噪声段反而采样不足。这就是后来各种时间步重要性采样、基于信噪比的重加权的动机来源。我在早期一个玩具项目里没做这个处理结果模型在大 $t$ 段的重建损失压得极低看起来非常健康但采样出来的东西细节全是模糊的——因为模型根本没有在关键的“中等噪声”区间获得足够的梯度信号。还有一个物理概念值得拎出来熵。数据分布是有结构的熵较低高斯分布是给定方差下熵最大的分布。前向扩散是一个熵单调增加的过程最终到达最大熵状态。生成模型要做的是让这个熵增加的过程可逆——我们不是违反热力学第二定律而是额外注入了“关于数据分布的知识”用模型参数把这个过程反向驱动回去。这一点必须说清楚否则很容易产生“扩散模型是永动机”的错觉。1.3 反向过程为什么是“逆着时间走的热力学”严格来说一个扩散过程的逆向过程本身仍然是一个扩散过程只不过漂移项需要修正。对 VP-SDE 而言反向时间 SDE 写出来是$$dx \Big[-\tfrac{1}{2}\beta(t)x - \beta(t)\nabla_x \log p_t(x)\Big]dt \sqrt{\beta(t)}, d\bar w$$对比前向你会发现两处变化漂移项多了一个 $-\beta(t)\nabla_x \log p_t(x)$噪声项前面的符号变了时间在倒流。这个多出来的项就是整个生成模型的灵魂。它有一个非常物理的名字漂移的修正项。想象一个布朗粒子在势场里运动普通的扩散只会让它往低浓度区域跑但如果我们希望它逆着浓度梯度“爬坡”就必须额外施加一个力这个力正比于概率密度的对数梯度。工程上这意味着什么意味着我们不需要学习整个数据分布 $p(x)$只需要学习一个向量场 $\nabla_x \log p_t(x)$——它在每个位置、每个时刻指向“概率密度上升最快的方向”。这比学习一个归一化的概率分布容易太多了因为不用管配分函数归一化常数而配分函数在物理系统里往往是最难算的东西。这是我认为物理学视角最有解释力的一处。从“学分布”降级为“学力场”任务难度直接下降一个量级。2. 分数函数物理学里的“力”也是生成模型的方向盘2.1 能量、玻尔兹曼分布与分数的物理含义在统计物理里一个系统处于状态 $x$ 的概率由玻尔兹曼分布给出$p(x) \propto e^{-E(x)/kT}$其中 $E(x)$ 是能量$T$ 是温度$k$ 是常数。两边取对数再求梯度$$\nabla_x \log p(x) -\frac{1}{kT}\nabla_x E(x)$$右边是什么是力的负值力是能量梯度的负方向。所以分数函数 $\nabla_x \log p(x)$ 在物理上就是“把粒子推向高概率区域的力除以温度”。温度越高同样的能量地形粒子受到的有效引导越弱温度越低粒子越“死心塌地”地往能量谷底掉。这个图像一旦建立扩散模型的采样过程就变得非常直观了你在一个崎岖的能量地形上撒了一把粒子然后让温度和噪声逐步降低粒子会沿着力的方向滚进那些深谷——每一个深谷就对应一张合理的、高概率的图像。早期 $t$ 大、温度高粒子大范围游走决定“大概长什么样”的全局结构后期 $t$ 小、温度低粒子只能在局部微调决定纹理和细节。这个从粗到细的生成顺序不是设计者刻意加的是退火过程的自然涌现。这也是为什么扩散模型生成的图像往往是先有轮廓再有细节和自回归模型从左到右逐像素生成的方式有本质区别。2.2 朗之万采样把噪声当成热扰动有了力场最直接的采样办法就是朗之万动力学$$x_{k1} x_k \eta \nabla_x \log p(x_k) \sqrt{2\eta}, z_k,\qquad z_k\sim\mathcal{N}(0,I)$$三步沿力走一小步加上一点热噪声重复。这是一个离散时间的过阻尼朗之万方程。它的稳态分布恰好就是 $p(x)$这是很经典的结果。扩散模型早期的“去噪分数匹配”采样本质上就是这个式子在各个噪声等级上依次执行。你现在看到的很多采样器名字剥开外面那层包装内核都是朗之万动力学的变体或者它的确定性极限。这里有个实操细节值得说$\eta$ 的选取不是越小越好。太小粒子走不动采样需要几百上千步太大粒子会跳过能量谷产生所谓的“离散化误差”表现为图像出现奇怪的伪影或者颜色偏移。我在一个低分辨率实验里尝试把 $\eta$ 放大 2 倍来省步数结果生成的样本在高频区域出现明显的棋盘格噪声——这正是数值积分步长过大、粒子来回震荡的典型症状。2.3 从朗之万到概率流ODE确定性轨迹随机采样有个毛病同一个随机种子只能出一个结果而且步数少了容易飘。所以后来有了概率流 ODE的写法$$\frac{dx}{dt} f(x,t) - \frac{1}{2}g(t)^2 \nabla_x \log p_t(x)$$去掉了随机项只保留漂移。它和对应的 SDE 共享同一族边缘分布但轨迹是确定的。物理上这相当于从“布朗运动”切换到“沿流线运动”你不再让粒子被热噪声撞来撞去而是直接沿着概率流的速度场走。这个切换带来的最大好处是可以用高阶数值积分器比如二阶、三阶的 Runge–Kutta 变体在 20 到 50 步内就收敛得不错而随机采样通常需要几百步。代价是失去了随机性带来的多样性——但如果你只是想要一张好图这恰恰是优点。实际部署里我基本默认用确定性采样器出图只有在需要批量生成多样化候选、或者做图像编辑类任务时才切回随机版本。3. 噪声调度一条物理意义上的降温曲线3.1 β、ᾱ 与信噪比的关系推导前面一直用 $\bar\alpha_t$但工程实现里你面对的是 $\beta_t$ 这个序列。三个量的关系很朴素$$\alpha_t 1 - \beta_t,\qquad \bar\alpha_t \prod_{i1}^{t}\alpha_i$$$\beta_t$ 是每一步注入的噪声比例$\bar\alpha_t$ 是累积后的信号保留率。真正决定“这个时间步有多难”的是信噪比$$\mathrm{SNR}(t) \frac{\bar\alpha_t}{1-\bar\alpha_t}$$注意这个式子的来源$x_t$ 里信号分量的方差是 $\bar\alpha_t$噪声分量的方差是 $1-\bar\alpha_t$两者之比就是信噪比。它是单调递减的$t0$ 时是无穷大$tT$ 时接近 0。我习惯在开始训练前画一张 $\log \mathrm{SNR}(t)$ 随 $t$ 变化的曲线图。这张图能直接告诉你两件事第一你的调度在前半段是不是下降得太快导致中段几乎没剩多少信噪比可用第二最后一个时间步的信噪比是否足够接近于零如果不够说明前向过程没走到底训练目标和真实采样起点不一致采样第一步就会崩。3.2 线性、余弦、余弦偏移的取舍早期的线性调度$\beta$ 从 $10^{-4}$ 线性增到 $0.02$有个明显缺陷信噪比在两端下降太快中段几乎是断崖式的。后果是模型在信息最丰富的中间噪声段训练样本非常稀疏。余弦调度就是为了修这个问题它让 $\bar\alpha_t$ 按照余弦函数平滑衰减使得信噪比在整个时间轴上下降得更加均匀。我做过一个对比实验在相同的训练步数下余弦调度的模型在中低噪声区域的重建误差明显更低生成图像的纹理也更自然。下面这张表是我在实际项目里总结的不同调度的观感对比供参考调度类型信噪比曲线特征训练稳定性典型副作用适用场景线性 β两端陡、中段窄中等中间噪声段欠拟合纹理发糊快速验证、低分辨率玩具实验余弦全程较均匀好极低噪声段步长偏密浪费少量算力通用图像生成最稳妥的默认值余弦偏移可调偏置好偏移量选错会导致高噪段欠采样需要控制生成亮度/对比度分布时信噪比截断人为砍掉两端好端点不匹配需同步调整采样器追求极少步数的蒸馏场景表里最后一行值得多说一句。所谓“信噪比截断”是把训练和采样的时间范围都限制在 $\mathrm{SNR}\in[\text{下限}, \text{上限}]$ 之间跳过那些“太简单”和“太无意义”的区间。这能显著降低训练成本但你必须保证训练端和采样端用同一套截断否则就会出现“训练时模型从没见过这个噪声水平采样却让它从这开始”的错配。3.3 时间步重采样与“非均匀散热”前面提过均匀采样的问题。更细一点说扩散模型的训练损失在不同噪声段上的梯度尺度是不一样的。高噪声段模型要预测的噪声幅度接近 1损失量级大低噪声段噪声很小损失量级也小。如果你直接对所有时间步取平均梯度会被高噪声段主导。解决办法有两类。一类是重要性采样按损失的反比来确定采样概率让难学的段被采得更多。另一类是损失加权给不同噪声段的损失乘上不同权重把梯度尺度拉平。我个人的经验是如果你的数据集规模在十万级以下重要性采样能带来比较明显的收益如果已经到百万级以上收益会被大数据量本身稀释不如把精力放在调度曲线的形状上。这跟物理里“样本量足够大时涨落被平均掉”是一个道理。4. 从像素空间到潜空间为什么要做“粗粒化”4.1 感知压缩与流形假设到这一步我们有一个完整可行的扩散模型了但它有个致命的工程问题太贵。一张 $512\times512$ 的三通道图像展开是 78 万维。在这个维度上做扩散每一次前向都要过一个参数量不小的网络每一步采样都要重复一次。一千步采样普通消费级显卡根本扛不住。更关键的是这 78 万维里存在大量冗余。自然图像并不是均匀散布在整个像素空间里的它们集中在一个低维流形附近——相邻像素高度相关大片区域内颜色平滑过渡。用信息论的话说一张自然图像的有效自由度远低于像素总数。这就是感知压缩的出发点既然数据本来就在低维流形上那我们先用一个自编码器把它压到一个更紧致的表示里然后在那个表示上做扩散。这个压缩后的空间就是潜空间在上面做扩散的模型就是隐扩散模型。物理上这个过程可以类比为粗粒化。就像描述一杯水的状态你不需要追踪每一个水分子的位置速度那是 $10^{23}$ 维的相空间只需要几个宏观变量温度、压强、密度。粗粒化丢掉的确实是一些微观信息但只要这些信息对宏观行为不重要描述就是有效的。4.2 潜空间扩散相当于什么物理过程再往深一层想。重整化群理论里有一个核心思想当你把系统在更粗的尺度上观察时微观细节被积分掉剩下的是一套有效场论——方程的形式往往不变只是参数被重新标定了。隐扩散模型做的事情和这个是高度同构的。像素空间扩散研究的是 $p(x)$潜空间扩散研究的是 $p(z)$其中 $z \mathcal{E}(x)$。两者都用一个形式相同的扩散过程来描述一个在原始空间一个在“粗粒化后的观测尺度”上。换句话说你把扩散过程搬到潜空间不是引入了一个近似而是换了一个观测尺度。这个视角有个直接的实用推论潜空间的压缩率越高你换的尺度就越粗丢掉的细节就越多。当压缩率到某个临界点以下那些和低频结构无关的细节小字号文字、细密的织物纹理、眼睛里的高光形状就开始丢失因为它们在粗粒化过程中已经和周围的像素混在一起了。我在一个项目里就吃过这个亏。当时为了省显存把空间下采样倍数从 8 提到 16训练速度确实快了但生成的图里所有的小字全部糊成马赛克人脸在远景下五官会粘连。这不是扩散模型的问题是自编码器在粗尺度上重建能力不够扩散模型再强也补不回来。4.3 压缩率怎么定算一笔账不同压缩率带来的差异有多大我给一组典型的量级参考输入尺寸三通道潜空间尺寸潜变量元素数相对计算量粗估观感512×512×364×64×4163841.0基准细节完整文字可辨512×512×332×32×44096约 0.25纹理略软小字开始出问题512×512×3128×128×465536约 4.0细节更锐成本明显上升512×512×3512×512×3无压缩786432约 48细节最好训练基本不现实表里的“相对计算量”是个粗略估计。真实情况更复杂扩散网络的注意力层开销随序列长度是二次增长所以压缩率的收益主要体现在注意力部分卷积部分则是线性于空间面积的。我的经验是在 64×64 这个量级上空间压缩倍数取 8 是一个相当好的平衡点——再往下压感知质量掉得很快再往上提收益递减而成本陡增。还有一个实操要点潜变量的数值范围要归一化。常见的做法是统计训练集上潜变量的标准差用一个接近 0.2 量级的缩放因子把它拉到单位方差附近再送进扩散网络。这个常数千万不能随手写我第一次就照抄了别人的配置结果因为自编码器训练方式不同标准差差了将近一倍导致网络的输入分布不匹配训练 loss 从 0.1 起步怎么调学习率都压不下去。5. 隐扩散模型的实操骨架5.1 两段式训练流程隐扩散的训练必须严格分两段不能合并成一个端到端任务。第一段训练自编码器。目标是重建目标函数是重建损失感知损失和对抗损失的加权组合在很多实现里都会加用来提升高频细节的还原度加上一个把潜变量往标准正态分布拉的正则项。正则项强度是个关键旋钮太弱潜空间方差大、结构松散扩散模型学起来费劲太强潜变量的信息容量被压缩重建质量下降。我习惯从较小的正则强度起步观察重建误差和潜变量统计量逐步往上加找到“潜变量接近标准正态但重建还清晰”的位置。第二段冻结自编码器在潜空间训练扩散网络。输入是 $z_0\mathcal{E}(x)$按调度加噪网络预测噪声或速度场。这一步的训练时长通常比第一段高一个数量级所以自编码器一旦确认就应该冻结不要反复动它——动了就得重训扩散代价太大。提示自编码器一旦冻结它的输入归一化常数就固定了。如果你后面换了数据集要重新统计潜变量的均值方差否则扩散网络看到的输入分布会偏移务必写进训练脚本的检查项里。5.2 关键代码片段下面是前向加噪和时间步调度的最小实现我习惯把它写成纯函数方便做单元测试import torch, math def cosine_alphas_bar(T1000, s0.008): 余弦调度直接给出累积信号保留率 steps torch.arange(T 1, dtypetorch.float64) f torch.cos(((steps / T) s) / (1 s) * math.pi / 2) ** 2 abar f / f[0] return abar.clamp(1e-8, 1.0) # 形状 (T1,) def forward_diffuse(x0, t, abar, epsNone): 单步加噪x_t sqrt(abar)*x0 sqrt(1-abar)*eps if eps is None: eps torch.randn_like(x0) a abar[t].view(-1, 1, 1, 1) # 广播到 (B,C,H,W) return a.sqrt() * x0 (1 - a).sqrt() * eps, eps注意这里我用的是 float64 计算调度系数——因为累积连乘非常容易在数值上出问题用低精度算到后期 $\bar\alpha$ 会直接掉到 1e-10 以下$1-\bar\alpha$ 相对精度崩掉。这个细节不值得省那点内存。时间步嵌入需要一个能把标量 $t$ 映射成高维向量的函数最常用的是正弦位置编码def timestep_embedding(t, dim, max_period10000): half dim // 2 freqs torch.exp(-math.log(max_period) * torch.arange(half, dtypetorch.float32) / half) args t.float()[:, None] * freqs[None] return torch.cat([torch.cos(args), torch.sin(args)], dim-1)它的物理意义很直接给网络一个“当前处于什么温度”的编码。用正弦而不是 one-hot是因为从 $t$ 到 $t1$ 的变化应该是连续的——相邻温度下的力场应该相似这个连续性对训练稳定性有帮助。推理时的确定性采样更新式DDIM 形式是torch.no_grad() def ddim_sample(model, abar, shape, steps50, eta0.0, cfg1.0): T len(abar) ts torch.linspace(T - 1, 0, steps 1).long() x torch.randn(shape) for i in range(steps): t_cur, t_prev ts[i], ts[i 1] e model(x, t_cur) if cfg ! 1.0: e_u model(x, t_cur) # 无条件分支 e e_u cfg * (e - e_u) # 外推 x0 (x - (1 - abar[t_cur]).sqrt() * e) / abar[t_cur].sqrt() x0 x0.clamp(-4, 4) # 抑制外推发散 x abar[t_prev].sqrt() * x0 (1 - abar[t_prev]).sqrt() * e return x上面那个cfg分支在实际实现里通常是一次前向带两路输入有条件、无条件拼成一个 batch不是跑两遍网络我这里为了可读性拆开了。另外x0的裁剪范围不要写死太大否则等于没裁写太小会把正常的高对比区域也削掉4 个标准差左右是常见量级具体要看你潜变量的归一化尺度。5.3 无分类器引导的物理直觉无分类器引导classifier-free guidance的公式是$$\hat\epsilon \epsilon_\theta(x_t,\varnothing) w\big(\epsilon_\theta(x_t,c) - \epsilon_\theta(x_t,\varnothing)\big)$$一个常见的误解是把它当成“加强条件信号”。用物理语言讲更准确这是在条件方向上加了一个外推偏置场。$w1$ 时是标准条件采样$w1$ 时你把样本沿着“条件与非条件之间的差异方向”往外推推向更典型、条件特征更鲜明的区域。问题在于这个外推是在分布的尾部操作的。当 $w$ 大到一定程度样本会被推到数据流形之外落到模型从未见过的区域表现为过饱和、边缘出现硬边、颜色失真、人脸变成塑料质感。这跟物理里把一个粒子推出势垒的行为很像能量地形之外没有力学约束粒子就乱飘了。我的经验值$w$ 在 5 到 8 之间是甜区超过 12 基本都会看到明显的质感劣化。少数场景比如需要极强风格的插画可以上到 10 左右但要配合降低采样步长来抑制伪影这实际上是在用数值离散化误差去掩盖外推误差属于权宜之计别当常规手段用。5.4 训练循环与资源估算完整的训练循环结构不复杂但几个配置项的经验值值得记一下学习率在 $10^{-4}$ 量级配合余弦学习率衰减和大约 5000 步的线性预热批量大小在单卡显存允许的前提下尽量大梯度累积可以补但批归一化相关的层要看清楚是否用的是无批依赖的归一化扩散网络里通常用组归一化或者层归一化否则小批量下统计量不稳会直接毁掉训练。资源估算可以这么粗算以 64×64×4 的潜变量、约 8 亿参数的扩散网络为例单次前向加上反向的显存占用大致在十几 GB 量级一张 24 GB 显存的卡可以在 $\text{bs}8$ 到 $16$ 之间跑训练步数通常在十万到数十万量级多卡并行的话几天到一周能收敛到一个可用状态。这个数字浮动很大主要取决于网络宽度和下采样层数仅供参考。推理侧的压力比训练小得多但也别忽略采样步数带来的线性开销50 步采样就是 50 次网络前向启用引导还要乘以 2如果单张图要 3 秒批量生成一千张就是接近两小时。这也是为什么蒸馏加速、步数压缩这类工作一直很热门——它直接决定了产品的可用性。6. 实测踩坑与排查速查表6.1 典型现象对照表下面这些症状我在不同项目里基本都遇到过整理成一张表方便对照排查症状表现可能原因排查手法处理方向loss 正常下降采样全是灰雾潜变量归一化常数错输入分布偏移统计训练集潜变量的均值方差与配置比对重算缩放因子重训或至少重跑验证高对比区域出现棋盘格采样步长过大ODE 离散化误差把步数翻倍看伪影是否消失提步数或换高阶积分器小字、细纹理必糊自编码器空间压缩率过高单独跑自编码器重建看原始细节降低压缩倍数或提升重建损失权重边缘出现硬边、颜色过饱和引导系数过大样本被推出流形把 $w$ 逐级降到 5 以下对比降低引导系数加 x0 裁剪采样第一步就崩成噪声块训练端与采样端时间步范围不匹配检查是否对两端做了信噪比截断且保持一致对齐训练与采样端点生成结果多样性差、几乎雷同用确定性采样器且种子固定换随机采样器或批量内多种子按需切换采样器类型某些类别一直学不好数据长尾该类别样本过少分类统计样本分布重采样加权或补数据6.2 三条我认为最值钱的经验第一条永远先单独验证自编码器。隐扩散出问题时问题往往不在扩散本身。做法很简单拿一批真实图像过一遍编码解码人眼看重建结果。如果重建就已经糊了、色偏了后面所有调参都是徒劳。我现在的流程是自编码器不通过人眼验收绝不进入扩散训练。这一步看着笨但省下来的时间远超投入。第二条把 $\log \mathrm{SNR}$ 曲线当成第一诊断工具。无论是训练不收敛还是采样效果差先画这张图。它能一眼看出你的调度是不是在某个区间留了“空洞”。很多所谓“模型能力不足”的问题本质是那个噪声段采样密度太低模型没有足够的梯度去学。注意不同分辨率、不同压缩率下最优的调度曲线形状是不一样的。别把 512 分辨率上调好的配置直接搬到 1024中段信噪比会整体偏移需要重新扫一遍。第三条引导系数和采样步数是耦合的别分开调。我见过不少人把引导系数调到 15 追求“强条件”然后靠加步数去压伪影结果是既慢又难看。正确的顺序是先固定一个中等步数比如 30把引导系数扫到伪影刚好不出现的临界点然后再在临界点附近微调步数。这个顺序能把搜索空间砍掉一大半。最后分享一个小技巧。如果你在隐空间里想做一些约束比如让生成结果的整体色调往某个方向偏别直接去改采样轨迹加惩罚项——那会破坏轨迹的物理一致性容易产生结构性伪影。更稳的做法是在自编码器的潜空间里做线性插值或者方向偏移因为潜空间本身是连续的、结构良好的微小的线性扰动解码回来往往是自然的渐变。这个思路本质上和物理里“在慢变量上做微扰快变量会自动跟随”是一个道理实测下来很稳。