# 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 の [クイックツアー](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_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 のクロップ座標埋め込みに含める高さおよび幅の座標
- `--conditioning_image_column`: データセット内の条件付け画像の列
- `--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,
)
```

最後に、[学習ループ](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
```

トレーニングループの仕組みについてさらに詳しく知りたい場合は、デノイジングプロセスの基本的なパターンを解説している[パイプライン、モデル、スケジューラーの理解](../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チームによる実験結果の詳細については、[T2I-Adaptersを用いたSDXL向けの効率的で制御可能な生成](https://huggingface.co/blog/t2i-sdxl-adapters)というブログ記事をお読みください。

