快速入门
扩散模型被训练逐步去除随机高斯噪声以生成目标样本,例如图像或音频。这引发了人们对生成式 AI 的极大兴趣,您可能在互联网上看到了扩散生成的图像示例。🧨 Diffusers 是一个旨在让每个人都能轻松使用扩散模型的库。
无论您是开发者还是普通用户,此快速入门将介绍您🧨 Diffusers 并帮助您快速开始生成!库中有三个主要组件需要了解
- DiffusionPipeline 是一个高级端到端类,旨在快速从预训练的扩散模型生成样本以进行推理。
- 流行的预训练模型 架构和模块,可用作创建扩散系统的构建块。
- 许多不同的调度器 - 用于控制训练时如何添加噪声以及在推理过程中如何生成去噪图像的算法。
快速入门将向您展示如何使用DiffusionPipeline 进行推理,然后引导您完成如何组合模型和调度器以复制DiffusionPipeline 内部的过程。
快速入门是介绍性🧨 Diffusers 笔记本 的简化版本,可帮助您快速上手。如果您想了解有关🧨 Diffusers 的目标、设计理念及其核心 API 的更多详细信息,请查看该笔记本!
在开始之前,请确保您已安装所有必要的库
# uncomment to install the necessary libraries in Colab
#!pip install --upgrade diffusers accelerate transformers
- 🤗 Accelerate 加速模型加载以进行推理和训练。
- 🤗 Transformers 是运行最流行的扩散模型(例如Stable Diffusion)所必需的。
DiffusionPipeline
DiffusionPipeline 是使用预训练的扩散系统进行推理的最简单方法。它是一个端到端系统,包含模型和调度器。您可以将DiffusionPipeline 开箱即用地用于许多任务。请查看下面的表格以了解一些支持的任务,有关支持任务的完整列表,请查看🧨 Diffusers 摘要 表格。
任务 | 描述 | 管道 |
---|---|---|
无条件图像生成 | 从高斯噪声生成图像 | unconditional_image_generation |
文本引导图像生成 | 根据文本提示生成图像 | conditional_image_generation |
文本引导图像到图像翻译 | 根据文本提示调整图像 | img2img |
文本引导图像修复 | 根据图像、蒙版和文本提示填充图像的遮罩部分 | inpaint |
文本引导深度到图像翻译 | 根据文本提示调整图像的某些部分,同时通过深度估计保留结构 | depth2img |
首先创建一个DiffusionPipeline 实例,并指定要下载的管道检查点。您可以将DiffusionPipeline 用于 Hugging Face Hub 上存储的任何检查点。在此快速入门中,您将加载stable-diffusion-v1-5
检查点以进行文本到图像生成。
对于Stable Diffusion 模型,请在运行模型之前仔细阅读许可证。🧨 Diffusers 实现了一个safety_checker
来防止攻击性或有害内容,但该模型改进的图像生成能力仍然可能产生潜在的有害内容。
使用from_pretrained() 方法加载模型
>>> from diffusers import DiffusionPipeline
>>> pipeline = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", use_safetensors=True)
DiffusionPipeline 下载并缓存所有建模、标记化和调度组件。您会发现 Stable Diffusion 管道由UNet2DConditionModel 和PNDMScheduler 以及其他内容组成
>>> pipeline
StableDiffusionPipeline {
"_class_name": "StableDiffusionPipeline",
"_diffusers_version": "0.21.4",
...,
"scheduler": [
"diffusers",
"PNDMScheduler"
],
...,
"unet": [
"diffusers",
"UNet2DConditionModel"
],
"vae": [
"diffusers",
"AutoencoderKL"
]
}
我们强烈建议在 GPU 上运行管道,因为该模型大约包含 14 亿个参数。您可以将生成器对象移动到 GPU,就像您在 PyTorch 中所做的那样
>>> 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/runwayml/stable-diffusion-v1-5
然后将保存的权重加载到管道中
>>> pipeline = DiffusionPipeline.from_pretrained("./stable-diffusion-v1-5", use_safetensors=True)
现在,您可以像在上面的部分中一样运行管道。
交换调度器
不同的调度器具有不同的去噪速度和质量权衡。找到最适合您的调度器的最佳方法是尝试它们!🧨 Diffusers 的主要功能之一是允许您轻松地在调度器之间切换。例如,要将默认的 PNDMScheduler 替换为 EulerDiscreteScheduler,可以使用 from_config() 方法加载它。
>>> from diffusers import EulerDiscreteScheduler
>>> pipeline = DiffusionPipeline.from_pretrained("runwayml/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)
要访问模型参数,请调用model.config
>>> model.config
模型配置是一个🧊冻结🧊字典,这意味着这些参数在模型创建后无法更改。这是有意的,并确保用于在开始时定义模型架构的参数保持不变,而其他参数仍然可以在推理过程中进行调整。
一些最重要的参数是
sample_size
:输入样本的高度和宽度维度。in_channels
:输入样本的输入通道数。down_block_types
和up_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 是一种使用预构建扩散系统入门的好方法,但您也可以分别选择自己的模型和调度器组件来构建自定义扩散系统。
对于快速入门,您将使用 DDPMScheduler 及其 from_config() 方法实例化它。
>>> 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_start
和beta_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 生成了一些很酷的图像!接下来的步骤可以是
- 在 训练 教程中训练或微调模型以生成自己的图像。
- 查看用于各种用例的示例官方和社区 训练或微调脚本。
- 在 使用不同的调度器 指南中了解有关加载、访问、更改和比较调度器的更多信息。
- 在 Stable Diffusion 指南中探索提示工程、速度和内存优化以及生成更高质量图像的技巧和窍门。
- 通过有关 GPU 上的优化 PyTorch 的指南以及运行 Apple Silicon (M1/M2) 上的 Stable Diffusion 和 ONNX Runtime 的推理指南,更深入地了解如何加快 🧨 Diffusers 的速度。