使用 Latent Consistency LoRA 让 SDXL 实现 4 步出图

发布于 2023 年 11 月 9 日
在 GitHub 上更新

Latent Consistency Models (LCM) 是一种通过将原始模型 蒸馏 成另一个版本来减少 Stable Diffusion(或 SDXL)生成图像所需步数的方法,新版本需要更少的步数(4到8步,而非原始的25到50步)。蒸馏是一种训练过程,试图用一个新模型来复制源模型的输出。蒸馏后的模型可以被设计得更小(比如 DistilBERT 或最近发布的 Distil-Whisper),或者像本例一样,需要更少的运行步数。这通常是一个漫长且昂贵的过程,需要大量的数据、耐心和几块 GPU。

嗯,这是今天之前的现状!

我们很高兴地宣布一种新方法,它基本上可以使 Stable Diffusion 和 SDXL 变得更快,就像它们经过了 LCM 过程的蒸馏一样!在 3090 显卡上运行 任何 SDXL 模型,时间从 7 秒缩短到约 1 秒,或者在 Mac 上快 10 倍,听起来怎么样?请继续阅读以了解详情!

目录

方法概述

那么,诀窍是什么呢?对于潜在一致性蒸馏,每个模型都需要单独蒸馏。而 LCM LoRA 的核心思想是只训练少量被称为 LoRA 层 的适配器,而不是整个模型。然后,生成的 LoRA 就可以应用于模型的任何微调版本,而无需对它们进行单独的蒸馏。如果你迫不及待想看看实际效果,请直接跳到 下一节 去体验推理代码。如果你想训练自己的 LoRA,你可以按照以下流程操作:

  1. 从 Hub 中选择一个可用的教师模型。例如,你可以使用 SDXL (base),或任何你喜欢的微调或 Dreambooth 版本。
  2. 在该模型上训练一个 LCM LoRA。LoRA 是一种性能高效的微调(PEFT)方法,其成本远低于完整的模型微调。有关 PEFT 的更多详情,请查看 这篇博客文章diffusers 的 LoRA 文档
  3. 将 LoRA 与任何 SDXL 扩散模型和 LCM 调度器一起使用;搞定!你只需几个步骤就能获得高质量的推理结果。

有关该过程的更多详情,请下载我们的论文

这为什么重要?

Stable Diffusion 和 SDXL 的快速推理催生了新的应用场景和工作流程。仅举几例:

  • 可及性:生成式工具可以被更多人有效使用,即使他们没有最新的硬件。
  • 更快的迭代:在极短的时间内获得更多图像和多种变体!这对艺术家和研究人员来说非常棒,无论是个人还是商业用途。
  • 生产工作负载可能可以在不同的加速器上运行,包括 CPU。
  • 更便宜的图像生成服务。

为了衡量我们所说的速度差异,在 M1 Mac 上使用 SDXL(基础版)生成一张 1024x1024 的图像大约需要一分钟。而使用 LCM LoRA,我们只需约 6 秒(4 步)就能得到出色的结果。这是一个数量级的提速,无需等待结果改变了一切。使用 4090 显卡,我们几乎可以得到即时响应(不到 1 秒)。这解锁了 SDXL 在需要实时响应的应用中的使用。

使用 SDXL LCM LoRA 进行快速推理

今天发布的 diffusers 版本使得使用 LCM LoRA 变得非常简单:

from diffusers import DiffusionPipeline, LCMScheduler
import torch

model_id = "stabilityai/stable-diffusion-xl-base-1.0"
lcm_lora_id = "latent-consistency/lcm-lora-sdxl"

pipe = DiffusionPipeline.from_pretrained(model_id, variant="fp16")

pipe.load_lora_weights(lcm_lora_id)
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
pipe.to(device="cuda", dtype=torch.float16)

prompt = "close-up photography of old man standing in the rain at night, in a street lit by lamps, leica 35mm summilux"
images = pipe(
    prompt=prompt,
    num_inference_steps=4,
    guidance_scale=1,
).images[0]

请注意代码是如何:

  • 使用 SDXL 1.0 基础模型实例化一个标准的扩散管线。
  • 应用 LCM LoRA。
  • 将调度器更改为 LCMScheduler,这是潜在一致性模型中使用的调度器。
  • 就是这样!

这将生成以下全分辨率图像:

SDXL in 4 steps with LCM LoRA
使用 LCM LoRA,通过 4 步用 SDXL 生成的图像。

质量比较

让我们看看步数如何影响生成质量。以下代码将生成总推理步数为 1 到 8 的图像:

images = []
for steps in range(8):
    generator = torch.Generator(device=pipe.device).manual_seed(1337)
    image = pipe(
        prompt=prompt,
        num_inference_steps=steps+1,
        guidance_scale=1,
        generator=generator,
    ).images[0]
    images.append(image)

这是以网格形式显示的 8 张图像:

LCM LoRA generations with 1 to 8 steps
使用 1 到 8 步生成的 LCM LoRA 图像。

正如预期的那样,仅使用 1 步会产生一个大致的形状,没有可辨别的特征且缺乏纹理。然而,结果很快得到改善,通常在 4 到 6 步内就非常令人满意。就我个人而言,我觉得上一个测试中 8 步的图像对我来说有点太饱和和“卡通化”了,所以我可能会在这个例子中选择 5 到 6 步的图像。生成速度非常快,你只需 4 步就能创建一堆不同的变体,然后选择你喜欢的,再用几步和更精细的提示词进行迭代。

引导系数和负向提示词

请注意,在前面的例子中,我们使用的 guidance_scale1,这实际上禁用了它。这对于大多数提示词效果很好,而且速度最快,但会忽略负向提示词。你也可以尝试使用负向提示词,通过提供一个介于 12 之间的引导系数——我们发现更大的值效果不佳。

与基础版 SDXL 的质量对比

在质量方面,这与标准的 SDXL 管线相比如何?让我们看一个例子!

我们可以通过卸载 LoRA 权重并切换到默认调度器来快速将我们的管线恢复为标准的 SDXL 管线:

from diffusers import EulerDiscreteScheduler

pipe.unload_lora_weights()
pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config)

然后我们可以像往常一样运行 SDXL 的推理。我们将收集不同步数下的结果:

images = []
for steps in (1, 4, 8, 15, 20, 25, 30, 50):
    generator = torch.Generator(device=pipe.device).manual_seed(1337)
    image = pipe(
        prompt=prompt,
        num_inference_steps=steps,
        generator=generator,
    ).images[0]
    images.append(image)

SDXL results for various inference steps
SDXL 管线结果(相同的提示词和随机种子),使用 1、4、8、15、20、25、30 和 50 步。

正如你所见,在这个例子中,图像在约 20 步(第二行)之前几乎是无用的,并且质量随着步数的增加仍然有显著提升。最终图像的细节令人惊叹,但它需要 50 步才能达到。

LCM LoRA 与其他模型的结合

这项技术也适用于任何其他微调的 SDXL 或 Stable Diffusion 模型。为了演示,让我们看看如何在 collage-diffusion 上运行推理,这是一个使用 Dreambooth 从 Stable Diffusion v1.5 微调的模型。

代码与我们前面例子中看到的类似。我们加载微调后的模型,然后加载适用于 Stable Diffusion v1.5 的 LCM LoRA。

from diffusers import DiffusionPipeline, LCMScheduler
import torch

model_id = "wavymulder/collage-diffusion"
lcm_lora_id = "latent-consistency/lcm-lora-sdv1-5"

pipe = DiffusionPipeline.from_pretrained(model_id, variant="fp16")
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
pipe.load_lora_weights(lcm_lora_id)
pipe.to(device="cuda", dtype=torch.float16)

prompt = "collage style kid sits looking at the night sky, full of stars"

generator = torch.Generator(device=pipe.device).manual_seed(1337)
images = pipe(
    prompt=prompt,
    generator=generator,
    negative_prompt=negative_prompt,
    num_inference_steps=4,
    guidance_scale=1,
).images[0]
images

LCM LoRA technique with a Dreambooth Stable Diffusion v1.5 model, allowing 4-step inference.
LCM LoRA 技术与 Dreambooth Stable Diffusion v1.5 模型结合,实现 4 步推理。

完整的 Diffusers 集成

LCM 在 diffusers 中的集成使得利用 diffusers 工具箱中的许多功能和工作流程成为可能。例如:

  • 开箱即用的对搭载 Apple Silicon 芯片 Mac 的 mps 支持。
  • 内存和性能优化,如 flash attention 或 torch.compile()
  • 针对低内存环境的额外内存节省策略,包括模型卸载。
  • 像 ControlNet 或图生图这样的工作流程。
  • 训练和微调脚本。

基准测试

本节并非旨在详尽无遗,而是为了说明我们在各种计算机上实现的生成速度。让我们再次强调,如此轻松地探索图像生成是多么令人解放。

硬件 SDXL LoRA LCM (4 步) 标准 SDXL (25 步)
Mac, M1 Max 6.5 秒 64 秒
2080 Ti 4.7 秒 10.2 秒
3090 1.4 秒 7 秒
4090 0.7 秒 3.4 秒
T4 (Google Colab 免费版) 8.4 秒 26.5 秒
A100 (80 GB) 1.2 秒 3.8 秒
Intel i9-10980XE CPU (使用 1/36 核) 29 秒 219 秒

这些测试在所有情况下都使用批大小为 1 运行,脚本由 Sayak Paul 编写,链接在这里

对于像 A100 这样大容量的显卡,当一次生成多张图像时,性能会显著提高,这通常是生产工作负载的情况。

今日发布的 LCM LoRA 和模型

额外内容:将 LCM LoRA 与常规 SDXL LoRA 结合

使用 diffusers + PEFT 集成,你可以将 LCM LoRA 与常规 SDXL LoRA 结合,赋予它们仅需 4 步即可进行 LCM 推理的超能力。

这里我们将结合 CiroN2022/toy_face LoRA 和 LCM LoRA:

from diffusers import DiffusionPipeline, LCMScheduler
import torch

model_id = "stabilityai/stable-diffusion-xl-base-1.0"
lcm_lora_id = "latent-consistency/lcm-lora-sdxl"
pipe = DiffusionPipeline.from_pretrained(model_id, variant="fp16")
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

pipe.load_lora_weights(lcm_lora_id)
pipe.load_lora_weights("CiroN2022/toy-face", weight_name="toy_face_sdxl.safetensors", adapter_name="toy")

pipe.set_adapters(["lora", "toy"], adapter_weights=[1.0, 0.8])
pipe.to(device="cuda", dtype=torch.float16)

prompt = "a toy_face man"
negative_prompt = "blurry, low quality, render, 3D, oversaturated"
images = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    num_inference_steps=4,
    guidance_scale=0.5,
).images[0]
images

Combining LoRAs for fast inference
标准 LoRA 和 LCM LoRA 结合,实现快速(4 步)推理。

需要一些探索 LoRA 的想法吗?快来试试我们实验性的 LoRA the Explorer (LCM 版) Space,测试社区的惊人创作并获取灵感吧!

如何训练 LCM 模型和 LoRA

作为今天 diffusers 发布的一部分,我们提供了与 LCM 团队作者合作开发的训练和微调脚本。它们允许用户:

  • 在像 Laion 这样的大型数据集上对 Stable Diffusion 或 SDXL 模型进行全模型蒸馏。
  • 训练 LCM LoRA,这是一个容易得多的过程。正如我们在这篇文章中展示的,它也使得在 Stable Diffusion 上实现快速推理成为可能,而无需经过蒸馏训练。

更多详情,请查看仓库中针对 SDXLStable Diffusion 的说明。

我们希望这些脚本能激励社区尝试他们自己的微调。如果您在项目中使用它们,请务必告诉我们!

资源

致谢

Latent Consistency Models 的惊人工作由 LCM 团队 完成,请务必查看他们的代码、报告和论文。这个项目是 diffusers 团队、LCM 团队和社区贡献者 Daniel Gu 之间的合作成果。我们相信,这是开源 AI 赋能的证明,它是让研究人员、从业者和爱好者探索新思想和协作的基石。我们还要感谢 @madebyollin 对社区的持续贡献,包括我们在训练脚本中使用的 float16 自动编码器。

社区

注册登录 以发表评论