调度器功能
调度器是任何扩散模型的重要组成部分,因为它控制着整个去噪(或采样)过程。调度器有很多类型,有些针对速度进行了优化,有些针对质量进行了优化。使用 Diffusers,您可以修改调度器配置以使用自定义噪声调度、sigma 以及重新缩放噪声调度。更改这些参数会对推理质量和速度产生深远的影响。
本指南将演示如何使用这些功能来提高推理质量。
Diffusers 目前仅支持选定调度器和管道中的 timesteps
和 sigmas
参数。如果您想将这些参数扩展到当前不支持它们的调度器和管道,请随时打开一个 功能请求!
时间步长调度
时间步长或噪声调度决定了每个采样步骤中的噪声量。调度器使用它来生成在每个步骤中具有相应噪声量的图像。时间步长调度是从调度器的默认配置生成的,但您可以自定义调度器以使用 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]
时间步长间隔
在调度中选择采样步骤的方式会影响生成图像的质量,尤其是在 重新缩放噪声调度 方面,这可以使模型生成更亮或更暗的图像。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
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]
重新缩放噪声调度
在论文常见扩散噪声调度和采样步骤存在缺陷中,作者发现常见的噪声调度允许一些信号泄漏到最后一个时间步长。这种推理时的信号泄漏会导致模型只能生成中等亮度的图像。通过为时间步长调度强制执行零信噪比 (SNR) 并从最后一个时间步长采样,可以改进模型以生成非常明亮或黑暗的图像。
对于推理,您需要一个使用v_prediction训练的模型。要使用v_prediction训练您自己的模型,请将以下标志添加到train_text_to_image.py或train_text_to_image_lora.py脚本中。
--prediction_type="v_prediction"
例如,加载使用v_prediction
和DDIMScheduler训练的ptx0/pseudo-journey-v2检查点。在DDIMScheduler中配置以下参数
rescale_betas_zero_snr=True
将噪声调度重新缩放为零 SNRtimestep_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