Diffusers 文档

快速教程

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

快速教程

扩散模型通过逐步去噪随机高斯噪声来生成感兴趣的样本,例如图像或音频。这在生成式人工智能领域引起了巨大兴趣,您可能已经在互联网上看到过扩散生成的图像示例。🧨 Diffusers 是一个旨在让所有人都能广泛使用扩散模型的库。

无论您是开发人员还是日常用户,本快速教程都将向您介绍 🧨 Diffusers 并帮助您快速开始生成!该库有三个主要组件需要了解:

  • DiffusionPipeline 是一个高级的端到端类,旨在快速从预训练扩散模型生成样本以进行推理。
  • 流行的预训练模型架构和模块,可用作构建扩散系统的构建块。
  • 许多不同的调度器 - 控制训练时如何添加噪声以及推理时如何生成去噪图像的算法。

快速教程将向您展示如何使用DiffusionPipeline进行推理,然后引导您了解如何组合模型和调度器以复制DiffusionPipeline内部发生的事情。

快速教程是 🧨 Diffusers 入门notebook 的简化版本,可帮助您快速入门。如果您想了解更多关于 🧨 Diffusers 的目标、设计理念及其核心 API 的其他详细信息,请查看该 notebook!

在开始之前,请确保您已安装所有必要的库

# uncomment to install the necessary libraries in Colab
#!pip install --upgrade diffusers accelerate transformers

DiffusionPipeline

DiffusionPipeline 是使用预训练扩散系统进行推理的最简单方法。它是一个包含模型和调度器的端到端系统。您可以开箱即用DiffusionPipeline来完成许多任务。请查看下表以了解一些受支持的任务,有关受支持任务的完整列表,请查看🧨 Diffusers 摘要表。

任务 描述 流水线
无条件图像生成 从高斯噪声生成图像 无条件图像生成
文本引导图像生成 根据文本提示生成图像 条件图像生成
文本引导图像到图像翻译 根据文本提示调整图像 图像到图像
文本引导图像修复 给定图像、遮罩和文本提示,填充图像的遮罩部分 图像修复
文本引导深度到图像翻译 根据文本提示调整图像部分,同时通过深度估计保持结构 深度到图像

首先创建DiffusionPipeline的实例,并指定要下载的管道检查点。您可以将DiffusionPipeline用于存储在 Hugging Face Hub 上的任何检查点。在本快速教程中,您将加载stable-diffusion-v1-5检查点以进行文本到图像生成。

对于Stable Diffusion模型,请在运行模型之前仔细阅读许可证。🧨 Diffusers 实现了safety_checker以防止冒犯性或有害内容,但模型的改进图像生成能力仍可能生成潜在有害内容。

使用from_pretrained()方法加载模型

>>> from diffusers import DiffusionPipeline

>>> pipeline = DiffusionPipeline.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", use_safetensors=True)

DiffusionPipeline下载并缓存所有建模、分词和调度组件。您会看到 Stable Diffusion 管道由UNet2DConditionModelPNDMScheduler等组成

>>> pipeline
StableDiffusionPipeline {
  "_class_name": "StableDiffusionPipeline",
  "_diffusers_version": "0.21.4",
  ...,
  "scheduler": [
    "diffusers",
    "PNDMScheduler"
  ],
  ...,
  "unet": [
    "diffusers",
    "UNet2DConditionModel"
  ],
  "vae": [
    "diffusers",
    "AutoencoderKL"
  ]
}

我们强烈建议在 GPU 上运行管道,因为该模型包含大约 14 亿个参数。您可以像在 PyTorch 中一样将生成器对象移动到 GPU。

>>> pipeline.to("cuda")

现在您可以将文本提示传递给pipeline以生成图像,然后访问去噪图像。默认情况下,图像输出被包装在PIL.Image对象中。

>>> image = pipeline("An image of a squirrel in Picasso style").images[0]
>>> image

通过调用save保存图像

>>> image.save("image_of_squirrel_painting.png")

本地管道

您也可以在本地使用该管道。唯一的区别是您需要先下载权重

!git lfs install
!git clone https://huggingface.co/stable-diffusion-v1-5/stable-diffusion-v1-5

然后将保存的权重加载到管道中

>>> pipeline = DiffusionPipeline.from_pretrained("./stable-diffusion-v1-5", use_safetensors=True)

现在,您可以像上一节中那样运行管道。

更换调度器

不同的调度器具有不同的去噪速度和质量权衡。找出最适合您的方法是尝试它们!🧨 Diffusers 的主要功能之一是让您可以轻松地在调度器之间切换。例如,要用EulerDiscreteScheduler替换默认的PNDMScheduler,请使用from_config()方法加载它

>>> from diffusers import EulerDiscreteScheduler

>>> pipeline = DiffusionPipeline.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", use_safetensors=True)
>>> pipeline.scheduler = EulerDiscreteScheduler.from_config(pipeline.scheduler.config)

尝试使用新的调度器生成图像,看看您是否注意到差异!

在下一节中,您将仔细研究构成DiffusionPipeline的组件——模型和调度器——并学习如何使用这些组件生成猫的图像。

模型

大多数模型接收一个带噪声的样本,并在每个时间步预测*噪声残差*(其他模型学习直接预测之前的样本或速度或v-prediction),即噪声较少的图像与输入图像之间的差异。您可以混合搭配模型来创建其他扩散系统。

模型通过from_pretrained()方法进行初始化,该方法也会在本地缓存模型权重,以便下次加载模型时更快。在本快速教程中,您将加载UNet2DModel,这是一个基于猫图像训练的检查点的基本无条件图像生成模型。

>>> from diffusers import UNet2DModel

>>> repo_id = "google/ddpm-cat-256"
>>> model = UNet2DModel.from_pretrained(repo_id, use_safetensors=True)

如果您不确定要使用哪个模型类,可以使用AutoModel API 自动选择模型类。

要访问模型参数,请调用model.config

>>> model.config

模型配置是一个🧊冻结🧊的字典,这意味着这些参数在模型创建后不能更改。这是有意为之的,确保用于定义模型架构的参数在开始时保持不变,而其他参数仍可在推理期间调整。

一些最重要的参数是:

  • sample_size:输入样本的高度和宽度维度。
  • in_channels:输入样本的输入通道数。
  • down_block_typesup_block_types:用于创建 UNet 架构的下采样和上采样块的类型。
  • block_out_channels:下采样块的输出通道数;也以相反顺序用于上采样块的输入通道数。
  • layers_per_block:每个 UNet 块中存在的 ResNet 块的数量。

为了将模型用于推理,使用随机高斯噪声创建图像形状。它应该有一个batch轴,因为模型可以接收多个随机噪声,一个对应于输入通道数的channel轴,以及一个用于图像高度和宽度的sample_size轴。

>>> import torch

>>> torch.manual_seed(0)

>>> noisy_sample = torch.randn(1, model.config.in_channels, model.config.sample_size, model.config.sample_size)
>>> noisy_sample.shape
torch.Size([1, 3, 256, 256])

对于推理,将带噪图像和`timestep`传递给模型。`timestep`表示输入图像的噪声程度,开始时噪声更多,结束时噪声更少。这有助于模型确定其在扩散过程中的位置,是更接近开始还是结束。使用`sample`方法获取模型输出。

>>> with torch.no_grad():
...     noisy_residual = model(sample=noisy_sample, timestep=2).sample

但是,要生成实际示例,您需要一个调度器来指导去噪过程。在下一节中,您将学习如何将模型与调度器结合使用。

调度器

调度器根据模型输出(在本例中为`noisy_residual`)管理从带噪声样本到噪声较少样本的过程。

🧨 Diffusers 是一个用于构建扩散系统的工具箱。虽然DiffusionPipeline是开始使用预构建扩散系统的便捷方法,但您也可以单独选择自己的模型和调度器组件来构建自定义扩散系统。

对于快速教程,您将使用其from_config()方法实例化DDPMScheduler

>>> from diffusers import DDPMScheduler

>>> scheduler = DDPMScheduler.from_pretrained(repo_id)
>>> scheduler
DDPMScheduler {
  "_class_name": "DDPMScheduler",
  "_diffusers_version": "0.21.4",
  "beta_end": 0.02,
  "beta_schedule": "linear",
  "beta_start": 0.0001,
  "clip_sample": true,
  "clip_sample_range": 1.0,
  "dynamic_thresholding_ratio": 0.995,
  "num_train_timesteps": 1000,
  "prediction_type": "epsilon",
  "sample_max_value": 1.0,
  "steps_offset": 0,
  "thresholding": false,
  "timestep_spacing": "leading",
  "trained_betas": null,
  "variance_type": "fixed_small"
}

💡 与模型不同,调度器没有可训练的权重,并且是无参数的!

一些最重要的参数是:

  • num_train_timesteps:去噪过程的长度,换句话说,是将随机高斯噪声处理成数据样本所需的时间步数。
  • beta_schedule:用于推理和训练的噪声调度类型。
  • beta_startbeta_end:噪声调度的起始和结束噪声值。

要预测一个稍微不那么嘈杂的图像,请将以下内容传递给调度器的step()方法:模型输出、`timestep`和当前`sample`。

>>> less_noisy_sample = scheduler.step(model_output=noisy_residual, timestep=2, sample=noisy_sample).prev_sample
>>> less_noisy_sample.shape
torch.Size([1, 3, 256, 256])

less_noisy_sample 可以传递到下一个 `timestep`,在那里它会变得更不嘈杂!现在让我们把所有这些结合起来,可视化整个去噪过程。

首先,创建一个函数,该函数将去噪后的图像作为PIL.Image进行后处理和显示。

>>> import PIL.Image
>>> import numpy as np


>>> def display_sample(sample, i):
...     image_processed = sample.cpu().permute(0, 2, 3, 1)
...     image_processed = (image_processed + 1.0) * 127.5
...     image_processed = image_processed.numpy().astype(np.uint8)

...     image_pil = PIL.Image.fromarray(image_processed[0])
...     display(f"Image at step {i}")
...     display(image_pil)

为了加快去噪过程,将输入和模型移到 GPU

>>> model.to("cuda")
>>> noisy_sample = noisy_sample.to("cuda")

现在创建一个去噪循环,预测噪声较小样本的残差,并用调度器计算噪声较小样本

>>> import tqdm

>>> sample = noisy_sample

>>> for i, t in enumerate(tqdm.tqdm(scheduler.timesteps)):
...     # 1. predict noise residual
...     with torch.no_grad():
...         residual = model(sample, t).sample

...     # 2. compute less noisy image and set x_t -> x_t-1
...     sample = scheduler.step(residual, t, sample).prev_sample

...     # 3. optionally look at image
...     if (i + 1) % 50 == 0:
...         display_sample(sample, i + 1)

坐下来,看着一只猫从无到有地生成!😻

下一步

希望您在本快速教程中用 🧨 Diffusers 生成了一些很酷的图像!接下来,您可以:

< > 在 GitHub 上更新