Diffusers 文档

Latent Consistency Model

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Latent Consistency Model

Latent Consistency Model (LCM) 通过直接在潜在空间而非像素空间中预测反向扩散过程,实现了快速、高质量的图像生成。换句话说,与典型的扩散模型迭代地从噪声图像中去除噪声不同,LCM 试图从噪声图像中预测出无噪声的图像。由于避免了迭代采样过程,LCM 能够在 2-4 个步骤内生成高质量图像,而不是 20-30 个步骤。

LCM 是从预训练模型中蒸馏出来的,这需要大约 32 个 A100 计算小时。为了加速这一过程,LCM-LoRA 训练了一个 LoRA 适配器,其需要训练的参数比完整模型少得多。LCM-LoRA 训练完成后可以插入到扩散模型中。

本指南将向您展示如何使用 LCM 和 LCM-LoRA 在各种任务上进行快速推理,以及如何将它们与其他适配器(如 ControlNet 或 T2I-Adapter)一起使用。

LCM 和 LCM-LoRA 适用于 Stable Diffusion v1.5、Stable Diffusion XL 和 SSD-1B 模型。您可以在 Latent Consistency 集合中找到它们的检查点。

文本到图像

LCM
LCM-LoRA

要使用 LCM,您需要将支持的模型的 LCM 检查点加载到 UNet2DConditionModel 中,并将调度器替换为 LCMScheduler。然后您可以像往常一样使用 pipeline,并传递一个文本提示,仅需 4 个步骤即可生成图像。

使用 LCM 时需要注意以下几点:

  • 通常,在 pipeline 内部,为了实现无分类器引导(classifier-free guidance),批次大小会加倍。但是 LCM 使用引导嵌入(guidance embeddings)来应用引导,不需要加倍批次大小,从而实现了更快的推理。其缺点是负向提示词(negative prompts)对 LCM 不起作用,因为它们对去噪过程没有任何影响。
  • guidance_scale 的理想范围是 [3., 13.],因为这是 UNet 训练时使用的范围。然而,在大多数情况下,使用 1.0 的值禁用 guidance_scale 也是有效的。
from diffusers import StableDiffusionXLPipeline, UNet2DConditionModel, LCMScheduler
import torch

unet = UNet2DConditionModel.from_pretrained(
    "latent-consistency/lcm-sdxl",
    torch_dtype=torch.float16,
    variant="fp16",
)
pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", unet=unet, torch_dtype=torch.float16, variant="fp16",
).to("cuda")
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

prompt = "Self-portrait oil painting, a beautiful cyborg with golden hair, 8k"
generator = torch.manual_seed(0)
image = pipe(
    prompt=prompt, num_inference_steps=4, generator=generator, guidance_scale=8.0
).images[0]
image

图像到图像

LCM
LCM-LoRA

要使用 LCM 进行图像到图像生成,您需要将支持的模型的 LCM 检查点加载到 UNet2DConditionModel 中,并将调度器替换为 LCMScheduler。然后您可以像往常一样使用 pipeline,并传递一个文本提示和初始图像,仅需 4 个步骤即可生成图像。

尝试不同的 num_inference_stepsstrengthguidance_scale 值,以获得最佳结果。

import torch
from diffusers import AutoPipelineForImage2Image, UNet2DConditionModel, LCMScheduler
from diffusers.utils import load_image

unet = UNet2DConditionModel.from_pretrained(
    "SimianLuo/LCM_Dreamshaper_v7",
    subfolder="unet",
    torch_dtype=torch.float16,
)

pipe = AutoPipelineForImage2Image.from_pretrained(
    "Lykon/dreamshaper-7",
    unet=unet,
    torch_dtype=torch.float16,
    variant="fp16",
).to("cuda")
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/img2img-init.png")
prompt = "Astronauts in a jungle, cold color palette, muted colors, detailed, 8k"
generator = torch.manual_seed(0)
image = pipe(
    prompt,
    image=init_image,
    num_inference_steps=4,
    guidance_scale=7.5,
    strength=0.5,
    generator=generator
).images[0]
image
初始图像
生成的图像

图像修复

要使用 LCM-LoRA 进行图像修复,您需要将调度器替换为 LCMScheduler,并使用 load_lora_weights() 方法加载 LCM-LoRA 权重。然后您可以像往常一样使用 pipeline,并传递一个文本提示、初始图像和蒙版图像,仅需 4 个步骤即可生成图像。

import torch
from diffusers import AutoPipelineForInpainting, LCMScheduler
from diffusers.utils import load_image, make_image_grid

pipe = AutoPipelineForInpainting.from_pretrained(
    "runwayml/stable-diffusion-inpainting",
    torch_dtype=torch.float16,
    variant="fp16",
).to("cuda")

pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

pipe.load_lora_weights("latent-consistency/lcm-lora-sdv1-5")

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")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
generator = torch.manual_seed(0)
image = pipe(
    prompt=prompt,
    image=init_image,
    mask_image=mask_image,
    generator=generator,
    num_inference_steps=4,
    guidance_scale=4,
).images[0]
image
初始图像
生成的图像

适配器

LCM 与 LoRA、ControlNet、T2I-Adapter 和 AnimateDiff 等适配器兼容。您可以将 LCM 的速度带到这些适配器中,以生成特定风格的图像,或根据其他输入(如 canny 图像)来对模型进行条件化。

LoRA

LoRA 适配器可以快速进行微调,仅需几张图像即可学习一种新风格,并将其插入预训练模型中,以生成该风格的图像。

LCM
LCM-LoRA

将支持的模型的 LCM 检查点加载到 UNet2DConditionModel 中,并将调度器替换为 LCMScheduler。然后您可以使用 load_lora_weights() 方法将 LoRA 权重加载到 LCM 中,并在几个步骤内生成带有风格的图像。

from diffusers import StableDiffusionXLPipeline, UNet2DConditionModel, LCMScheduler
import torch

unet = UNet2DConditionModel.from_pretrained(
    "latent-consistency/lcm-sdxl",
    torch_dtype=torch.float16,
    variant="fp16",
)
pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", unet=unet, torch_dtype=torch.float16, variant="fp16",
).to("cuda")
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
pipe.load_lora_weights("TheLastBen/Papercut_SDXL", weight_name="papercut.safetensors", adapter_name="papercut")

prompt = "papercut, a cute fox"
generator = torch.manual_seed(0)
image = pipe(
    prompt=prompt, num_inference_steps=4, generator=generator, guidance_scale=8.0
).images[0]
image

ControlNet

ControlNet 是一种适配器,可以在多种输入(如 canny 边缘、姿态估计或深度)上进行训练。ControlNet 可以插入到 pipeline 中,为模型提供额外的条件和控制,以实现更精确的生成。

您可以在 lllyasviel 的仓库中找到更多在其他输入上训练的 ControlNet 模型。

LCM
LCM-LoRA

加载一个在 canny 图像上训练的 ControlNet 模型,并将其传递给 ControlNetModel。然后,您可以将 LCM 模型加载到 StableDiffusionControlNetPipeline 中,并将调度器替换为 LCMScheduler。现在将 canny 图像传递给 pipeline 并生成图像。

尝试不同的 num_inference_stepscontrolnet_conditioning_scalecross_attention_kwargsguidance_scale 值,以获得最佳结果。

import torch
import cv2
import numpy as np
from PIL import Image

from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, LCMScheduler
from diffusers.utils import load_image, make_image_grid

image = load_image(
    "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/input_image_vermeer.png"
).resize((512, 512))

image = np.array(image)

low_threshold = 100
high_threshold = 200

image = cv2.Canny(image, low_threshold, high_threshold)
image = image[:, :, None]
image = np.concatenate([image, image, image], axis=2)
canny_image = Image.fromarray(image)

controlnet = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-canny", torch_dtype=torch.float16)
pipe = StableDiffusionControlNetPipeline.from_pretrained(
    "SimianLuo/LCM_Dreamshaper_v7",
    controlnet=controlnet,
    torch_dtype=torch.float16,
    safety_checker=None,
).to("cuda")
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

generator = torch.manual_seed(0)
image = pipe(
    "the mona lisa",
    image=canny_image,
    num_inference_steps=4,
    generator=generator,
).images[0]
make_image_grid([canny_image, image], rows=1, cols=2)

T2I-Adapter

T2I-Adapter 是一个比 ControlNet 更轻量级的适配器,它为预训练模型提供了一个额外的输入以进行条件化。它比 ControlNet 更快,但结果可能略差。

您可以在 TencentArc 的仓库中找到更多在其他输入上训练的 T2I-Adapter 检查点。

LCM
LCM-LoRA

加载一个在 canny 图像上训练的 T2IAdapter,并将其传递给 StableDiffusionXLAdapterPipeline。然后将 LCM 检查点加载到 UNet2DConditionModel 中,并将调度器替换为 LCMScheduler。现在将 canny 图像传递给 pipeline 并生成图像。

import torch
import cv2
import numpy as np
from PIL import Image

from diffusers import StableDiffusionXLAdapterPipeline, UNet2DConditionModel, T2IAdapter, LCMScheduler
from diffusers.utils import load_image, make_image_grid

# detect the canny map in low resolution to avoid high-frequency details
image = load_image(
    "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/input_image_vermeer.png"
).resize((384, 384))

image = np.array(image)

low_threshold = 100
high_threshold = 200

image = cv2.Canny(image, low_threshold, high_threshold)
image = image[:, :, None]
image = np.concatenate([image, image, image], axis=2)
canny_image = Image.fromarray(image).resize((1024, 1216))

adapter = T2IAdapter.from_pretrained("TencentARC/t2i-adapter-canny-sdxl-1.0", torch_dtype=torch.float16, variant="fp16").to("cuda")

unet = UNet2DConditionModel.from_pretrained(
    "latent-consistency/lcm-sdxl",
    torch_dtype=torch.float16,
    variant="fp16",
)
pipe = StableDiffusionXLAdapterPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    unet=unet,
    adapter=adapter,
    torch_dtype=torch.float16,
    variant="fp16",
).to("cuda")

pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

prompt = "the mona lisa, 4k picture, high quality"
negative_prompt = "extra digit, fewer digits, cropped, worst quality, low quality, glitch, deformed, mutated, ugly, disfigured"

generator = torch.manual_seed(0)
image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    image=canny_image,
    num_inference_steps=4,
    guidance_scale=5,
    adapter_conditioning_scale=0.8,
    adapter_conditioning_factor=1,
    generator=generator,
).images[0]

AnimateDiff

AnimateDiff 是一种为图像添加运动的适配器。它可以与大多数 Stable Diffusion 模型一起使用,有效地将它们转变为“视频生成”模型。使用视频模型生成好的结果通常需要生成多帧(16-24 帧),这对于常规的 Stable Diffusion 模型来说可能非常慢。LCM-LoRA 可以通过每帧仅需 4-8 个步骤来加速这个过程。

加载一个 AnimateDiffPipeline 并向其传递一个 MotionAdapter。然后将调度器替换为 LCMScheduler,并使用 ~loaders.UNet2DConditionLoadersMixin.set_adapters 方法组合两个 LoRA 适配器。现在您可以将提示词传递给 pipeline 并生成一个动画图像。

import torch
from diffusers import MotionAdapter, AnimateDiffPipeline, DDIMScheduler, LCMScheduler
from diffusers.utils import export_to_gif

adapter = MotionAdapter.from_pretrained("guoyww/animatediff-motion-adapter-v1-5")
pipe = AnimateDiffPipeline.from_pretrained(
    "frankjoshua/toonyou_beta6",
    motion_adapter=adapter,
).to("cuda")

# set scheduler
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

# load LCM-LoRA
pipe.load_lora_weights("latent-consistency/lcm-lora-sdv1-5", adapter_name="lcm")
pipe.load_lora_weights("guoyww/animatediff-motion-lora-zoom-in", weight_name="diffusion_pytorch_model.safetensors", adapter_name="motion-lora")

pipe.set_adapters(["lcm", "motion-lora"], adapter_weights=[0.55, 1.2])

prompt = "best quality, masterpiece, 1girl, looking at viewer, blurry background, upper body, contemporary, dress"
generator = torch.manual_seed(0)
frames = pipe(
    prompt=prompt,
    num_inference_steps=5,
    guidance_scale=1.25,
    cross_attention_kwargs={"scale": 1},
    num_frames=24,
    generator=generator
).frames[0]
export_to_gif(frames, "animation.gif")
< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.