Skip to content

扰动注意力引导

Perturbed-Attention Guidance (PAG) 是一种新的扩散采样引导方法,可以在无条件和有条件设置下提高样本质量,而无需进一步训练或集成外部模块。PAG 通过考虑自注意力机制捕捉结构信息的能力,逐步增强合成样本的结构。它通过在扩散 U-Net 中用单位矩阵替换选定的自注意力图来生成结构退化的中间样本,并引导去噪过程远离这些退化的样本。

本指南将向你展示如何在各种任务和用例中使用 PAG。

通用任务

你可以将 PAG 应用于 [StableDiffusionXLPipeline],用于文本到图像、图像到图像和修复等任务。要为特定任务启用 PAG,可以使用 AutoPipeline API 加载管道,并设置 enable_pag=True 标志和 pag_applied_layers 参数。

TIP

🤗 Diffusers 目前仅支持在选定的 SDXL 管道和 [PixArtSigmaPAGPipeline] 中使用 PAG。如果你希望为新的管道添加 PAG 支持,欢迎提交 功能请求

使用 ControlNet 的 PAG

要使用带有 ControlNet 的 PAG,首先创建一个 controlnet。然后,将 controlnet 和其他 PAG 参数传递给指定任务的 AutoPipeline 的 from_pretrained 方法。

py
from diffusers import AutoPipelineForText2Image, ControlNetModel
import torch

controlnet = ControlNetModel.from_pretrained(
    "diffusers/controlnet-canny-sdxl-1.0", torch_dtype=torch.float16
)

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    controlnet=controlnet,
    enable_pag=True,
    pag_applied_layers="mid",
    torch_dtype=torch.float16
)
pipeline.enable_model_cpu_offload()

你可以像正常使用 ControlNet 管道一样使用该管道,同时还可以指定一个 pag_scale 参数。请注意,PAG 在无条件生成方面表现良好。在本例中,我们将生成一张没有提示词的图像。

py
from diffusers.utils import load_image
canny_image = load_image(
    "https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/pag_control_input.png"
)

for pag_scale in [0.0, 3.0]:
    generator = torch.Generator(device="cpu").manual_seed(1)
    images = pipeline(
        prompt="",
        controlnet_conditioning_scale=controlnet_conditioning_scale,
        image=canny_image,
        num_inference_steps=50,
        guidance_scale=0,
        generator=generator,
        pag_scale=pag_scale,
    ).images
    images[0]
generated image without PAG
generated image with PAG

使用 IP-Adapter 的 PAG

IP-Adapter 是一个流行的模型,可以插入扩散模型中,无需对底层模型进行任何修改即可实现图像提示。你可以在加载了 IP-Adapter 的管道中启用 PAG。

py
from diffusers import AutoPipelineForText2Image
from diffusers.utils import load_image
from transformers import CLIPVisionModelWithProjection
import torch

image_encoder = CLIPVisionModelWithProjection.from_pretrained(
    "h94/IP-Adapter",
    subfolder="models/image_encoder",
    torch_dtype=torch.float16
)

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    image_encoder=image_encoder,
    enable_pag=True,
    torch_dtype=torch.float16
).to("cuda")

pipeline.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name="ip-adapter-plus_sdxl_vit-h.bin")

pag_scales = 5.0
ip_adapter_scales = 0.8

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

pipeline.set_ip_adapter_scale(ip_adapter_scale)
generator = torch.Generator(device="cpu").manual_seed(0)
images = pipeline(
    prompt="a polar bear sitting in a chair drinking a milkshake",
    ip_adapter_image=image,
    negative_prompt="deformed, ugly, wrong proportion, low res, bad anatomy, worst quality, low quality",
    num_inference_steps=25,
    guidance_scale=3.0,
    generator=generator,
    pag_scale=pag_scale,
).images
images[0]

PAG 减少了伪影并改善了整体构图。

generated image without PAG
generated image with PAG

配置参数

pag_applied_layers

pag_applied_layers 参数允许你指定 PAG 应用到哪些层。默认情况下,它仅应用于中间块。更改此设置将显著影响输出。你可以使用 set_pag_applied_layers 方法在创建管道后调整 PAG 层,帮助你找到模型的最佳层。

例如,以下是使用 pag_layers = ["down.block_2"]pag_layers = ["down.block_2", "up.block_1.attentions_0"] 生成的图像。

py
prompt = "an insect robot preparing a delicious meal, anime style"
pipeline.set_pag_applied_layers(pag_layers)
generator = torch.Generator(device="cpu").manual_seed(0)
images = pipeline(
    prompt=prompt,
    num_inference_steps=25,
    guidance_scale=guidance_scale,
    generator=generator,
    pag_scale=pag_scale,
).images
images[0]
down.block_2 + up.block1.attentions_0
down.block_2