# 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 [Quick tour](https://huggingface.co/docs/accelerate/quicktour)를 참고하세요.

🤗 Accelerate 환경을 초기화합니다:

```bash
accelerate config
```

어떤 구성도 선택하지 않고 기본 🤗 Accelerate 환경을 설정하려면:

```bash
accelerate config default
```

또는 노트북과 같이 인터랙티브 셸을 지원하지 않는 환경에서는 다음을 사용할 수 있습니다:

```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) 함수에 있습니다. 이 부분이 학습 스크립트를 수정하여 자체 사용 사례에 맞게 조정하는 곳입니다.

스크립트 매개변수와 마찬가지로, [Text-to-image](text2image#training-script) 학습 가이드에서 학습 스크립트의 전체적인 흐름을 안내합니다. 대신 이 가이드에서는 InstructPix2Pix와 관련된 스크립트 부분을 살펴봅니다.

스크립트는 InstructPix2Pix의 추가 조건 이미지를 고려하여 UNet의 첫 번째 컨볼루션 레이어의 [입력 채널 수](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L445)를 수정하는 것으로 시작합니다:

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

마지막으로, [training loop](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L730)에서는 편집된 이미지를 latent space로 인코딩하는 것으로 시작합니다:

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

그 다음으로, 스크립트는 CFG를 지원하기 위해 원본 이미지와 편집 지침 임베딩에 dropout을 적용합니다. 이를 통해 모델이 편집 지침과 원본 이미지가 편집된 이미지에 미치는 영향을 조절할 수 있습니다.

```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` 값이 서로 다른 경우로 실험해 보시기 바랍니다. 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에 대한 실험, 데이터셋 준비, 다양한 지시어에 대한 결과를 자세히 알아보려면 [Instruction-tuning Stable Diffusion with InstructPix2Pix](https://huggingface.co/blog/instruction-tuning-sd) 블로그 포스트를 읽어보세요.

