# ControlNet

[ControlNet](https://hf.co/papers/2302.05543)モデルは、別の事前学習済みモデルの上に訓練されたアダプターです。追加の入力画像でモデルを条件付けすることで、画像生成に対する制御度を高めることができます。入力画像には、cannyエッジ、深度マップ、人間のポーズなど、さまざまなものを使用できます。

vRAM が限られた GPU で学習を行う場合は、学習コマンドで `gradient_checkpointing`、`gradient_accumulation_steps`、`mixed_precision` パラメータを有効にすることを推奨します。また、[xFormers](../optimization/attention_backends) を使用したメモリ効率の高いアテンションにより、メモリ使用量を削減することもできます。

このガイドでは、[train_controlnet.py](https://github.com/huggingface/diffusers/blob/main/examples/controlnet/train_controlnet.py) トレーニングスクリプトを詳しく見ていき、その内容に慣れるとともに、ご自身のユースケースに合わせてどのように適応させられるかを解説します。

スクリプトを実行する前に、ソースからライブラリをインストールしていることを確認してください。

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

次に、トレーニングスクリプトを含むサンプルフォルダに移動し、使用しているスクリプトに必要な依存関係をインストールします。

```bash
cd examples/controlnet
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/controlnet/train_controlnet.py)をぜひお読みいただき、ご質問やご懸念事項があればお知らせください。

## スクリプトのパラメータ

トレーニングスクリプトには、トレーニング実行をカスタマイズするための多くのパラメータが用意されています。すべてのパラメータとその説明は、[`parse_args()`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/controlnet/train_controlnet.py#L231)関数に記載されています。この関数は、トレーニングバッチサイズや学習率などの各パラメータにデフォルト値を設定していますが、必要に応じてトレーニングコマンドで独自の値を設定することもできます。

例えば、fp16 形式の混合精度でトレーニングを高速化するには、トレーニングコマンドに `--mixed_precision` パラメータを追加します。

```bash
accelerate launch train_controlnet.py \
  --mixed_precision="fp16"
```

基本的かつ重要なパラメータの多くは、[Text-to-image](text2image#script-parameters)のトレーニングガイドで説明されているため、本ガイドではControlNetに関連するパラメータに焦点を当てます。

- `--max_train_samples`: 学習サンプルの数。より高速な学習のためにこれを下げることができますが、非常に大規模なデータセットをストリーミングで扱う場合は、学習コマンドにこのパラメータと`--streaming`パラメータを含める必要があります。
- `--gradient_accumulation_steps`: バックワードパスの前に蓄積する更新ステップ数。これにより、GPUメモリが通常処理できる以上の大きなバッチサイズで学習できます。

### Min-SNR重み付け

[Min-SNR](https://huggingface.co/papers/2303.09556)重み付け戦略は、損失を再バランス化して収束を高速化することで、トレーニングを支援できます。トレーニングスクリプトは`epsilon`（ノイズ）または`v_prediction`の予測をサポートしていますが、Min-SNRはどちらの予測タイプにも対応しています。この重み付け戦略はPyTorchでのみサポートされています。

`--snr_gamma` パラメータを追加し、推奨値である 5.0 に設定します:

```bash
accelerate launch train_controlnet.py \
  --snr_gamma=5.0
```

## 学習スクリプト

スクリプトのパラメータと同様に、[Text-to-image](text2image#training-script)トレーニングガイドでは、トレーニングスクリプトの一般的な解説が提供されています。本ガイドでは、ControlNetスクリプトの関連する部分に焦点を当てて解説します。

学習スクリプトには、画像変換とキャプションのトークン化によってデータセットを前処理するための [`make_train_dataset`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/controlnet/train_controlnet.py#L582) 関数が含まれています。通常のキャプションのトークン化や画像変換に加えて、スクリプトには条件付け画像用の変換も含まれていることがわかります。

> [!TIP]
> TPU上でデータセットをストリーミングしている場合、画像に最適化されていない🤗 Datasetsライブラリがボトルネックとなり、パフォーマンスが低下する可能性があります。最大のスループットを確保するために、[WebDataset](https://github.com/webdataset/webdataset)、[TorchData](https://github.com/pytorch/data)、[TensorFlow Datasets](https://www.tensorflow.org/datasets/tfless_tfds)などの他のデータセット形式を検討することをお勧めします。

```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/64603389da01082055a901f2883c4810d1144edb/examples/controlnet/train_controlnet.py#L713) 関数内には、tokenizer、text encoder、scheduler、モデルを読み込むコードが含まれています。また、ControlNet モデルを既存の重みから読み込むか、UNet からランダムに初期化して読み込むかの処理もここで行われます。

```py
if args.controlnet_model_name_or_path:
    logger.info("Loading existing controlnet weights")
    controlnet = ControlNetModel.from_pretrained(args.controlnet_model_name_or_path)
else:
    logger.info("Initializing controlnet weights from unet")
    controlnet = ControlNetModel.from_unet(unet)
```

[optimizer](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/controlnet/train_controlnet.py#L871)は、ControlNetのパラメータを更新するように設定されています:

```py
params_to_optimize = controlnet.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/64603389da01082055a901f2883c4810d1144edb/examples/controlnet/train_controlnet.py#L943)では、条件付けテキストの埋め込みと画像が、ControlNet モデルのダウンブロックとミッドブロックに渡されます。

```py
encoder_hidden_states = text_encoder(batch["input_ids"])[0]
controlnet_image = batch["conditioning_pixel_values"].to(dtype=weight_dtype)

down_block_res_samples, mid_block_res_sample = controlnet(
    noisy_latents,
    timesteps,
    encoder_hidden_states=encoder_hidden_states,
    controlnet_cond=controlnet_image,
    return_dict=False,
)
```

トレーニングループの仕組みについてさらに詳しく知りたい場合は、デノイジングプロセスの基本的なパターンを解説している[パイプライン、モデル、スケジューラーの理解](../using-diffusers/write_own_pipeline)チュートリアルをご覧ください。

## スクリプトを実行します

これで学習スクリプトの起動準備が整いました! 🚀

このガイドでは[fusing/fill50k](https://huggingface.co/datasets/fusing/fill50k)データセットを使用しますが、必要に応じて独自のデータセットを作成して使用することもできます（[学習用データセットの作成](create_dataset)ガイドを参照してください）。

環境変数 `MODEL_NAME` に 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
```

スクリプトを実行する前に、もう1点だけ! 使用しているGPUの種類によっては、ControlNetの学習のために特定の最適化を有効にする必要がある場合があります。このスクリプトのデフォルト設定では、約38GBのvRAMが必要です。複数のGPUで学習を行う場合は、`accelerate launch`コマンドに`--multi_gpu`パラメータを追加してください。

16GBのGPUでは、bitsandbytesの8ビットオプティマイザーと勾配チェックポイントを使用して、トレーニングの実行を最適化できます。bitsandbytesをインストールします:

```py
pip install bitsandbytes
```

次に、トレーニングコマンドに次のパラメータを追加します。

```bash
accelerate launch train_controlnet.py \
  --gradient_checkpointing \
  --use_8bit_adam \
```

12GBのGPUでは、メモリ使用量を削減するために、bitsandbytesの8ビットオプティマイザー、勾配チェックポイント、xFormersを使用し、勾配をゼロではなく`None`に設定する必要があります。

```bash
accelerate launch train_controlnet.py \
  --use_8bit_adam \
  --gradient_checkpointing \
  --enable_xformers_memory_efficient_attention \
  --set_grads_to_none \
```

8GBのGPUでは、vRAM上の一部のテンソルをCPUまたはNVMEにオフロードして、GPUメモリを少なくしてトレーニングできるようにするため、[DeepSpeed](https://www.deepspeed.ai/)を使用する必要があります。

🤗 Accelerate 環境を設定するには、次のコマンドを実行してください:

```bash
accelerate config
```

設定時に、DeepSpeed stage 2 を使用することを確認してください。これにより、DeepSpeed stage 2、fp16 混合精度、およびモデルパラメータとオプティマイザ状態の CPU オフロードを組み合わせることで、8GB 未満の vRAM でトレーニングが可能になります。ただし、これにはより多くのシステム RAM（約 25 GB）が必要です。その他の設定オプションについては、[DeepSpeed ドキュメント](https://huggingface.co/docs/accelerate/usage_guides/deepspeed)を参照してください。設定ファイルは次のようになります。

```bash
compute_environment: LOCAL_MACHINE
deepspeed_config:
  gradient_accumulation_steps: 4
  offload_optimizer_device: cpu
  offload_param_device: cpu
  zero3_init_flag: false
  zero_stage: 2
distributed_type: DEEPSPEED
```

大幅な高速化のため、デフォルトの Adam オプティマイザーを DeepSpeed の最適化版である [`deepspeed.ops.adam.DeepSpeedCPUAdam`](https://deepspeed.readthedocs.io/en/latest/optimizers.html#adam-cpu) に変更することをお勧めします。`DeepSpeedCPUAdam` を有効にするには、システムの CUDA ツールチェーンのバージョンが、PyTorch にインストールされたものと一致している必要があります。

bitsandbytes の 8-bit オプティマイザーは、現時点では DeepSpeed と互換性がないようです。

以上です！トレーニングコマンドに追加のパラメータを指定する必要はありません。

```bash
export MODEL_DIR="stable-diffusion-v1-5/stable-diffusion-v1-5"
export OUTPUT_DIR="path/to/save/model"

accelerate launch train_controlnet.py \
 --pretrained_model_name_or_path=$MODEL_DIR \
 --output_dir=$OUTPUT_DIR \
 --dataset_name=fusing/fill50k \
 --resolution=512 \
 --learning_rate=1e-5 \
 --validation_image "./conditioning_image_1.png" "./conditioning_image_2.png" \
 --validation_prompt "red circle with blue background" "cyan circle with brown floral background" \
 --train_batch_size=1 \
 --gradient_accumulation_steps=4 \
 --push_to_hub
```

トレーニングが完了したら、新しく学習したモデルを推論に使用できます!

```py
from diffusers import StableDiffusionControlNetPipeline, ControlNetModel
from diffusers.utils import load_image
import torch

controlnet = ControlNetModel.from_pretrained("path/to/controlnet", dtype=torch.float16)
pipeline = StableDiffusionControlNetPipeline.from_pretrained(
    "path/to/base/model", controlnet=controlnet, dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"

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, num_inference_steps=20, generator=generator, image=control_image).images[0]
image.save("./output.png")
```

## Stable Diffusion XL

Stable Diffusion XL (SDXL) は高解像度の画像を生成する強力なテキストから画像へのモデルであり、そのアーキテクチャに第2のテキストエンコーダーを追加しています。SDXLモデル用のControlNetアダプターを学習するには、[`train_controlnet_sdxl.py`](https://github.com/huggingface/diffusers/blob/main/examples/controlnet/train_controlnet_sdxl.py) スクリプトを使用します。

SDXLの学習スクリプトについては、[SDXLの学習](sdxl)ガイドで詳しく説明しています。

## 次のステップ

ご自身のControlNetの学習が完了したことをお祝いします。新しいモデルの使用方法について詳しく知るために、以下のガイドが役立つ可能性があります：

- さまざまなタスクで推論を行う際に[ControlNetを使用する方法](../using-diffusers/controlnet)を学びましょう。

