Diffusers 文档

InstructPix2Pix

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始入门

InstructPix2Pix

InstructPix2Pix 是一个 Stable Diffusion 模型,经过训练可以根据人类提供的指令编辑图像。 例如,您的 prompt 可以是“将云变成多雨”,模型将相应地编辑输入图像。 此模型以文本 prompt(或编辑指令)和输入图像为条件。

本指南将探讨 train_instruct_pix2pix.py 训练脚本,以帮助您熟悉它,以及如何针对您自己的用例进行调整。

在运行脚本之前,请确保您从源代码安装了库

git clone https://github.com/huggingface/diffusers
cd diffusers
pip install .

然后导航到包含训练脚本的示例文件夹,并安装您正在使用的脚本所需的依赖项

cd examples/instruct_pix2pix
pip install -r requirements.txt

🤗 Accelerate 是一个帮助您在多个 GPU/TPU 上或使用混合精度进行训练的库。 它将根据您的硬件和环境自动配置您的训练设置。 请查看 🤗 Accelerate 快速入门 以了解更多信息。

初始化 🤗 Accelerate 环境

accelerate config

要设置默认的 🤗 Accelerate 环境而无需选择任何配置

accelerate config default

或者,如果您的环境不支持交互式 shell(例如 notebook),您可以使用

from accelerate.utils import write_basic_config

write_basic_config()

最后,如果您想在您自己的数据集上训练模型,请查看 创建用于训练的数据集 指南,以了解如何创建与训练脚本配合使用的数据集。

以下部分重点介绍了训练脚本中对于理解如何修改脚本很重要的部分,但并未详细介绍脚本的每个方面。 如果您有兴趣了解更多信息,请随时通读 脚本,如果您有任何问题或疑虑,请告知我们。

脚本参数

训练脚本有许多参数可以帮助您自定义训练运行。 所有参数及其说明都可以在 parse_args() 函数中找到。 大多数参数都提供了默认值,这些默认值效果很好,但如果您愿意,也可以在训练命令中设置自己的值。

例如,要增加输入图像的分辨率

accelerate launch train_instruct_pix2pix.py \
  --resolution=512 \

许多基本且重要的参数在 文本到图像 训练指南中进行了描述,因此本指南仅关注 InstructPix2Pix 的相关参数

  • --original_image_column:编辑之前的原始图像
  • --edited_image_column:编辑后的图像
  • --edit_prompt_column:编辑图像的指令
  • --conditioning_dropout_prob:训练期间编辑后的图像和编辑 prompt 的 dropout 概率,这为一个或两个条件输入启用了无分类器指导(CFG)

训练脚本

数据集预处理代码和训练循环可以在 main() 函数中找到。 您可以在此处更改训练脚本,以使其适应您自己的用例。

与脚本参数一样,文本到图像 训练指南中提供了训练脚本的详细介绍。 相反,本指南着眼于脚本中与 InstructPix2Pix 相关的部分。

脚本首先修改 UNet 的第一个卷积层中的 输入通道数,以考虑 InstructPix2Pix 的附加条件图像

in_channels = 8
out_channels = unet.conv_in.out_channels
unet.register_to_config(in_channels=in_channels)

with torch.no_grad():
    new_conv_in = nn.Conv2d(
        in_channels, out_channels, unet.conv_in.kernel_size, unet.conv_in.stride, unet.conv_in.padding
    )
    new_conv_in.weight.zero_()
    new_conv_in.weight[:, :4, :, :].copy_(unet.conv_in.weight)
    unet.conv_in = new_conv_in

这些 UNet 参数由优化器 更新

optimizer = optimizer_cls(
    unet.parameters(),
    lr=args.learning_rate,
    betas=(args.adam_beta1, args.adam_beta2),
    weight_decay=args.adam_weight_decay,
    eps=args.adam_epsilon,
)

接下来,编辑后的图像和编辑指令被 预处理标记化。 重要的是,相同的图像转换应用于原始图像和编辑后的图像。

def preprocess_train(examples):
    preprocessed_images = preprocess_images(examples)

    original_images, edited_images = preprocessed_images.chunk(2)
    original_images = original_images.reshape(-1, 3, args.resolution, args.resolution)
    edited_images = edited_images.reshape(-1, 3, args.resolution, args.resolution)

    examples["original_pixel_values"] = original_images
    examples["edited_pixel_values"] = edited_images

    captions = list(examples[edit_prompt_column])
    examples["input_ids"] = tokenize_captions(captions)
    return examples

最后,在 训练循环 中,它首先将编辑后的图像编码到潜在空间中

latents = vae.encode(batch["edited_pixel_values"].to(weight_dtype)).latent_dist.sample()
latents = latents * vae.config.scaling_factor

然后,脚本将 dropout 应用于原始图像和编辑指令嵌入,以支持 CFG。 这使得模型能够调节编辑指令和原始图像对编辑后图像的影响。

encoder_hidden_states = text_encoder(batch["input_ids"])[0]
original_image_embeds = vae.encode(batch["original_pixel_values"].to(weight_dtype)).latent_dist.mode()

if args.conditioning_dropout_prob is not None:
    random_p = torch.rand(bsz, device=latents.device, generator=generator)
    prompt_mask = random_p < 2 * args.conditioning_dropout_prob
    prompt_mask = prompt_mask.reshape(bsz, 1, 1)
    null_conditioning = text_encoder(tokenize_captions([""]).to(accelerator.device))[0]
    encoder_hidden_states = torch.where(prompt_mask, null_conditioning, encoder_hidden_states)

    image_mask_dtype = original_image_embeds.dtype
    image_mask = 1 - (
        (random_p >= args.conditioning_dropout_prob).to(image_mask_dtype)
        * (random_p < 3 * args.conditioning_dropout_prob).to(image_mask_dtype)
    )
    image_mask = image_mask.reshape(bsz, 1, 1, 1)
    original_image_embeds = image_mask * original_image_embeds

差不多就是这样! 除了此处描述的差异之外,脚本的其余部分与 文本到图像 训练脚本非常相似,因此请随时查看以了解更多详细信息。 如果您想了解有关训练循环如何工作的更多信息,请查看 理解 pipelines, models 和 schedulers 教程,其中分解了去噪过程的基本模式。

启动脚本

一旦您对脚本的更改感到满意,或者如果您对默认配置感到满意,您就可以启动训练脚本了!🚀

本指南使用 fusing/instructpix2pix-1000-samples 数据集,它是 原始数据集 的较小版本。 如果您愿意,也可以创建和使用您自己的数据集(请参阅 创建用于训练的数据集 指南)。

MODEL_NAME 环境变量设置为模型的名称(可以是 Hub 上的模型 ID 或本地模型的路径),并将 DATASET_ID 设置为 Hub 上数据集的名称。 该脚本会创建所有组件(特征提取器、scheduler、文本编码器、UNet 等)并将其保存到您存储库的子文件夹中。

为了获得更好的结果,请尝试使用更大的数据集进行更长时间的训练。 我们仅在较小规模的数据集上测试过此训练脚本。


要使用 Weights and Biases 监控训练进度,请将 --report_to=wandb 参数添加到训练命令,并使用 --val_image_url 指定验证图像,并使用 --validation_prompt 指定验证 prompt。 这对于调试模型非常有用。

如果您在多个 GPU 上进行训练,请将 --multi_gpu 参数添加到 accelerate launch 命令。

accelerate launch --mixed_precision="fp16" train_instruct_pix2pix.py \
    --pretrained_model_name_or_path=$MODEL_NAME \
    --dataset_name=$DATASET_ID \
    --enable_xformers_memory_efficient_attention \
    --resolution=256 \
    --random_flip \
    --train_batch_size=4 \
    --gradient_accumulation_steps=4 \
    --gradient_checkpointing \
    --max_train_steps=15000 \
    --checkpointing_steps=5000 \
    --checkpoints_total_limit=1 \
    --learning_rate=5e-05 \
    --max_grad_norm=1 \
    --lr_warmup_steps=0 \
    --conditioning_dropout_prob=0.05 \
    --mixed_precision=fp16 \
    --seed=42 \
    --push_to_hub

训练完成后,您可以使用新的 InstructPix2Pix 进行推理

import PIL
import requests
import torch
from diffusers import StableDiffusionInstructPix2PixPipeline
from diffusers.utils import load_image

pipeline = StableDiffusionInstructPix2PixPipeline.from_pretrained("your_cool_model", torch_dtype=torch.float16).to("cuda")
generator = torch.Generator("cuda").manual_seed(0)

image = load_image("https://huggingface.co/datasets/sayakpaul/sample-datasets/resolve/main/test_pix2pix_4.png")
prompt = "add some ducks to the lake"
num_inference_steps = 20
image_guidance_scale = 1.5
guidance_scale = 10

edited_image = pipeline(
   prompt,
   image=image,
   num_inference_steps=num_inference_steps,
   image_guidance_scale=image_guidance_scale,
   guidance_scale=guidance_scale,
   generator=generator,
).images[0]
edited_image.save("edited_image.png")

您应该尝试不同的 num_inference_stepsimage_guidance_scaleguidance_scale 值,以查看它们如何影响推理速度和质量。 指导 scale 参数尤其重要,因为它们控制原始图像和编辑指令对编辑后图像的影响程度。

Stable Diffusion XL

Stable Diffusion XL (SDXL) 是一个强大的文本到图像模型,可以生成高分辨率图像,并且在其架构中添加了第二个文本编码器。 使用 train_instruct_pix2pix_sdxl.py 脚本来训练 SDXL 模型以遵循图像编辑指令。

有关 SDXL 训练脚本的更多详细信息,请参阅 SDXL 训练 指南。

下一步

恭喜您训练了自己的 InstructPix2Pix 模型! 🥳 要了解有关该模型的更多信息,以下内容可能会有所帮助:

< > 在 GitHub 上更新