Diffusers 文档
InstructPix2Pix
并获得增强的文档体验
开始使用
InstructPix2Pix
InstructPix2Pix 是一个 Stable Diffusion 模型,经过训练可以根据人类提供的指令编辑图像。例如,您的提示可以是“让云朵变得多雨”,模型将相应地编辑输入图像。该模型根据文本提示(或编辑指令)和输入图像进行条件化。
本指南将探讨 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(例如笔记本),您可以使用
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
:训练期间编辑图像和编辑提示的 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
差不多就是这样了!除了这里描述的差异之外,脚本的其余部分与文本到图像训练脚本非常相似,因此您可以随意查看它以获取更多详细信息。如果您想了解更多关于训练循环如何工作的信息,请查看理解管道、模型和调度器教程,该教程分解了去噪过程的基本模式。
启动脚本
一旦您对脚本的更改满意,或者您对默认配置满意,您就可以启动训练脚本了!🚀
本指南使用 fusing/instructpix2pix-1000-samples 数据集,它是原始数据集的一个较小版本。如果您愿意,您也可以创建并使用自己的数据集(请参阅创建训练数据集指南)。
将 MODEL_NAME
环境变量设置为模型的名称(可以是 Hub 上的模型 ID 或本地模型的路径),将 DATASET_ID
设置为 Hub 上数据集的名称。脚本会在您的存储库中创建一个子文件夹并保存所有组件(特征提取器、调度器、文本编码器、UNet 等)到其中。
为了获得更好的结果,请尝试使用更大的数据集进行更长时间的训练运行。我们只在小规模数据集上测试过此训练脚本。
要使用 Weights and Biases 监控训练进度,请在训练命令中添加 `--report_to=wandb` 参数,并使用 `--val_image_url` 指定验证图像,使用 `--validation_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_steps
、image_guidance_scale
和 guidance_scale
值,以了解它们如何影响推理速度和质量。引导比例参数尤其重要,因为它们控制原始图像和编辑指令对编辑图像的影响程度。
Stable Diffusion XL
Stable Diffusion XL (SDXL) 是一种功能强大的文本到图像模型,可生成高分辨率图像,并在其架构中添加了第二个文本编码器。使用 train_instruct_pix2pix_sdxl.py
脚本来训练 SDXL 模型以遵循图像编辑指令。
SDXL 训练脚本在 SDXL 训练指南中有更详细的讨论。
后续步骤
恭喜您训练了自己的 InstructPix2Pix 模型!🥳 要了解更多关于该模型的信息,可能会有帮助的
- 阅读使用 InstructPix2Pix 对 Stable Diffusion 进行指令微调这篇博客文章,了解我们对 InstructPix2Pix 所做的一些实验、数据集准备以及不同指令的结果。