社区计算机视觉课程文档
Stable Diffusion 简介
并获得增强的文档体验
开始使用
Stable Diffusion 简介
本章介绍 Stable Diffusion 的构建模块,Stable Diffusion 是一种生成式人工智能(生成式 AI)模型,可根据文本和图像提示生成独特的逼真图像。它最初于 2022 年推出,得益于 Stability AI、RunwayML 和慕尼黑大学 CompVis 团队在论文发表后的合作。
您将从本章学到什么?
- Stable Diffusion 的基本组成部分
- 如何使用
text-to-image
、image2image
、图像修复管道
Stable Diffusion 如何工作?
为了使本节有趣,我们将尝试回答一些问题,以了解 Stable Diffusion 过程的基本组成部分。我们将简要讨论每个组成部分,因为它们已在我们的 Diffusers 课程中介绍。此外,您可以访问我们之前的章节,其中详细介绍了 GANs 和扩散模型。
- Stable Diffusion 采用哪些策略来学习新信息?
- 它使用扩散模型的前向和反向过程。在前向过程中,我们向图像添加高斯噪声,直到只剩下随机噪声。通常我们无法识别图像的最终噪声版本。
- 在反向过程中,我们有一个经过训练的神经网络,用于从纯噪声开始逐渐去噪图像,直到得到实际图像。
这两个过程都发生在有限的步数 T(根据 DDPM 论文 T=1000)。您从时间开始该过程通过从数据分布中采样真实图像,并且前向过程在每个时间步 t 从高斯分布中采样一些噪声,并将其添加到前一个时间步的图像中。要获得更多数学直觉,请阅读 Hugging Face 博客上关于扩散模型的文章。
- 由于我们的图像可能很大,我们如何压缩它?
当您拥有大图像时,它们需要更多的计算能力来处理。这在称为自注意力的特定操作中变得非常明显。图像越大,所需的计算量越大,并且这些计算量随着图像的大小呈“二次方”快速增加。例如,如果您的图像宽度和高度为 128 像素,则其像素是宽度和高度仅为 64 像素的图像的四倍。由于自注意力工作原理,处理此较大图像不仅需要四倍的内存和计算能力,它实际上需要十六倍(因为 4 乘以 4 等于 16)。这使得处理高分辨率图像变得具有挑战性,因为它们需要大量的资源来处理。潜在扩散模型通过使用变分自编码器(VAE)将图像缩小到更易于管理的大小来解决处理大图像的高计算需求。其思想是,许多图像都包含重复或不必要的信息。VAE 在大量数据上进行训练后,可以将图像压缩成更小、更紧凑的形式。这种较小的版本仍然保留了原始图像的基本特征。
- 既然我们正在使用提示,我们如何将文本与图像融合?
我们知道,在推理时,我们可以输入我们希望看到的图像描述和一些纯噪声作为起点,模型会尽力将随机输入“去噪”成与描述匹配的内容。SD 利用基于 CLIP 的预训练 Transformer 模型。CLIP 的文本编码器旨在将图像描述处理成可用于比较图像和文本的形式,因此它非常适合从图像描述创建有用表示的任务。输入提示首先被标记化(基于一个大词汇表,其中每个单词或子单词被分配一个特定的标记),然后通过 CLIP 文本编码器,为每个标记生成一个 768 维(SD 1.X 的情况)或 1024 维(SD 2.X)向量。为了保持一致性,提示总是被填充/截断为 77 个标记长,因此我们用作条件的最终表示是一个形状为每个提示 77x1024 的张量。
- 我们如何加入良好的归纳偏置?
因为我们正在尝试生成新的东西(例如,一只逼真的宝可梦),我们需要一种方法来超越我们以前见过的图像(例如,一只动漫宝可梦)。这就是 U-Net 和自注意力发挥作用的地方。给定图像的噪声版本,模型的任务是根据额外的线索(例如图像的文本描述)预测去噪版本。好的,我们如何将这些条件信息实际输入到 U-Net 中以供其在进行预测时使用?答案是所谓的交叉注意力。U-Net 中散布着交叉注意力层。U-Net 中的每个空间位置都可以“关注”文本条件中的不同标记,从而从提示中引入相关信息。
如何在 Diffusers 中使用 text-to-image、image-to-image、图像修复模型
本节介绍有用的用例以及如何使用 Diffusers 库执行这些任务。
text-to-image
推理步骤:其思想是传入文本提示,然后将其转换为输出图像。
使用 diffusers
库,您可以通过 2 个步骤使 text-to-image
工作。
我们首先安装 diffusers
库。
pip install diffusers
现在我们将初始化管道并传入我们的提示并进行推理。
from diffusers import AutoPipelineForText2Image
import torch
pipeline = AutoPipelineForText2Image.from_pretrained(
"runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16, variant="fp16"
).to("cuda")
generator = torch.Generator(device="cuda").manual_seed(31)
image = pipeline(
"Astronaut in a jungle, cold color palette, muted colors, detailed, 8k",
generator=generator,
).images[0]
image-to-image
推理步骤:以类似的方式,我们可以初始化管道,但传入图像和文本提示。
import torch
from diffusers import AutoPipelineForImage2Image
from diffusers.utils import load_image, make_image_grid
pipeline = AutoPipelineForImage2Image.from_pretrained(
"kandinsky-community/kandinsky-2-2-decoder",
torch_dtype=torch.float16,
use_safetensors=True,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()
# Load an image to pass to the pipeline:
init_image = load_image(
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/cat.png"
)
# Pass a prompt and image to the pipeline to generate an image:
prompt = "cat wizard, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney, 8k"
image = pipeline(prompt, image=init_image).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
- 图像修复步骤:对于图像修复管道,我们需要传入图像、文本提示和基于图像中对象的遮罩,这表明要在图像中进行修复。在此示例中,我们还传入一个负面提示,以进一步影响我们希望避免的推理。
# Load the pipeline
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid
pipeline = AutoPipelineForInpainting.from_pretrained(
"kandinsky-community/kandinsky-2-2-decoder-inpaint", torch_dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()
# Load the base and mask images:
init_image = load_image(
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png"
)
mask_image = load_image(
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png"
)
# Create a prompt to inpaint the image with and pass it to the pipeline with the base and mask images:
prompt = (
"a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k"
)
negative_prompt = "bad anatomy, deformed, ugly, disfigured"
image = pipeline(
prompt=prompt,
negative_prompt=negative_prompt,
image=init_image,
mask_image=mask_image,
).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)