# Stable Diffusion XL

> [!WARNING]
> Этот скрипт является экспериментальным, и с его помощью легко переобучить модель и столкнуться с проблемами, такими как катастрофическое забывание. Попробуйте исследовать различные гиперпараметры, чтобы получить наилучшие результаты на вашем наборе данных.

[Stable Diffusion XL (SDXL)](https://hf.co/papers/2307.01952) — это более крупная и мощная итерация модели Stable Diffusion, способная генерировать изображения с более высоким разрешением.

UNet в SDXL в 3 раза больше, а в архитектуру модели добавлен второй текстовый энкодер. В зависимости от доступного вам оборудования это может требовать значительных вычислительных ресурсов, и модель может не запуститься на потребительском GPU, таком как Tesla T4. Чтобы уместить эту более крупную модель в память и ускорить обучение, попробуйте включить `gradient_checkpointing`, `mixed_precision` и `gradient_accumulation_steps`. Вы можете ещё больше снизить потребление памяти, включив энергоэффективное внимание с помощью [xFormers](../optimization/attention_backends) и используя 8-битный оптимизатор от [bitsandbytes'](https://github.com/TimDettmers/bitsandbytes).

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 или с использованием смешанной точности. Она автоматически настраивает среду обучения в зависимости от вашего оборудования и окружения. Подробнее можно узнать в [Кратком обзоре](https://huggingface.co/docs/accelerate/quicktour) 🤗 Accelerate.

Инициализируйте среду 🤗 Accelerate:

```bash
accelerate config
```

Чтобы настроить среду по умолчанию 🤗 Accelerate без выбора каких-либо конфигураций:

```bash
accelerate config default
```

Или, если ваша среда не поддерживает интерактивную оболочку, например, ноутбук, вы можете использовать:

```py
from accelerate.utils import write_basic_config

write_basic_config()
```

Наконец, если вы хотите обучить модель на собственном наборе данных, ознакомьтесь с руководством [Create a dataset for training](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; известно, что VAE в SDXL страдает от численной нестабильности, поэтому этот параметр позволяет указать более подходящую [VAE](https://huggingface.co/madebyollin/sdxl-vae-fp16-fix)
- `--proportion_empty_prompts`: доля текстовых подсказок для изображений, которые заменяются пустыми строками
- `--timestep_bias_strategy`: где (на более ранних или более поздних шагах) применять смещение, что может побуждать модель обучаться деталям с низкой или высокой частотой
- `--timestep_bias_multiplier`: вес смещения, применяемого к шагу
- `--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
```

## Скрипт обучения

Скрипт обучения также похож на руководство по обучению [Text-to-image](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 использует по два каждого:

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

Наконец, [цикл обучения](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)
```

Если вы хотите узнать больше о том, как работает цикл обучения, обратитесь к учебнику [Understanding pipelines, models and schedulers](../using-diffusers/write_own_pipeline), в котором подробно разбирается базовый паттерн процесса денойзинга.

## Запустите скрипт

Когда вы внесёте все изменения или решите оставить конфигурацию по умолчанию, можно запускать скрипт обучения! 🚀

Обучимся на датасете [Naruto BLIP captions](https://huggingface.co/datasets/lambdalabs/naruto-blip-captions), чтобы генерировать собственных персонажей Наруто. Установите переменные окружения `MODEL_NAME` и `DATASET_NAME` в значения модели и датасета (из Hub или локальный путь). Также с помощью `VAE_NAME` укажите VAE, отличный от SDXL VAE (из Hub или локальный путь), чтобы избежать численных нестабильностей.

> [!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) позволяет запускать PyTorch на устройствах XLA, таких как TPU, что может быть быстрее. Первый шаг прогрева занимает больше времени, так как модель должна быть скомпилирована и оптимизирована. Однако последующие вызовы пайплайна с входными данными **той же длины**, что и исходный промпт, выполняются значительно быстрее, поскольку можно повторно использовать оптимизированный граф.

```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), чтобы узнать, как использовать его для различных задач (генерация изображений по тексту, преобразование изображения в изображение, inpainting), как применять его модель-рефинер, а также о различных типах микро-условий.
- Ознакомьтесь с руководствами по обучению [DreamBooth](dreambooth) и [LoRA](lora), чтобы узнать, как обучить персонализированную модель SDXL всего на нескольких примерах изображений. Эти два метода обучения можно даже комбинировать!

