# InstructPix2Pix

[InstructPix2Pix](https://hf.co/papers/2211.09800) 是一个 Stable Diffusion 模型，经过训练可根据人类提供的指令编辑图像。例如，您的提示词可以是“让云变成雨云”，模型会相应地编辑输入图像。该模型以文本提示词（或编辑指令）和输入图像作为条件。

本指南将深入探讨 [train_instruct_pix2pix.py](https://github.com/huggingface/diffusers/blob/main/examples/instruct_pix2pix/train_instruct_pix2pix.py) 训练脚本，帮助你熟悉该脚本，并了解如何将其适配到你自己的使用场景中。

在运行脚本之前，请确保从源代码安装该库：

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

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

```bash
cd examples/instruct_pix2pix
pip install -r requirements.txt
```

> [!TIP]
> 🤗 Accelerate 是一个用于在多个 GPU/TPU 上训练或使用混合精度训练的库。它会根据你的硬件和环境自动配置训练设置。请查看 🤗 Accelerate 的 [快速入门](https://huggingface.co/docs/accelerate/quicktour) 以了解更多信息。

初始化一个 🤗 Accelerate 环境：

```bash
accelerate config
```

要设置一个默认的 🤗 Accelerate 环境，而不选择任何配置：

```bash
accelerate config default
```

或者，如果你的环境不支持交互式 shell（例如 notebook），你可以使用：

```py
from accelerate.utils import write_basic_config

write_basic_config()
```

最后，如果您想在自己的数据集上训练模型，请查看[创建训练数据集](create_dataset)指南，了解如何创建可与训练脚本配合使用的数据集。

> [!TIP]
> 以下各节重点介绍了训练脚本中对于理解如何修改脚本至关重要的部分，但并未详细涵盖脚本的每个方面。如果您希望了解更多，请随时阅读[脚本](https://github.com/huggingface/diffusers/blob/main/examples/instruct_pix2pix/train_instruct_pix2pix.py)，并告诉我们您是否有任何疑问或顾虑。

## 脚本参数

训练脚本包含许多参数，可帮助你自定义训练运行。所有参数及其说明均位于 [`parse_args()`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L65) 函数中。大多数参数都提供了默认值，效果相当不错，但你也可以在训练命令中设置自己的值。

例如，要提高输入图像的分辨率：

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

许多基础且重要的参数已在[文本到图像](text2image#script-parameters)训练指南中进行了说明，因此本指南仅聚焦于 InstructPix2Pix 的相关参数：

- `--original_image_column`：进行编辑之前的原始图像
- `--edited_image_column`：完成编辑后的图像
- `--edit_prompt_column`：用于编辑图像的指令
- `--conditioning_dropout_prob`：训练期间用于编辑图像和编辑提示的 dropout 概率，可为一个或两个条件输入启用 classifier-free guidance (CFG)

## 训练脚本

数据集预处理代码和训练循环位于 [`main()`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L374) 函数中。你需要在此处对训练脚本进行修改，以适配你自己的使用场景。

与脚本参数类似，[文本到图像](text2image#training-script)训练指南中提供了训练脚本的逐步讲解。本指南则着重介绍脚本中与 InstructPix2Pix 相关的部分。

该脚本首先修改 UNet 第一个卷积层的 [输入通道数](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L445)，以适配 InstructPix2Pix 的额外条件图像：

```py
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 参数由优化器进行[更新](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L545C1-L551C6)：

```py
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,
)
```

接下来，编辑后的图像和编辑指令会经过[预处理](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L624)和[分词](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L610C24-L610C24)。重要的是，原始图像和编辑后的图像必须应用相同的图像变换。

```py
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
```

最后，在 [训练循环](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L730) 中，它首先将编辑后的图像编码到潜在空间：

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

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

```py
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
```

基本上就是这样了！除了此处描述的不同之处外，脚本的其余部分与[文本生成图像](text2image#training-script)训练脚本非常相似，因此您可以随时查看该脚本以获取更多详细信息。如果您想深入了解训练循环的工作原理，请查看[理解流水线、模型和调度器](../using-diffusers/write_own_pipeline)教程，该教程详细解析了去噪过程的基本模式。

## 运行脚本

当你对脚本的修改感到满意，或者接受默认配置时，就可以启动训练脚本了！🚀

本指南使用 [fusing/instructpix2pix-1000-samples](https://huggingface.co/datasets/fusing/instructpix2pix-1000-samples) 数据集，它是 [原始数据集](https://huggingface.co/datasets/timbrooks/instructpix2pix-clip-filtered) 的缩小版本。您也可以创建并使用自己的数据集（参见 [创建训练数据集](create_dataset) 指南）。

将 `MODEL_NAME` 环境变量设置为模型名称（可以是 Hub 上的模型 id 或本地模型的路径），并将 `DATASET_ID` 设置为 Hub 上数据集的名称。该脚本会创建并保存所有组件（feature extractor、scheduler、text encoder、UNet 等）到仓库中的一个子文件夹中。

> [!TIP]
> 为了获得更好的效果，请尝试使用更大的数据集进行更长时间的训练。我们仅在较小规模的数据集上测试过此训练脚本。
>
> 
>
> 若要使用 Weights and Biases 监控训练进度，请在训练命令中添加 `--report_to=wandb` 参数，并通过 `--val_image_url` 指定验证图像，通过 `--validation_prompt` 指定验证提示词。这对于调试模型非常有用。

如果要在多块 GPU 上进行训练，请在 `accelerate launch` 命令中添加 `--multi_gpu` 参数。

```bash
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 进行推理：

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

pipeline = StableDiffusionInstructPix2PixPipeline.from_pretrained("your_cool_model", dtype=torch.float16).to("cuda")  # or "mps", "xpu", "cpu"
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`](https://github.com/huggingface/diffusers/blob/main/examples/instruct_pix2pix/train_instruct_pix2pix_sdxl.py) 脚本可以训练 SDXL 模型以遵循图像编辑指令。

SDXL 训练脚本在 [SDXL 训练](sdxl) 指南中有更详细的介绍。

## 后续步骤

恭喜您训练了自己的 InstructPix2Pix 模型！🥳 如需进一步了解该模型，您可以：

- 阅读[使用 InstructPix2Pix 对 Stable Diffusion 进行指令微调](https://huggingface.co/blog/instruction-tuning-sd)博客文章，以了解更多关于我们使用 InstructPix2Pix 进行的实验、数据集准备以及不同指令下的结果。

