潜在一致性模型
潜在一致性模型 (LCM) 通过直接预测潜在空间而不是像素空间中的反向扩散过程,实现了快速高质量的图像生成。换句话说,LCM 尝试从噪声图像中预测无噪声图像,与典型的扩散模型从噪声图像中迭代去除噪声形成对比。通过避免迭代采样过程,LCM 能够在 2-4 步而不是 20-30 步内生成高质量的图像。
LCM 从预训练模型中提炼出来,需要大约 32 小时的 A100 计算。为了加快速度,LCM-LoRAs 训练一个 LoRA 适配器,与完整模型相比,它具有更少的参数需要训练。LCM-LoRA 可以训练完成后插入扩散模型中。
本指南将向您展示如何在任务中使用 LCM 和 LCM-LoRA 进行快速推断,以及如何将它们与其他适配器(如 ControlNet 或 T2I-Adapter)一起使用。
LCM 和 LCM-LoRA 可用于 Stable Diffusion v1.5、Stable Diffusion XL 和 SSD-1B 模型。您可以在 潜在一致性 集合中找到它们的检查点。
文到图
要使用 LCM,您需要将支持模型的 LCM 检查点加载到 UNet2DConditionModel 中,并将调度器替换为 LCMScheduler。然后,您可以照常使用管道,并传递文本提示以在短短 4 步内生成图像。
使用 LCM 时需要牢记几点
- 通常,批次大小在管道内会加倍以进行无分类器引导。但 LCM 使用引导嵌入进行引导,不需要将批次大小加倍,从而实现更快的推断。缺点是负面提示对 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 检查点加载到 UNet2DConditionModel 中,并将调度器替换为 LCMScheduler。然后,您可以照常使用管道,并传递文本提示和初始图像以在短短 4 步内生成图像。
尝试不同的 num_inference_steps
、strength
和 guidance_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 权重。然后,您可以照常使用管道,并传递文本提示、初始图像和掩码图像以在短短 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 检查点加载到 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 可以插入到管道中,为模型提供额外的条件和控制,以实现更准确的生成。
你可以在 lllyasviel 的 仓库中找到针对其他输入训练的额外 ControlNet 模型。
加载一个针对 Canny 图像训练的 ControlNet 模型,并将其传递给 ControlNetModel。然后,你可以将 LCM 模型加载到 StableDiffusionControlNetPipeline 中,并用 LCMScheduler 替换调度器。现在将 Canny 图像传递给管道并生成图像。
尝试使用不同的 num_inference_steps
、controlnet_conditioning_scale
、cross_attention_kwargs
和 guidance_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://hf.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 检查点。
加载一个针对 Canny 图像训练的 T2IAdapter,并将其传递给 StableDiffusionXLAdapterPipeline。然后将 LCM 检查点加载到 UNet2DConditionModel 中,并用 LCMScheduler 替换调度器。现在将 Canny 图像传递给管道并生成图像。
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://hf.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, varient="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 替换调度器,并将两个 LoRA 适配器与 ~loaders.UNet2DConditionLoadersMixin.set_adapters
方法组合起来。现在你可以将提示传递给管道并生成动画图像。
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")