Diffusers 文档

加载调度器和模型

Hugging Face's logo
加入 Hugging Face 社区

并获得增强型文档体验

开始使用

加载调度器和模型

扩散管道是可互换调度器和模型的集合,可以混合匹配以根据特定用例定制管道。调度器封装了整个去噪过程,例如去噪步骤数量和查找去噪样本的算法。调度器不带参数或训练,因此它们占用的内存很少。模型通常只关心从噪声输入到噪声较小的样本的正向传递。

本指南将向您展示如何加载调度器和模型以自定义管道。您将在本指南中使用 runwayml/stable-diffusion-v1-5 检查点,因此让我们先加载它。

import torch
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16, use_safetensors=True
).to("cuda")

您可以使用 pipeline.scheduler 属性查看此管道使用的调度器。

pipeline.scheduler
PNDMScheduler {
  "_class_name": "PNDMScheduler",
  "_diffusers_version": "0.21.4",
  "beta_end": 0.012,
  "beta_schedule": "scaled_linear",
  "beta_start": 0.00085,
  "clip_sample": false,
  "num_train_timesteps": 1000,
  "set_alpha_to_one": false,
  "skip_prk_steps": true,
  "steps_offset": 1,
  "timestep_spacing": "leading",
  "trained_betas": null
}

加载调度器

调度器由配置文件定义,该配置文件可用于多种调度器。使用 SchedulerMixin.from_pretrained() 方法加载调度器,并指定 subfolder 参数将配置文件加载到管道存储库的正确子文件夹中。

例如,要加载 DDIMScheduler

from diffusers import DDIMScheduler, DiffusionPipeline

ddim = DDIMScheduler.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="scheduler")

然后,您可以将新加载的调度器传递到管道中。

pipeline = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5", scheduler=ddim, torch_dtype=torch.float16, use_safetensors=True
).to("cuda")

比较调度器

调度器各有优缺点,因此很难定量比较哪个调度器最适合管道。您通常需要在去噪速度和去噪质量之间进行权衡。我们建议尝试不同的调度器以找到最适合您的用例的调度器。调用 pipeline.scheduler.compatibles 属性以查看哪些调度器与管道兼容。

让我们比较一下以下提示和种子上的 LMSDiscreteSchedulerEulerDiscreteSchedulerEulerAncestralDiscreteSchedulerDPMSolverMultistepScheduler

import torch
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16, use_safetensors=True
).to("cuda")

prompt = "A photograph of an astronaut riding a horse on Mars, high resolution, high definition."
generator = torch.Generator(device="cuda").manual_seed(8)

要更改管道调度器,请使用 from_config() 方法将其他调度器的 pipeline.scheduler.config 加载到管道中。

LMSDiscreteScheduler
EulerDiscreteScheduler
EulerAncestralDiscreteScheduler
DPMSolverMultistepScheduler

LMSDiscreteScheduler 通常比默认调度器生成更高质量的图像。

from diffusers import LMSDiscreteScheduler

pipeline.scheduler = LMSDiscreteScheduler.from_config(pipeline.scheduler.config)
image = pipeline(prompt, generator=generator).images[0]
image
LMSDiscreteScheduler
EulerDiscreteScheduler
EulerAncestralDiscreteScheduler
DPMSolverMultistepScheduler

大多数图像看起来非常相似,质量相当。再次,这通常取决于您的特定用例,因此一种好的方法是运行多个不同的调度器并比较结果。

Flax 调度器

要比较 Flax 调度器,您还需要将调度器状态加载到模型参数中。例如,让我们更改 FlaxStableDiffusionPipeline 中的默认调度器以使用超快的 FlaxDPMSolverMultistepScheduler

FlaxLMSDiscreteSchedulerFlaxDDPMScheduler 尚未与 FlaxStableDiffusionPipeline 兼容。

import jax
import numpy as np
from flax.jax_utils import replicate
from flax.training.common_utils import shard
from diffusers import FlaxStableDiffusionPipeline, FlaxDPMSolverMultistepScheduler

scheduler, scheduler_state = FlaxDPMSolverMultistepScheduler.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    subfolder="scheduler"
)
pipeline, params = FlaxStableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    scheduler=scheduler,
    variant="bf16",
    dtype=jax.numpy.bfloat16,
)
params["scheduler"] = scheduler_state

然后,您可以利用 Flax 与 TPU 的兼容性并行生成多个图像。您需要为每个可用设备制作模型参数的副本,然后将输入拆分到它们之间以生成所需数量的图像。

# Generate 1 image per parallel device (8 on TPUv2-8 or TPUv3-8)
prompt = "A photograph of an astronaut riding a horse on Mars, high resolution, high definition."
num_samples = jax.device_count()
prompt_ids = pipeline.prepare_inputs([prompt] * num_samples)

prng_seed = jax.random.PRNGKey(0)
num_inference_steps = 25

# shard inputs and rng
params = replicate(params)
prng_seed = jax.random.split(prng_seed, jax.device_count())
prompt_ids = shard(prompt_ids)

images = pipeline(prompt_ids, params, prng_seed, num_inference_steps, jit=True).images
images = pipeline.numpy_to_pil(np.asarray(images.reshape((num_samples,) + images.shape[-3:])))

模型

模型是从 ModelMixin.from_pretrained() 方法加载的,该方法会下载和缓存模型权重和配置的最新版本。如果本地缓存中存在最新文件,from_pretrained() 会重用缓存中的文件,而不是重新下载它们。

可以使用 subfolder 参数从子文件夹加载模型。例如,runwayml/stable-diffusion-v1-5 的模型权重存储在 unet 子文件夹中。

from diffusers import UNet2DConditionModel

unet = UNet2DConditionModel.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="unet", use_safetensors=True)

它们也可以直接从 存储库 中加载。

from diffusers import UNet2DModel

unet = UNet2DModel.from_pretrained("google/ddpm-cifar10-32", use_safetensors=True)

要加载和保存模型变体,请在 ModelMixin.from_pretrained()ModelMixin.save_pretrained() 中指定 variant 参数。

from diffusers import UNet2DConditionModel

unet = UNet2DConditionModel.from_pretrained(
    "runwayml/stable-diffusion-v1-5", subfolder="unet", variant="non_ema", use_safetensors=True
)
unet.save_pretrained("./local-unet", variant="non_ema")
< > 更新 在 GitHub 上