Diffusers 文档

调度器功能

Hugging Face's logo
加入 Hugging Face 社区

并获得增强文档体验

开始使用

调度器功能

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

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

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

时间步长调度

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

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

from diffusers.schedulers import AysSchedules

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

您可以通过将其传递给 timesteps 参数,在管道中使用 AYS 采样调度。

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 时间步长调度 10 步
线性时间步长调度 10 步
线性时间步长调度 25 步

时间步长间隔

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

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

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

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
5 步后的 trailing 间隔
5 步后的 leading 间隔

Sigmas

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

例如,您可以手动将类似于之前 10 步 AYS 调度的 sigmas 传递给管道。

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 计算得出的。

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

Karras Sigmas

有关支持 Karras Sigmas 的调度器列表,请参阅调度器 API 概述

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

Karras 调度器使用来自 阐明基于扩散的生成模型的设计空间 论文的时间步长调度和 Sigmas。与其他调度器相比,此调度器变体在接近采样过程结束时会应用更少的噪声,并且可以提高生成图像的细节水平。

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

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
已禁用 Karras Sigmas

重新缩放噪声调度

在论文常见扩散噪声调度和采样步骤存在缺陷中,作者发现常见的噪声调度允许一些信号泄漏到最后一个时间步长。这种推理时的信号泄漏会导致模型只能生成中等亮度的图像。通过为时间步长调度强制执行零信噪比 (SNR) 并从最后一个时间步长采样,可以改进模型以生成非常明亮或黑暗的图像。

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

--prediction_type="v_prediction"

例如,加载使用v_predictionDDIMScheduler训练的ptx0/pseudo-journey-v2检查点。在DDIMScheduler中配置以下参数

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

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

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
默认 Stable Diffusion v2-1 图像
启用零 SNR 和尾随时间步长间距的图像
< > 在 GitHub 上更新