Skip to content

调度器功能

调度器是任何扩散模型的重要组成部分,因为它控制着整个去噪(或采样)过程。调度器有很多类型,有些针对速度优化,有些针对质量优化。使用 Diffusers,你可以修改调度器配置以使用自定义噪声调度、sigma 和重新缩放噪声调度。更改这些参数会对推理质量和速度产生深远的影响。

本指南将演示如何使用这些功能来提高推理质量。

TIP

Diffusers 目前仅支持 timestepssigmas 参数,适用于选定的调度器和管道列表。如果你想将这些参数扩展到当前不支持它们的调度器和管道,请随时打开一个 功能请求

时间步长调度

时间步长或噪声调度决定了每个采样步骤的噪声量。调度器使用它来生成在每个步骤具有相应噪声量的图像。时间步长调度是从调度器的默认配置生成的,但你可以自定义调度器以使用尚未在 Diffusers 中的新的优化采样调度。

例如,Align Your Steps (AYS) 是一种优化采样调度以在少至 10 步内生成高质量图像的方法。Stable Diffusion XL 的最佳 10 步调度 为:

py
from diffusers.schedulers import AysSchedules

sampling_schedule = AysSchedules["StableDiffusionXLTimesteps"]
print(sampling_schedule)
"[999, 845, 730, 587, 443, 310, 193, 116, 53, 13]"

时间步间隔

在调度中选择采样步骤的方式会影响生成图像的质量,尤其是在重新缩放噪声调度方面,这可以使模型生成更亮或更暗的图像。Diffusers 提供三种时间步间隔方法:

  • leading 创建均匀间隔的步骤
  • linspace 包含第一个和最后一个步骤,并均匀地选择剩余的中间步骤
  • trailing 只包含最后一个步骤,并从末尾开始均匀地选择剩余的中间步骤

建议使用 trailing 间隔方法,因为它在采样步骤较少时会生成更高质量的图像,并包含更多细节。但对于更标准的采样步骤值,质量差异并不明显。

py
pipeline = StableDiffusionXLPipeline.from_pretrained(
    "SG161222/RealVisXL_V4.0",
    torch_dtype=torch.float16,
    variant="fp16",
).to("cuda")
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config, algorithm_type="sde-dpmsolver++")

prompt = "A cinematic shot of a cute little rabbit wearing a jacket and doing a thumbs up"
generator = torch.Generator(device="cpu").manual_seed(2487854446)
image = pipeline(
    prompt=prompt,
    negative_prompt="",
    generator=generator,
    timesteps=sampling_schedule,
).images[0]
AYS timestep schedule 10 steps
Linearly-spaced timestep schedule 10 steps
Linearly-spaced timestep schedule 25 steps
py
import torch
from diffusers import StableDiffusionXLPipeline, DPMSolverMultistepScheduler

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "SG161222/RealVisXL_V4.0",
    torch_dtype=torch.float16,
    variant="fp16",
).to("cuda")
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config, timestep_spacing="trailing")

prompt = "A cinematic shot of a cute little black cat sitting on a pumpkin at night"
generator = torch.Generator(device="cpu").manual_seed(2487854446)
image = pipeline(
    prompt=prompt,
    negative_prompt="",
    generator=generator,
    num_inference_steps=5,
).images[0]
image
trailing spacing after 5 steps
leading spacing after 5 steps

西格玛

sigmas 参数是在每个时间步根据时间步调度添加的噪声量。与 timesteps 参数类似,你可以自定义 sigmas 参数来控制在每个步骤中添加多少噪声。当你使用自定义 sigmas 值时,timesteps 将根据自定义 sigmas 值计算,默认调度程序配置将被忽略。

例如,你可以手动将 sigmas 传递给管道,例如之前提到的 10 步 AYS 调度。

py
import torch

from diffusers import DiffusionPipeline, EulerDiscreteScheduler

model_id = "stabilityai/stable-diffusion-xl-base-1.0"
pipeline = DiffusionPipeline.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  torch_dtype=torch.float16,
  variant="fp16",
).to("cuda")
pipeline.scheduler = EulerDiscreteScheduler.from_config(pipeline.scheduler.config)

sigmas = [14.615, 6.315, 3.771, 2.181, 1.342, 0.862, 0.555, 0.380, 0.234, 0.113, 0.0]
prompt = "anthropomorphic capybara wearing a suit and working with a computer"
generator = torch.Generator(device='cuda').manual_seed(123)
image = pipeline(
    prompt=prompt,
    num_inference_steps=10,
    sigmas=sigmas,
    generator=generator
).images[0]

当你查看调度程序的 timesteps 参数时,你会发现它与 AYS 时间步调度相同,因为 timestep 调度是根据 sigmas 计算的。

py
print(f" timesteps: {pipe.scheduler.timesteps}")
"timesteps: tensor([999., 845., 730., 587., 443., 310., 193., 116.,  53.,  13.], device='cuda:0')"

Karras 标准差

TIP

请参考调度器 API 概述 以获取支持 Karras 标准差的调度器列表。

Karras 标准差不应用于未用其训练的模型。例如,基础 Stable Diffusion XL 模型不应使用 Karras 标准差,但 DreamShaperXL 模型可以使用,因为它们是用 Karras 标准差训练的。

Karras 调度器使用 阐明基于扩散的生成模型的设计空间 论文中的时间步长计划和标准差。与其他调度器相比,这种调度器变体在采样过程结束时每步应用的噪声更少,可以提高生成图像的细节水平。

通过在调度器中设置 use_karras_sigmas=True 来启用 Karras 标准差。

py
import torch
from diffusers import StableDiffusionXLPipeline, DPMSolverMultistepScheduler

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "SG161222/RealVisXL_V4.0",
    torch_dtype=torch.float16,
    variant="fp16",
).to("cuda")
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config, algorithm_type="sde-dpmsolver++", use_karras_sigmas=True)

prompt = "A cinematic shot of a cute little rabbit wearing a jacket and doing a thumbs up"
generator = torch.Generator(device="cpu").manual_seed(2487854446)
image = pipeline(
    prompt=prompt,
    negative_prompt="",
    generator=generator,
).images[0]
Karras sigmas enabled
Karras sigmas disabled

重塑噪声调度

Common Diffusion Noise Schedules and Sample Steps are Flawed 这篇论文中,作者发现常见的噪声调度允许一些信号泄漏到最后一个时间步。这种推理时的信号泄漏会导致模型只生成中等亮度的图像。通过对时间步调度强制执行零信噪比 (SNR) 并从最后一个时间步采样,可以改进模型以生成非常明亮或黑暗的图像。

TIP

对于推理,你需要一个使用 v_prediction 训练的模型。要使用 v_prediction 训练你自己的模型,请在 train_text_to_image.pytrain_text_to_image_lora.py 脚本中添加以下标志。

bash
> --prediction_type="v_prediction"
> ```

例如,加载 [ptx0/pseudo-journey-v2](https://hf.co/ptx0/pseudo-journey-v2) 检查点,该检查点使用 `v_prediction`  [`DDIMScheduler`] 进行训练。在 [`DDIMScheduler`] 中配置以下参数:

* `rescale_betas_zero_snr=True` 将噪声调度重新缩放到零 SNR
* `timestep_spacing="trailing"` 从最后一个时间步开始采样

在管道中设置 `guidance_rescale` 以防止过度曝光。较低的值会增加亮度,但某些细节可能会显得褪色。

```py
from diffusers import DiffusionPipeline, DDIMScheduler

pipeline = DiffusionPipeline.from_pretrained("ptx0/pseudo-journey-v2", use_safetensors=True)

pipeline.scheduler = DDIMScheduler.from_config(
    pipeline.scheduler.config, rescale_betas_zero_snr=True, timestep_spacing="trailing"
)
pipeline.to("cuda")
prompt = "cinematic photo of a snowy mountain at night with the northern lights aurora borealis overhead, 35mm photograph, film, professional, 4k, highly detailed"
generator = torch.Generator(device="cpu").manual_seed(23)
image = pipeline(prompt, guidance_rescale=0.7, generator=generator).images[0]
image
default Stable Diffusion v2-1 image
image with zero SNR and trailing timestep spacing enabled