# Stable Diffusion XL

> [!WARNING]
> このスクリプトは実験的なものであり、過学習やカタストロフィック・フォーゲッティングなどの問題に陥りやすいため、注意が必要です。データセットで最適な結果を得るために、さまざまなハイパーパラメータの探索をお試しください。

[Stable Diffusion XL (SDXL)](https://hf.co/papers/2307.01952)は、Stable Diffusionモデルのより大型で高性能なバージョンであり、より高解像度の画像を生成できます。

SDXLのUNetは3倍大きく、モデルはアーキテクチャに第2のテキストエンコーダーを追加しています。利用可能なハードウェアによっては、計算負荷が非常に高くなる場合があり、Tesla T4のようなコンシューマー向けGPUでは実行できない可能性があります。この大きなモデルをメモリに収め、トレーニングを高速化するために、`gradient_checkpointing`、`mixed_precision`、`gradient_accumulation_steps`を有効にすることを試してください。[xFormers](../optimization/attention_backends)でメモリ効率の高いアテンションを有効にし、[bitsandbytes'](https://github.com/TimDettmers/bitsandbytes)の8ビットオプティマイザーを使用することで、メモリ使用量をさらに削減できます。

This guide will explore the [train_text_to_image_sdxl.py](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_sdxl.py) training script to help you become more familiar with it, and how you can adapt it for your own use-case.

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

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

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

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

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

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

```bash
accelerate launch train_text_to_image_sdxl.py \
  --mixed_precision="bf16"
```

ほとんどのパラメータは[Text-to-image](text2image#script-parameters)のトレーニングガイドと同じですが、本ガイドではSDXLのトレーニングに関連するパラメータに焦点を当てます。

- `--pretrained_vae_model_name_or_path`: 事前学習済み VAE のパス。SDXL の VAE は数値的不安定性を生じることが知られているため、このパラメータによりより優れた [VAE](https://huggingface.co/madebyollin/sdxl-vae-fp16-fix) を指定できます。
- `--proportion_empty_prompts`: 画像プロンプトを空文字列に置き換える割合
- `--timestep_bias_strategy`: バイアスを適用するタイムステップの位置（初期か後期か）を指定します。これにより、モデルが低周波数または高周波数の詳細を学習するように促すことができます。
- `--timestep_bias_multiplier`: timestep に適用するバイアスの重み
- `--timestep_bias_begin`: バイアスを適用し始めるタイムステップ
- `--timestep_bias_end`: バイアスを適用する終了タイムステップ
- `--timestep_bias_portion`: バイアスを適用するタイムステップの割合

### Min-SNR重み付け

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

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

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

## 学習スクリプト

学習スクリプトは、[テキストから画像へ](text2image#training-script)の学習ガイドと似ていますが、SDXLの学習に対応するように修正されています。本ガイドでは、SDXLの学習スクリプト固有のコードに焦点を当てます。

プロンプトの埋め込みを計算するための[プロンプトのトークン化](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L478)、および[VAE](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L519)を用いた画像埋め込みの計算を行う関数を作成することから始まります。次に、適用するタイムステップ数とタイムステップのバイアス戦略に応じて、[タイムステップの重みを生成する](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L531)関数を作成します。

[`main()`](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L572) 関数内では、トークナイザーの読み込みに加えて、SDXL アーキテクチャがそれぞれ2つを使用するため、2つ目のトークナイザーとテキストエンコーダーを読み込みます。

```py
tokenizer_one = AutoTokenizer.from_pretrained(
    args.pretrained_model_name_or_path, subfolder="tokenizer", revision=args.revision, use_fast=False
)
tokenizer_two = AutoTokenizer.from_pretrained(
    args.pretrained_model_name_or_path, subfolder="tokenizer_2", revision=args.revision, use_fast=False
)

text_encoder_cls_one = import_model_class_from_model_name_or_path(
    args.pretrained_model_name_or_path, args.revision
)
text_encoder_cls_two = import_model_class_from_model_name_or_path(
    args.pretrained_model_name_or_path, args.revision, subfolder="text_encoder_2"
)
```

[プロンプトと画像の埋め込み](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L857)は最初に計算され、メモリに保持されます。これは小規模なデータセットでは通常問題になりませんが、大規模なデータセットではメモリ問題を引き起こす可能性があります。その場合は、事前計算された埋め込みをディスクに個別に保存し、トレーニングプロセス中にメモリへ読み込むことをお勧めします（このトピックに関する詳細な議論については、この[PR](https://github.com/huggingface/diffusers/pull/4505)を参照してください）。

```py
text_encoders = [text_encoder_one, text_encoder_two]
tokenizers = [tokenizer_one, tokenizer_two]
compute_embeddings_fn = functools.partial(
    encode_prompt,
    text_encoders=text_encoders,
    tokenizers=tokenizers,
    proportion_empty_prompts=args.proportion_empty_prompts,
    caption_column=args.caption_column,
)

train_dataset = train_dataset.map(compute_embeddings_fn, batched=True, new_fingerprint=new_fingerprint)
train_dataset = train_dataset.map(
    compute_vae_encodings_fn,
    batched=True,
    batch_size=args.train_batch_size * accelerator.num_processes * args.gradient_accumulation_steps,
    new_fingerprint=new_fingerprint_for_vae,
)
```

埋め込みを計算した後、メモリを解放するために、テキストエンコーダー、VAE、トークナイザーを削除します:

```py
del text_encoders, tokenizers, vae
gc.collect()
torch.cuda.empty_cache()
```

最後に、[training loop](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L943)が残りの処理を担当します。タイムステップのバイアス戦略を適用することを選んだ場合、タイムステップの重みが計算され、ノイズとして加算されることを確認できます。

```py
weights = generate_timestep_weights(args, noise_scheduler.config.num_train_timesteps).to(
        model_input.device
    )
    timesteps = torch.multinomial(weights, bsz, replacement=True).long()

noisy_model_input = noise_scheduler.add_noise(model_input, noise, timesteps)
```

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

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

すべての変更が完了したか、デフォルトの設定で問題ない場合は、トレーニングスクリプトの起動準備が整いました! 🚀

[Naruto BLIP captions](https://huggingface.co/datasets/lambdalabs/naruto-blip-captions) データセットで学習し、独自のナルトキャラクターを生成しましょう。モデルとデータセット（Hub 由来またはローカルパス）をそれぞれ環境変数 `MODEL_NAME` と `DATASET_NAME` に設定します。また、数値的不安定さを避けるため、SDXL VAE 以外の VAE（Hub 由来またはローカルパス）を `VAE_NAME` で指定する必要があります。

> [!TIP]
> Weights & Biases でトレーニングの進捗を監視するには、トレーニングコマンドに `--report_to=wandb` パラメータを追加します。また、結果を追跡するために、トレーニングコマンドに `--validation_prompt` と `--validation_epochs` も追加する必要があります。これにより、モデルのデバッグや中間結果の確認に非常に役立ちます。

```bash
export MODEL_NAME="stabilityai/stable-diffusion-xl-base-1.0"
export VAE_NAME="madebyollin/sdxl-vae-fp16-fix"
export DATASET_NAME="lambdalabs/naruto-blip-captions"

accelerate launch train_text_to_image_sdxl.py \
  --pretrained_model_name_or_path=$MODEL_NAME \
  --pretrained_vae_model_name_or_path=$VAE_NAME \
  --dataset_name=$DATASET_NAME \
  --enable_xformers_memory_efficient_attention \
  --resolution=512 \
  --center_crop \
  --random_flip \
  --proportion_empty_prompts=0.2 \
  --train_batch_size=1 \
  --gradient_accumulation_steps=4 \
  --gradient_checkpointing \
  --max_train_steps=10000 \
  --use_8bit_adam \
  --learning_rate=1e-06 \
  --lr_scheduler="constant" \
  --lr_warmup_steps=0 \
  --mixed_precision="fp16" \
  --report_to="wandb" \
  --validation_prompt="a cute Sundar Pichai creature" \
  --validation_epochs 5 \
  --checkpointing_steps=5000 \
  --output_dir="sdxl-naruto-model" \
  --push_to_hub
```

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

```py
from diffusers import DiffusionPipeline
import torch

pipeline = DiffusionPipeline.from_pretrained("path/to/your/model", dtype=torch.float16).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "A naruto with green eyes and red legs."
image = pipeline(prompt, num_inference_steps=30, guidance_scale=7.5).images[0]
image.save("naruto.png")
```

[PyTorch XLA](https://pytorch.org/xla) を使用すると、TPU などの XLA デバイス上で PyTorch を実行でき、より高速に動作する場合があります。最初のウォームアップステップは、モデルのコンパイルと最適化が必要なため、時間がかかります。ただし、元のプロンプトと**同じ長さ**の入力に対する pipeline の後続の呼び出しは、最適化されたグラフを再利用できるため、大幅に高速になります。

```py
from diffusers import DiffusionPipeline
import torch
import torch_xla.core.xla_model as xm

device = xm.xla_device()
pipeline = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0").to(device)

prompt = "A naruto with green eyes and red legs."
start = time()
image = pipeline(prompt, num_inference_steps=inference_steps).images[0]
print(f'Compilation time is {time()-start} sec')
image.save("naruto.png")

start = time()
image = pipeline(prompt, num_inference_steps=inference_steps).images[0]
print(f'Inference time is {time()-start} sec after compilation')
```

## 次のステップ

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

- [Stable Diffusion XL](../api/pipelines/stable_diffusion/stable_diffusion_xl)のガイドを読み、さまざまなタスク（テキストから画像への変換、画像から画像への変換、インペインティング）での使い方、リファイナーモデルの使い方、および異なるタイプのマイクロコンディショニングについて学びましょう。
- [DreamBooth](dreambooth)と[LoRA](lora)のトレーニングガイドを参照し、わずか数枚のサンプル画像でパーソナライズされたSDXLモデルをトレーニングする方法を学びましょう。これらの2つのトレーニング手法は組み合わせることも可能です。

