# Stable Diffusion XL

> [!WARNING]
> Ce script est expérimental, et il est facile de sur-apprendre et de rencontrer des problèmes tels que l'oubli catastrophique. Essayez d'explorer différents hyperparamètres pour obtenir les meilleurs résultats sur votre jeu de données.

[Stable Diffusion XL (SDXL)](https://hf.co/papers/2307.01952) est une itération plus grande et plus puissante du modèle Stable Diffusion, capable de produire des images en plus haute résolution.

Le UNet de SDXL est 3 fois plus volumineux et le modèle ajoute un second encodeur de texte à l'architecture. Selon le matériel dont vous disposez, cela peut être très intensif en calculs et il est possible que le modèle ne s'exécute pas sur un GPU grand public comme une Tesla T4. Pour aider à faire tenir ce modèle plus volumineux en mémoire et pour accélérer l'entraînement, essayez d'activer `gradient_checkpointing`, `mixed_precision` et `gradient_accumulation_steps`. Vous pouvez réduire encore davantage votre utilisation de la mémoire en activant l'attention efficace en mémoire avec [xFormers](../optimization/attention_backends) et en utilisant l'optimiseur 8 bits de [bitsandbytes'](https://github.com/TimDettmers/bitsandbytes).

Ce guide explore le script d’entraînement [train_text_to_image_sdxl.py](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_sdxl.py) afin de vous familiariser avec celui-ci et de vous montrer comment l’adapter à votre propre cas d’usage.

Avant d'exécuter le script, assurez-vous d'installer la bibliothèque à partir du code source :

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

Puis accédez au dossier d'exemple contenant le script d'entraînement et installez les dépendances requises pour le script que vous utilisez :

```bash
cd examples/text_to_image
pip install -r requirements_sdxl.txt
```

> [!TIP]
> 🤗 Accelerate est une bibliothèque qui vous aide à entraîner sur plusieurs GPU/TPU ou avec une précision mixte. Elle configure automatiquement votre configuration d'entraînement en fonction de votre matériel et de votre environnement. Consultez le [tour rapide](https://huggingface.co/docs/accelerate/quicktour) de 🤗 Accelerate pour en savoir plus.

Initialiser un environnement 🤗 Accelerate :

```bash
accelerate config
```

Pour configurer un environnement 🤗 Accelerate par défaut sans choisir de configuration :

```bash
accelerate config default
```

Sinon, si votre environnement ne prend pas en charge un shell interactif, comme un notebook, vous pouvez utiliser :

```py
from accelerate.utils import write_basic_config

write_basic_config()
```

Enfin, si vous souhaitez entraîner un modèle sur votre propre jeu de données, consultez le guide [Create a dataset for training](create_dataset) pour apprendre à créer un jeu de données compatible avec le script d'entraînement.

## Paramètres du script

> [!TIP]
> Les sections suivantes mettent en évidence les parties du script d'entraînement importantes pour comprendre comment le modifier, mais elles ne couvrent pas tous les aspects du script en détail. Si vous souhaitez en savoir plus, n'hésitez pas à lire le [script](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_sdxl.py) et à nous faire part de vos questions ou préoccupations.

Le script d’entraînement fournit de nombreux paramètres pour vous aider à personnaliser votre session d’entraînement. Tous les paramètres et leurs descriptions se trouvent dans la fonction [`parse_args()`](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L129). Cette fonction fournit des valeurs par défaut pour chaque paramètre, telles que la taille du lot d’entraînement et le taux d’apprentissage, mais vous pouvez également définir vos propres valeurs dans la commande d’entraînement si vous le souhaitez.

Par exemple, pour accélérer l’entraînement avec la précision mixte en utilisant le format bf16, ajoutez le paramètre `--mixed_precision` à la commande d’entraînement :

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

La plupart des paramètres sont identiques à ceux du guide d’entraînement [Text-to-image](text2image#script-parameters). Vous vous concentrerez donc, dans ce guide, sur les paramètres pertinents pour l’entraînement de SDXL.

- `--pretrained_vae_model_name_or_path` : chemin vers un VAE pré-entraîné ; le VAE de SDXL est connu pour souffrir d'instabilité numérique, ce paramètre vous permet donc de spécifier un [VAE](https://huggingface.co/madebyollin/sdxl-vae-fp16-fix) plus performant
- `--proportion_empty_prompts` : la proportion de prompts d'image à remplacer par des chaînes vides
- `--timestep_bias_strategy` : indique à quel moment (début ou fin) de la séquence de timesteps appliquer un biais, ce qui peut inciter le modèle à apprendre des détails de basse ou de haute fréquence
- `--timestep_bias_multiplier` : le poids du biais à appliquer au timestep
- `--timestep_bias_begin` : le timestep à partir duquel appliquer le biais
- `--timestep_bias_end` : le timestep à partir duquel l'application du biais se termine
- `--timestep_bias_portion` : la proportion de timesteps à laquelle appliquer le biais

### Pondération Min-SNR

La stratégie de pondération [Min-SNR](https://huggingface.co/papers/2303.09556) peut faciliter l’entraînement en rééquilibrant la perte pour obtenir une convergence plus rapide. Le script d’entraînement prend en charge la prédiction de `epsilon` (bruit) ou de `v_prediction`, mais Min-SNR est compatible avec les deux types de prédiction. Cette stratégie de pondération n’est prise en charge que par PyTorch.

Ajoutez le paramètre `--snr_gamma` et définissez-le à la valeur recommandée de 5,0 :

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

## Script d'entraînement

Le script d’entraînement est également similaire au guide d’entraînement [Text-to-image](text2image#training-script), mais il a été modifié pour prendre en charge l’entraînement de SDXL. Ce guide se concentrera sur le code propre au script d’entraînement de SDXL.

On commence par créer des fonctions pour [tokeniser les prompts](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L478) afin de calculer les embeddings de prompts, et pour calculer les embeddings d’images avec le [VAE](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L519). Ensuite, vous créerez une fonction pour [générer les poids des timesteps](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L531) en fonction du nombre de timesteps et de la stratégie de biais de timestep à appliquer.

Dans la fonction [`main()`](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L572), en plus du chargement d'un tokenizer, le script charge un second tokenizer et un encodeur de texte, car l'architecture SDXL en utilise deux de chaque :

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

Les [embeddings de prompt et d'image](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L857) sont d'abord calculés et conservés en mémoire, ce qui ne pose généralement pas de problème pour un jeu de données de petite taille, mais peut entraîner des problèmes de mémoire pour des jeux de données plus volumineux. Dans ce cas, vous devez enregistrer les embeddings précalculés sur le disque séparément et les charger en mémoire pendant le processus d'entraînement (voir cette [PR](https://github.com/huggingface/diffusers/pull/4505) pour plus de détails sur ce sujet).

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

Après le calcul des embeddings, l'encodeur de texte, le VAE et le tokenizer sont supprimés pour libérer de la mémoire :

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

Enfin, la [boucle d’entraînement](https://github.com/huggingface/diffusers/blob/aab6de22c33cc01fb7bc81c0807d6109e2c998c9/examples/text_to_image/train_text_to_image_sdxl.py#L943) s’occupe du reste. Si vous avez choisi d’appliquer une stratégie de biais sur les pas de temps, vous verrez que les poids des pas de temps sont calculés et ajoutés en tant que bruit :

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

Si vous souhaitez en savoir plus sur le fonctionnement de la boucle d’entraînement, consultez le tutoriel [Comprendre les pipelines, les modèles et les planificateurs](../using-diffusers/write_own_pipeline), qui détaille le schéma de base du processus de débruitage.

## Lancer le script

Une fois que vous avez apporté toutes vos modifications ou que vous êtes satisfait de la configuration par défaut, vous êtes prêt à lancer le script d’entraînement ! 🚀

Entraînons-nous sur le jeu de données [Naruto BLIP captions](https://huggingface.co/datasets/lambdalabs/naruto-blip-captions) pour générer vos propres personnages de Naruto. Définissez les variables d’environnement `MODEL_NAME` et `DATASET_NAME` sur le modèle et le jeu de données (soit depuis le Hub, soit un chemin local). Vous devez également spécifier un VAE autre que le VAE de SDXL (soit depuis le Hub, soit un chemin local) avec `VAE_NAME` afin d’éviter les instabilités numériques.

> [!TIP]
> Pour suivre la progression de l’entraînement avec Weights & Biases, ajoutez le paramètre `--report_to=wandb` à la commande d’entraînement. Vous devrez également ajouter `--validation_prompt` et `--validation_epochs` à la commande d’entraînement pour suivre les résultats. Cela peut s’avérer très utile pour déboguer le modèle et consulter les résultats intermédiaires.

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

Une fois l'entraînement terminé, vous pouvez utiliser votre nouveau modèle SDXL pour l'inférence !

```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) permet d’exécuter PyTorch sur des appareils XLA tels que les TPU, ce qui peut être plus rapide. L’étape de préchauffage initiale prend plus de temps car le modèle doit être compilé et optimisé. Cependant, les appels ultérieurs au pipeline sur une entrée **de la même longueur** que le prompt d’origine sont beaucoup plus rapides, car le graphe optimisé peut être réutilisé.

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

## Étapes suivantes

Félicitations pour l'entraînement d'un modèle SDXL ! Pour en savoir plus sur l'utilisation de votre nouveau modèle, les guides suivants peuvent s'avérer utiles :

- Lisez le guide [Stable Diffusion XL](../api/pipelines/stable_diffusion/stable_diffusion_xl) pour apprendre à l’utiliser pour diverses tâches (texte-vers-image, image-vers-image, inpainting), à utiliser son modèle de raffinement, ainsi que les différents types de micro-conditionnements.
- Consultez les guides d’entraînement [DreamBooth](dreambooth) et [LoRA](lora) pour apprendre à entraîner un modèle SDXL personnalisé à partir de quelques images d’exemple seulement. Ces deux techniques d’entraînement peuvent même être combinées !

