编辑
2025-04-11
深度学习
00

目录

Stable Diffusion WebUI 噪声采样的调度器的原理
1. 噪声调度器基础概念
2. Automatic (自动)
3. Uniform (均匀)
4. Karras
数学公式
5. Exponential (指数)
数学公式
6. Polyexponential (多项式指数)
数学公式
7. SGM Uniform (SGM均匀)
8. 调度器的选择与影响
调度器选择建议
调度器对最终图像的影响
9. 调度器原理与噪声水平的重要性
为什么噪声调度很重要
时间步长与数值精度
10. 自定义调度器参数的影响
sigmamin 和 sigmamax
rho 参数(Karras 和 Polyexponential)
11. 调度器代码实现的技术细节
零点附加
内部模型依赖
总结

Stable Diffusion WebUI 噪声采样的调度器的原理

噪声调度器(Noise Schedulers)是扩散模型生成过程中的关键组件,它们决定了扩散过程中噪声水平如何随时间变化。合适的噪声调度可以显著提高生成质量和效率。我将详细解析 SD WebUI 中的各种调度器,包括其数学原理和具体实现。

1. 噪声调度器基础概念

在扩散模型中,噪声调度器定义了 σ (sigma) 值如何从高噪声水平逐渐降低到低噪声水平。这些 σ 值构成了采样过程中的离散步骤。

首先让我们查看 SD WebUI 中的调度器代码实现:

Read file: modules/sd_schedulers.py

Read file: repositories/k-diffusion/k_diffusion/sampling.py

2. Automatic (自动)

Automatic 调度器不是一个实际的调度器,而是让系统基于当前选择的采样器自动选择最合适的调度器。

python
Scheduler('automatic', 'Automatic', None)

例如,当你使用DPM++ 2M采样器时,它默认会使用Karras调度器,因为这是该采样器的推荐调度器。

3. Uniform (均匀)

Uniform调度器使用模型内置的均匀间隔噪声调度,通常是线性间隔的噪声水平。

python
def uniform(n, sigma_min, sigma_max, inner_model, device): return inner_model.get_sigmas(n)

它直接从内部模型获取均匀分布的噪声水平,不考虑给定的 sigma_minsigma_max

这种调度的特点是简单直接,但对于许多采样器来说并不是最优的选择,尤其是在较少步数的情况下。

4. Karras

Karras调度器来自Karras等人在2022年的论文,是目前最广泛使用的调度器之一,尤其适合DPM系列采样器。

python
def get_sigmas_karras(n, sigma_min, sigma_max, rho=7., device='cpu'): """Constructs the noise schedule of Karras et al. (2022).""" ramp = torch.linspace(0, 1, n) min_inv_rho = sigma_min ** (1 / rho) max_inv_rho = sigma_max ** (1 / rho) sigmas = (max_inv_rho + ramp * (min_inv_rho - max_inv_rho)) ** rho return append_zero(sigmas).to(device)

数学公式

σ(t)=(σmax1/ρ+t(σmin1/ρσmax1/ρ))ρ\sigma(t) = \left( \sigma_{\max}^{1/\rho} + t \cdot (\sigma_{\min}^{1/\rho} - \sigma_{\max}^{1/\rho}) \right)^{\rho}

其中:

  • tt 是从0到1的归一化时间
  • ρ\rho 是控制曲线形状的参数,默认值为7
  • σmin\sigma_{\min}σmax\sigma_{\max} 是噪声范围

Karras调度器的特点是在高噪声区域分配更多步骤,在低噪声区域分配较少步骤,这与生成过程中最需要精确控制的区域相匹配。它显著提高了低步数采样的质量。

5. Exponential (指数)

指数调度器在对数空间中线性安排噪声水平,使噪声按指数衰减。

python
def get_sigmas_exponential(n, sigma_min, sigma_max, device='cpu'): """Constructs an exponential noise schedule.""" sigmas = torch.linspace(math.log(sigma_max), math.log(sigma_min), n, device=device).exp() return append_zero(sigmas)

数学公式

σ(t)=exp(log(σmax)+t(log(σmin)log(σmax)))\sigma(t) = \exp\left( \log(\sigma_{\max}) + t \cdot (\log(\sigma_{\min}) - \log(\sigma_{\max})) \right)

其中 tt 从0到1线性变化。

指数调度器在高噪声区域提供稍快的初始去噪,然后在细节形成阶段逐渐减慢,它是一个比均匀调度更好,但比Karras调度更简单的选择。

6. Polyexponential (多项式指数)

多项式指数调度器结合了指数衰减和多项式控制,提供更灵活的噪声分布。

python
def get_sigmas_polyexponential(n, sigma_min, sigma_max, rho=1., device='cpu'): """Constructs an polynomial in log sigma noise schedule.""" ramp = torch.linspace(1, 0, n, device=device) ** rho sigmas = torch.exp(ramp * (math.log(sigma_max) - math.log(sigma_min)) + math.log(sigma_min)) return append_zero(sigmas)

数学公式

σ(t)=exp((1t)ρ(log(σmax)log(σmin))+log(σmin))\sigma(t) = \exp\left( (1-t)^{\rho} \cdot (\log(\sigma_{\max}) - \log(\sigma_{\min})) + \log(\sigma_{\min}) \right)

其中:

  • tt 从0到1线性变化
  • ρ\rho 控制多项式的幂,默认值为1

ρ=1\rho = 1 时,它与指数调度器非常相似。但当 ρ>1\rho > 1 时,它会在初始阶段分配更多步骤,使去噪过程更平滑。当 ρ<1\rho < 1 时,初始去噪更快,后期细节生成更慢。

7. SGM Uniform (SGM均匀)

SGM均匀调度器是专为SGM (Score-based Generative Models) 设计的调度器,它在t空间(而非sigma空间)均匀采样。

python
def sgm_uniform(n, sigma_min, sigma_max, inner_model, device): start = inner_model.sigma_to_t(torch.tensor(sigma_max)) end = inner_model.sigma_to_t(torch.tensor(sigma_min)) sigs = [ inner_model.t_to_sigma(ts) for ts in torch.linspace(start, end, n + 1)[:-1] ] sigs += [0.0] return torch.FloatTensor(sigs).to(device)

这个调度器首先将 sigma 值转换为 t 空间,在 t 空间中均匀采样点,然后再将这些点转换回sigma值。

这种方法特别适合某些扩散模型变体,比如来自Stability AI的SGM模型。

8. 调度器的选择与影响

调度器选择建议

  1. 默认选择:对大多数情况,使用 Automatic 让系统自动选择最合适的调度器。

  2. 高质量结果

    • 与DPM++系列采样器结合使用 Karras 调度器
    • 此组合在低步数下也有优异表现
  3. 特定模型

    • 对于SGM模型使用 SGM Uniform 调度器
    • 对于最新的SD XL模型,Karras 通常也是最佳选择
  4. 实验和微调

    • 当标准调度器结果不够理想时,尝试 Polyexponential 并调整 rho 参数
    • 较小的 rho 值(如0.5)会在生成早期进行更快去噪,适合保留大致结构
    • 较大的 rho 值(如2.0)会进行更均匀的去噪,可能产生更一致的细节

调度器对最终图像的影响

不同调度器对生成结果有显著影响:

  1. 细节和清晰度

    • Karras 调度器通常产生最清晰、最精细的细节
    • Uniform 调度器在同样步数下通常细节较少
  2. 噪点和纹理

    • 不同调度器对最终图像的纹理和噪点有不同影响
    • ExponentialPolyexponential 可能在某些纹理上表现更好
  3. 速度和步数权衡

    • 对于低步数生成(<30步),Karras 通常有最佳性能
    • 对于高步数生成(>50步),调度器之间的差异减小

9. 调度器原理与噪声水平的重要性

为什么噪声调度很重要

扩散模型的去噪过程是从高噪声状态到低噪声状态的转换。这个过程不是均匀的:

  1. 高噪声区域(早期步骤):主要确定图像的整体结构和构图
  2. 中等噪声区域:形成主要特征和大型细节
  3. 低噪声区域(后期步骤):精细细节和纹理的生成

因此,理想的噪声调度应该根据每个阶段的重要性分配步骤。这就是为什么Karras调度器在实践中表现优异 - 它在关键的噪声水平分配了更多步骤。

时间步长与数值精度

噪声调度器实质上控制着数值积分过程中的"时间步长"。较小的时间步长(在关键区域)提供更高的精度,但需要更多计算步骤。最优的调度器找到了这一权衡的良好平衡点。

10. 自定义调度器参数的影响

sigma_min 和 sigma_max

这些参数定义了噪声范围:

  • sigma_max:初始噪声的大小,较大值会产生更多样的结果,但可能降低与提示的相关性
  • sigma_min:最终噪声的大小,过小可能导致过度平滑,过大可能保留噪点

rho 参数(Karras 和 Polyexponential)

控制噪声分布的"形状":

  • 较小的 rho:更快的初始去噪,更多的步骤用于后期细节生成
  • 较大的 rho:更均匀的去噪过程,对整体质量可能更好

11. 调度器代码实现的技术细节

零点附加

所有调度器都使用 append_zero 函数在噪声序列末尾添加一个零:

python
def append_zero(x): return torch.cat([x, x.new_zeros([1])])

这确保了最终状态完全无噪声,这对于生成干净的最终图像很重要。

内部模型依赖

某些调度器(Uniform 和 SGM Uniform)需要 inner_model 参数:

python
need_inner_model: bool = False

这是因为它们需要访问模型特定的函数来执行噪声转换。

总结

噪声调度器是扩散模型生成过程中的关键组件,正确选择调度器可以显著提高生成质量和效率:

  1. Automatic:默认选择,根据采样器自动选择最佳调度器
  2. Uniform:简单的均匀调度,不是最优选择
  3. Karras:高性能调度器,特别适合低步数采样
  4. Exponential:在对数空间均匀分布步骤
  5. Polyexponential:结合多项式和指数调度,提供灵活控制
  6. SGM Uniform:专为SGM模型设计的均匀t空间调度

在实际使用中,除非你有特定需求,否则使用 Automatic 让系统自动选择是最简单有效的方法。如果你想要更精细的控制,Karras调度器在大多数情况下是最佳选择,尤其是与DPM++系列采样器结合使用时。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!