调度器
调度器(scheduler)告诉去噪循环在每个步骤中应去除多少噪声。不同的调度器在速度与质量之间进行权衡。
本指南介绍如何加载调度器,并自定义其时间步调度、间隔和 sigmas。
选择调度器
从默认检查点开始。只有在需要不同的速度或质量权衡时,才进行替换。
- DPM++ 2M SDE Karras 是许多潜在扩散检查点的强大通用选项。
- TCDScheduler 适用于蒸馏模型。
- 对于 FlowMatch 模型(如 Qwen-Image、Flux 及类似模型),请使用 FlowMatchEulerDiscreteScheduler 或 FlowMatchHeunDiscreteScheduler。
- EulerDiscreteScheduler 或 EulerAncestralDiscreteScheduler 通常适用于动漫风格的图像。
- 如果检查点支持,使用 LCMScheduler 搭配 LCM UNet 或 LoRA 进行少步生成。
加载调度器
像 Qwen-Image 和 Flux 这样的 Flow-matching 模型默认使用 FlowMatchEulerDiscreteScheduler。除非您有意进行实验,否则请保留该调度器。仅当替换项与检查点兼容时,才使用 from_config() 进行替换。
调度器仅包含配置,不包含权重张量。可以通过访问 pipeline 的 .scheduler 属性来查看已加载的配置。
import torch
from diffusers import DiffusionPipeline
pipeline = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16, device_map="cuda" # or "mps", "xpu", "cpu"
)
pipeline.scheduler要在已加载的 pipeline 中更换调度器,请使用 from_config() 并传入现有的调度器配置,以确保 num_train_timesteps 及相关字段保持一致。对于 FlowMatch 检查点(Qwen-Image、Flux 及类似模型),除非您有意尝试使用兼容的替代方案,否则请保留 FlowMatchEulerDiscreteScheduler。
from diffusers import DPMSolverMultistepScheduler
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config)您还可以通过 from_pretrained() 从 Hub 加载调度器配置,并通过 scheduler 将其传入 from_pretrained()。
from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
dpm = DPMSolverMultistepScheduler.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", subfolder="scheduler"
)
pipeline = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
scheduler=dpm,
dtype=torch.float16,
device_map="cuda", # or "mps", "xpu", "cpu"
)
pipeline.scheduler时间步调度
时间步或噪声调度决定了噪声在去噪过程中的分布方式。该调度可以是线性的,也可以更集中于过程的起始或结束阶段。它是由调度器的默认配置生成的预计算噪声水平序列,但也可以自定义以使用其他调度方案。
linear (even steps) AYS (denser where it matters) noise noise ^ ^ | * | * | * | * | * | ** | * | *** | * | ** | * | * | * | * +-----------------> step +-----------------> step
自定义的
timesteps仅在该调度器的set_timesteps接受此参数时有效(流水线会通过retrieve_timesteps检查函数签名,否则将抛出ValueError)。在传入之前,请查阅该调度器的 API 页面或set_timesteps的函数签名。
以下示例使用 Align Your Steps (AYS) 调度器,该调度器可在 10 步内生成高质量图像,从而显著加快生成速度并减少计算时间。
导入该 schedule,并将其传递给 pipeline 中的 timesteps 参数。
import torch
from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
from diffusers.schedulers import AysSchedules
sampling_schedule = AysSchedules["StableDiffusionXLTimesteps"]
print(sampling_schedule)
# [999, 845, 730, 587, 443, 310, 193, 116, 53, 13]
pipeline = DiffusionPipeline.from_pretrained(
"SG161222/RealVisXL_V4.0",
dtype=torch.float16,
device_map="cuda" # or "mps", "xpu", "cpu"
)
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"
image = pipeline(
prompt=prompt,
negative_prompt="",
timesteps=sampling_schedule,
).images[0]
对于旧检查点的 v-prediction/zero-SNR 重缩放,请参阅 Legacy checkpoints。
时间步间隔
时间步间距指的是从调度方案中采样的特定步骤 t。Diffusers 提供了以下三种间距类型。
| 间距策略 | 间距计算 | 示例时间步 |
|---|---|---|
leading | 均匀间隔的步骤 | [900, 800, 700, ..., 100, 0] |
linspace | 包含首尾步骤,并均匀划分其余中间步骤 | [1000, 888.89, 777.78, ..., 111.11, 0] |
trailing | 包含最后一步,并从末尾开始均匀分配剩余的中间步骤 | [999, 899, 799, 699, 599, 499, 399, 299, 199, 99] |
将间距策略传递给调度器中的 timestep_spacing 参数。
trailing策略通常能在更少的步数下生成质量更高、细节更丰富的图像,但对于更标准的步数值,质量差异并不明显。
import torch
from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
pipeline = DiffusionPipeline.from_pretrained(
"SG161222/RealVisXL_V4.0",
dtype=torch.float16,
device_map="cuda" # or "mps", "xpu", "cpu"
)
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"
image = pipeline(
prompt=prompt,
negative_prompt="",
num_inference_steps=5,
).images[0]
image
Sigmas
Sigmas 是衡量在调度器定义的某个步骤中样本噪声程度的指标。当使用自定义的 sigmas 时,timesteps 将根据这些值进行计算,而不是使用默认的调度器配置。
step: 0 1 2 3 4
sigma: σ0 > σ1 > σ2 > σ3 > σ4 ≈ 0
high noise ---> clean sample自定义的
sigmas仅在该调度器的set_timesteps接受此参数时才有效(流水线会通过retrieve_timesteps检查函数签名,否则将抛出ValueError)。在传入之前,请查阅该调度器的 API 页面或set_timesteps的函数签名。
将自定义 sigmas 传入 pipeline 中的 sigmas 参数。下面的示例使用了 10 步 AYS 调度中的 sigmas。
import torch
from diffusers import DiffusionPipeline, EulerDiscreteScheduler
from diffusers.schedulers import AysSchedules
pipeline = DiffusionPipeline.from_pretrained(
"SG161222/RealVisXL_V4.0",
dtype=torch.float16,
device_map="cuda", # or "mps", "xpu", "cpu"
)
pipeline.scheduler = EulerDiscreteScheduler.from_config(pipeline.scheduler.config)
sigmas = AysSchedules["StableDiffusionXLSigmas"]
prompt = "A cinematic shot of a cute little rabbit wearing a jacket and doing a thumbs up"
image = pipeline(
prompt=prompt,
negative_prompt="",
sigmas=sigmas,
).images[0]Karras sigmas
Karras sigmas 通过重新采样噪声调度来实现更高效的采样:它在序列中部(结构重建至关重要的区域)将 sigmas 分布得更密集,而在噪声变化影响较小的开头和结尾使用更少的 sigmas。这可以提高生成图像的精细程度。
default σ: * * * * * * * * even-ish
Karras σ: * * * * * * * denser mid, sparser ends
|---structure---|在调度器中设置 use_karras_sigmas=True 即可启用该功能。
import torch
from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
pipeline = DiffusionPipeline.from_pretrained(
"SG161222/RealVisXL_V4.0",
dtype=torch.float16,
device_map="cuda" # or "mps", "xpu", "cpu"
)
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"
image = pipeline(
prompt=prompt,
negative_prompt="",
num_inference_steps=20,
).images[0]
有关支持 Karras sigmas 的调度器列表,请参阅调度器 API 概览。它仅应用于使用 Karras sigmas 训练的模型。
后续步骤
- Read the Common Diffusion Noise Schedules and Sample Steps are Flawed paper for more details about rescaling the noise schedule to enforce zero SNR.