社区计算机视觉课程文档

Stable Diffusion 简介

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Stable Diffusion 简介

本章介绍 Stable Diffusion 的构建模块,Stable Diffusion 是一种生成式人工智能(生成式 AI)模型,可根据文本和图像提示生成独特的逼真图像。它最初于 2022 年推出,得益于 Stability AI、RunwayML 和慕尼黑大学 CompVis 团队在论文发表后的合作。

您将从本章学到什么?

  • Stable Diffusion 的基本组成部分
  • 如何使用 text-to-imageimage2image、图像修复管道

Stable Diffusion 如何工作?

为了使本节有趣,我们将尝试回答一些问题,以了解 Stable Diffusion 过程的基本组成部分。我们将简要讨论每个组成部分,因为它们已在我们的 Diffusers 课程中介绍。此外,您可以访问我们之前的章节,其中详细介绍了 GANs 和扩散模型。

  • Stable Diffusion 采用哪些策略来学习新信息?
    • 它使用扩散模型的前向和反向过程。在前向过程中,我们向图像添加高斯噪声,直到只剩下随机噪声。通常我们无法识别图像的最终噪声版本。
    • 在反向过程中,我们有一个经过训练的神经网络,用于从纯噪声开始逐渐去噪图像,直到得到实际图像。

这两个过程都发生在有限的步数 T(根据 DDPM 论文 T=1000)。您从时间开始该过程t0t_0通过从数据分布中采样真实图像,并且前向过程在每个时间步 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)

进一步阅读

< > 在 GitHub 上更新