# T2I-Adapter

[T2I-Adapter](https://hf.co/papers/2302.08453)는 이미지 생성을 더 잘 제어할 수 있도록 추가 조건 입력 이미지(라인 아트, canny, 스케치, 깊이, 포즈)를 제공하는 경량 어댑터 모델입니다. ControlNet과 유사하지만, UNet을 복사하여 학습하는 대신 가중치만 삽입하기 때문에 훨씬 작습니다(약 77M 파라미터, 약 300MB 파일 크기).

T2I-Adapter는 Stable Diffusion XL (SDXL) 모델로만 학습할 수 있습니다.

이 가이드에서는 [train_t2i_adapter_sdxl.py](https://github.com/huggingface/diffusers/blob/main/examples/t2i_adapter/train_t2i_adapter_sdxl.py) 학습 스크립트를 살펴보고, 이를 이해한 후 자신의 사용 사례에 맞게 수정하는 방법을 안내합니다.

…

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

이후 학습 스크립트가 포함된 예제 폴더로 이동하여 사용하는 스크립트에 필요한 의존성을 설치하세요:

```bash
cd examples/t2i_adapter
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/t2i_adapter/train_t2i_adapter_sdxl.py)를 읽어보시고, 질문이나 우려 사항이 있으시면 알려주시기 바랍니다.

## 스크립트 매개변수

학습 스크립트는 학습 실행을 사용자 정의하는 데 도움이 되는 많은 매개변수를 제공합니다. 모든 매개변수와 그 설명은 [`parse_args()`](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/t2i_adapter/train_t2i_adapter_sdxl.py#L233) 함수에서 찾을 수 있습니다. 학습 배치 크기나 학습률과 같이 각 매개변수에 대한 기본값을 제공하지만, 원하시는 경우 학습 명령에서 직접 값을 설정할 수도 있습니다.

예를 들어, gradient accumulation을 활성화하려면 학습 명령에 `--gradient_accumulation_steps` 매개변수를 추가합니다:

```bash
accelerate launch train_t2i_adapter_sdxl.py \
  ----gradient_accumulation_steps=4
```

기본적이고 중요한 대부분의 매개변수는 [텍스트-이미지](text2image#script-parameters) 학습 가이드에 설명되어 있으므로, 이 가이드에서는 관련 T2I-Adapter 매개변수에만 초점을 맞춥니다:

- `--pretrained_vae_model_name_or_path`: 사전 학습된 VAE의 경로; SDXL VAE는 수치적 불안정성이 있는 것으로 알려져 있으므로, 이 매개변수를 통해 더 나은 [VAE](https://huggingface.co/madebyollin/sdxl-vae-fp16-fix)를 지정할 수 있습니다
- `--crops_coords_top_left_h` 및 `--crops_coords_top_left_w`: SDXL의 crop 좌표 임베딩에 포함할 높이 및 너비 좌표
- `--conditioning_image_column`: 데이터셋에서 conditioning image가 포함된 열
- `--proportion_empty_prompts`: 빈 문자열로 대체할 이미지 프롬프트의 비율

## 학습 스크립트

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

학습 스크립트는 데이터셋을 준비하는 것으로 시작합니다. 여기에는 프롬프트를 [토큰화](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/t2i_adapter/train_t2i_adapter_sdxl.py#L674)하고 이미지와 조건 이미지에 [변환을 적용](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/t2i_adapter/train_t2i_adapter_sdxl.py#L714)하는 작업이 포함됩니다.

```py
conditioning_image_transforms = transforms.Compose(
    [
        transforms.Resize(args.resolution, interpolation=transforms.InterpolationMode.BILINEAR),
        transforms.CenterCrop(args.resolution),
        transforms.ToTensor(),
    ]
)
```

[`main()`](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/t2i_adapter/train_t2i_adapter_sdxl.py#L770) 함수 내에서 T2I-Adapter는 사전 학습된 어댑터에서 로드되거나 무작위로 초기화됩니다:

```py
if args.adapter_model_name_or_path:
    logger.info("Loading existing adapter weights.")
    t2iadapter = T2IAdapter.from_pretrained(args.adapter_model_name_or_path)
else:
    logger.info("Initializing t2iadapter weights.")
    t2iadapter = T2IAdapter(
        in_channels=3,
        channels=(320, 640, 1280, 1280),
        num_res_blocks=2,
        downscale_factor=16,
        adapter_type="full_adapter_xl",
    )
```

[optimizer](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/t2i_adapter/train_t2i_adapter_sdxl.py#L952)는 T2I-Adapter의 매개변수에 대해 초기화됩니다:

```py
params_to_optimize = t2iadapter.parameters()
optimizer = optimizer_class(
    params_to_optimize,
    lr=args.learning_rate,
    betas=(args.adam_beta1, args.adam_beta2),
    weight_decay=args.adam_weight_decay,
    eps=args.adam_epsilon,
)
```

마지막으로, [training loop](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/t2i_adapter/train_t2i_adapter_sdxl.py#L1086)에서는 어댑터 조건 이미지와 텍스트 임베딩을 UNet에 전달하여 노이즈 잔차를 예측합니다:

```py
t2iadapter_image = batch["conditioning_pixel_values"].to(dtype=weight_dtype)
down_block_additional_residuals = t2iadapter(t2iadapter_image)
down_block_additional_residuals = [
    sample.to(dtype=weight_dtype) for sample in down_block_additional_residuals
]

model_pred = unet(
    inp_noisy_latents,
    timesteps,
    encoder_hidden_states=batch["prompt_ids"],
    added_cond_kwargs=batch["unet_added_conditions"],
    down_block_additional_residuals=down_block_additional_residuals,
).sample
```

학습 루프가 어떻게 작동하는지 더 자세히 알고 싶다면, 디노이징 과정의 기본 패턴을 단계별로 설명하는 [Understanding pipelines, models and schedulers](../using-diffusers/write_own_pipeline) 튜토리얼을 확인해 보세요.

## 스크립트 실행

이제 학습 스크립트를 실행할 준비가 되었습니다! 🚀

이 예제 학습에서는 [fusing/fill50k](https://huggingface.co/datasets/fusing/fill50k) 데이터셋을 사용합니다. 원하시는 경우, 직접 데이터셋을 생성하여 사용할 수도 있습니다([학습용 데이터셋 만들기](create_dataset) 가이드 참고).

환경 변수 `MODEL_DIR`을 Hub의 모델 ID 또는 로컬 모델 경로로, `OUTPUT_DIR`을 모델을 저장할 위치로 설정합니다.

다음 이미지들을 다운로드하여 학습을 조건화하세요:

```bash
wget https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/controlnet_training/conditioning_image_1.png
wget https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/controlnet_training/conditioning_image_2.png
```

> [!TIP]
> Weights & Biases로 학습 진행 상황을 모니터링하려면 학습 명령에 `--report_to=wandb` 매개변수를 추가하세요. 결과를 추적하려면 학습 명령에 `--validation_image`, `--validation_prompt`, `--validation_steps`도 추가해야 합니다. 이는 모델 디버깅 및 중간 결과 확인에 매우 유용합니다.

```bash
export MODEL_DIR="stabilityai/stable-diffusion-xl-base-1.0"
export OUTPUT_DIR="path to save model"

accelerate launch train_t2i_adapter_sdxl.py \
 --pretrained_model_name_or_path=$MODEL_DIR \
 --output_dir=$OUTPUT_DIR \
 --dataset_name=fusing/fill50k \
 --mixed_precision="fp16" \
 --resolution=1024 \
 --learning_rate=1e-5 \
 --max_train_steps=15000 \
 --validation_image "./conditioning_image_1.png" "./conditioning_image_2.png" \
 --validation_prompt "red circle with blue background" "cyan circle with brown floral background" \
 --validation_steps=100 \
 --train_batch_size=1 \
 --gradient_accumulation_steps=4 \
 --report_to="wandb" \
 --seed=42 \
 --push_to_hub
```

학습이 완료되면 추론에 T2I-Adapter를 사용할 수 있습니다:

```py
from diffusers import StableDiffusionXLAdapterPipeline, T2IAdapter, EulerAncestralDiscreteSchedulerTest
from diffusers.utils import load_image
import torch

adapter = T2IAdapter.from_pretrained("path/to/adapter", dtype=torch.float16)
pipeline = StableDiffusionXLAdapterPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", adapter=adapter, dtype=torch.float16
)

pipeline.scheduler = EulerAncestralDiscreteSchedulerTest.from_config(pipe.scheduler.config)
pipeline.enable_xformers_memory_efficient_attention()
pipeline.enable_model_cpu_offload()

control_image = load_image("./conditioning_image_1.png")
prompt = "pale golden rod circle with old lace background"

generator = torch.manual_seed(0)
image = pipeline(
    prompt, image=control_image, generator=generator
).images[0]
image.save("./output.png")
```

## 다음 단계

T2I-Adapter 모델 학습을 완료하신 것을 축하드립니다! 🎉 더 자세히 알아보려면:

- T2I-Adapter 팀의 실험 결과에 대한 자세한 내용은 [SDXL에서 T2I-Adapters를 활용한 효율적이고 제어 가능한 생성](https://huggingface.co/blog/t2i-sdxl-adapters) 블로그 포스트를 참고하세요.

