# DDIMScheduler

[Denoising Diffusion Implicit Models](https://huggingface.co/papers/2010.02502) (DDIM) de Jiaming Song, Chenlin Meng et Stefano Ermon.

L'abstract de l'article est :

*Les modèles de diffusion probabiliste de débruitage (DDPM) ont atteint une génération d’images de haute qualité sans entraînement adversarial, mais ils nécessitent de simuler une chaîne de Markov sur de nombreuses étapes pour produire un échantillon. Pour accélérer l’échantillonnage, nous présentons les modèles de diffusion implicite de débruitage (DDIM), une classe plus efficace de modèles probabilistes implicites itératifs partageant la même procédure d’entraînement que les DDPM. Dans les DDPM, le processus génératif est défini comme l’inverse d’un processus de diffusion markovien. Nous construisons une classe de processus de diffusion non markoviens qui mènent au même objectif d’entraînement, mais dont le processus inverse peut être beaucoup plus rapide à échantillonner. Nous démontrons empiriquement que les DDIM peuvent produire des échantillons de haute qualité 10 à 50 fois plus rapidement en temps réel par rapport aux DDPM, nous permettent de faire un compromis entre le calcul et la qualité des échantillons, et peuvent effectuer une interpolation d’images sémantiquement significative directement dans l’espace latent.*

Le code source original de cet article est disponible sur [ermongroup/ddim](https://github.com/ermongroup/ddim), et vous pouvez contacter l'auteur sur [tsong.me](https://tsong.me/).

## Astuces

L’article [Common Diffusion Noise Schedules and Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) affirme qu’un décalage entre les paramètres d’entraînement et d’inférence entraîne des résultats de génération sous-optimaux pour Stable Diffusion. Pour y remédier, les auteurs proposent :

> [!WARNING]
> 🧪 Il s'agit d'une fonctionnalité expérimentale !

1. redimensionner le calendrier de bruit pour imposer un rapport signal à bruit (SNR) terminal nul

```py
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config, rescale_betas_zero_snr=True)
```

2. entraîner un modèle avec `v_prediction` (ajouter l'argument suivant aux scripts [train_text_to_image.py](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image.py) ou [train_text_to_image_lora.py](https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_lora.py))

```bash
--prediction_type="v_prediction"
```

3. changer le sampler pour qu'il démarre toujours à partir de la dernière étape

```py
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config, timestep_spacing="trailing")
```

4. rééchelonner le guidage sans classifieur pour éviter une surexposition

```py
image = pipe(prompt, guidance_rescale=0.7).images[0]
```

Par exemple :

```py
from diffusers import DiffusionPipeline, DDIMScheduler
import torch

pipe = DiffusionPipeline.from_pretrained("ptx0/pseudo-journey-v2", dtype=torch.float16)
pipe.scheduler = DDIMScheduler.from_config(
    pipe.scheduler.config, rescale_betas_zero_snr=True, timestep_spacing="trailing"
)
pipe.to("cuda")  # or "mps", "xpu", "cpu"

prompt = "A lion in galaxies, spirals, nebulae, stars, smoke, iridescent, intricate detail, octane render, 8k"
image = pipe(prompt, guidance_rescale=0.7).images[0]
image
```

## DDIMScheduler[[diffusers.DDIMScheduler]]

#### diffusers.DDIMScheduler[[diffusers.DDIMScheduler]]

```python
diffusers.DDIMScheduler(num_train_timesteps: int = 1000, beta_start: float = 0.0001, beta_end: float = 0.02, beta_schedule: str = 'linear', trained_betas: numpy.ndarray | list[float] | None = None, clip_sample: bool = True, set_alpha_to_one: bool = True, steps_offset: int = 0, prediction_type: typing.Literal['epsilon', 'sample', 'v_prediction'] = 'epsilon', thresholding: bool = False, dynamic_thresholding_ratio: float = 0.995, clip_sample_range: float = 1.0, sample_max_value: float = 1.0, timestep_spacing: typing.Literal['leading', 'trailing', 'linspace'] = 'leading', rescale_betas_zero_snr: bool = False)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L139)

**Paramètres :**

num_train_timesteps (`int`, par défaut 1000) : Le nombre d'étapes de diffusion pour entraîner le modèle.

beta_start (`float`, par défaut 0.0001) : valeur initiale de `beta` pour l'inférence.

beta_end (`float`, par défaut 0.02) : La valeur finale de `beta`.

beta_schedule (`Literal["linear", "scaled_linear", "squaredcos_cap_v2"]`, par défaut `"linear"`) : Le planning des bêtas, une correspondance entre une plage de bêtas et une séquence de bêtas pour faire avancer le modèle. Doit être l'un des éléments suivants : `"linear"`, `"scaled_linear"` ou `"squaredcos_cap_v2"`.

trained_betas (`np.ndarray`, *facultatif*) : Passez un tableau de bêtas directement au constructeur pour contourner `beta_start` et `beta_end`.

clip_sample (`bool`, par défaut `True`) : Applique un seuil à l'échantillon prédit pour la stabilité numérique.

clip_sample_range (`float`, par défaut 1.0) : L'amplitude maximale pour le rognage des échantillons. Valable uniquement lorsque `clip_sample=True`.

set_alpha_to_one (`bool`, par défaut `True`) : Chaque étape de diffusion utilise la valeur du produit des alphas à cette étape et à l'étape précédente. Pour l'étape finale, il n'y a pas d'alpha précédent. Lorsque cette option est `True`, le produit des alphas précédents est fixé à `1`, sinon il utilise la valeur de l'alpha à l'étape 0.

steps_offset (`int`, valeur par défaut 0) : Un décalage ajouté aux étapes d'inférence, tel que requis par certaines familles de modèles.

prediction_type (`Literal["epsilon", "sample", "v_prediction"]`, par défaut `"epsilon"`) : Type de prédiction de la fonction du planificateur. Doit être l'un des éléments suivants : `"epsilon"` (prédit le bruit du processus de diffusion), `"sample"` (prédit directement l'échantillon bruité) ou `"v_prediction"` (voir la section 2.4 de l'article [Imagen Video](https://huggingface.co/papers/2210.02303)).

thresholding (`bool`, par défaut `False`) : Indique s'il faut utiliser la méthode de « seuillage dynamique ». Cette méthode n'est pas adaptée aux modèles de diffusion en espace latent, tels que Stable Diffusion.

dynamic_thresholding_ratio (`float`, par défaut 0,995) : Le ratio pour la méthode de seuillage dynamique. Valable uniquement lorsque `thresholding=True`.

sample_max_value (`float`, par défaut 1.0) : La valeur de seuil pour le seuillage dynamique. Valable uniquement lorsque `thresholding=True`.

timestep_spacing (`Literal["leading", "trailing", "linspace"]`, par défaut `"leading"`) : La méthode de mise à l'échelle des timesteps. Doit être l'une des valeurs `"leading"`, `"trailing"` ou `"linspace"`. Consultez le tableau 2 de l'article [Common Diffusion Noise Schedules and Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) pour plus d'informations.

rescale_betas_zero_snr (`bool`, par défaut `False`) : Indique s'il faut rééchelonner les bêtas pour obtenir un SNR terminal nul. Cela permet au modèle de générer des échantillons très clairs et très sombres, au lieu de se limiter à des échantillons de luminosité moyenne. Lié de manière lâche à [`--offset_noise`](https://github.com/huggingface/diffusers/blob/74fd735eb073eb1d774b1ab4154a0876eb82f055/examples/dreambooth/train_dreambooth.py#L506).

`DDIMScheduler` étend la procédure de débruitage introduite dans les modèles probabilistes de diffusion de débruitage (DDPM) avec un guidage non markovien.

Ce modèle hérite de [SchedulerMixin](/docs/diffusers/v0.43.0/fr/api/schedulers/overview#diffusers.SchedulerMixin) et [ConfigMixin](/docs/diffusers/v0.43.0/fr/api/configuration#diffusers.ConfigMixin). Consultez la documentation de la classe parente pour les méthodes génériques que la bibliothèque implémente pour tous les planificateurs, telles que le chargement et l'enregistrement.

#### add_noise[[diffusers.DDIMScheduler.add_noise]]

```python
add_noise(original_samples: Tensor, noise: Tensor, timesteps: IntTensor)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L517)

**Paramètres :**

original_samples (`torch.Tensor`) : Les échantillons d'origine auxquels du bruit sera ajouté.

noise (`torch.Tensor`) : Le bruit à ajouter aux échantillons.

timesteps (`torch.IntTensor`) : Les pas de temps indiquant le niveau de bruit pour chaque échantillon.

**Retourne :** `torch.Tensor`

Les échantillons bruités.

Ajoutez du bruit aux échantillons d'origine en fonction de l'amplitude du bruit à chaque pas de temps (il s'agit du processus de diffusion avant).

#### get_velocity[[diffusers.DDIMScheduler.get_velocity]]

```python
get_velocity(sample: Tensor, noise: Tensor, timesteps: IntTensor)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L560)

**Paramètres :**

sample (`torch.Tensor`) : L'échantillon d'entrée.

noise (`torch.Tensor`) : Le tenseur de bruit.

timesteps (`torch.IntTensor`) : Les pas de temps pour le calcul de la vitesse.

**Retourne :** `torch.Tensor`

La vitesse calculée.

Calculer la prédiction de vitesse à partir de l'échantillon et du bruit selon la formule de vitesse.

#### scale_model_input[[diffusers.DDIMScheduler.scale_model_input]]

```python
scale_model_input(sample: Tensor, timestep: int = None)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L245)

**Paramètres :**

sample (`torch.Tensor`) : L'échantillon d'entrée.

timestep (`int`, *facultatif*) : L'étape temporelle actuelle dans la chaîne de diffusion.

**Retourne :** `torch.Tensor`

Un échantillon d'entrée mis à l'échelle.

Assure l'interchangeabilité avec les planificateurs qui doivent mettre à l'échelle l'entrée du modèle de débruitage en fonction de l'étape temporelle actuelle.

#### set_timesteps[[diffusers.DDIMScheduler.set_timesteps]]

```python
set_timesteps(num_inference_steps: int, device: typing.Union[str, torch.device] = None)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L334)

**Paramètres :**

num_inference_steps (`int`) : Le nombre d'étapes de diffusion utilisées lors de la génération d'échantillons avec un modèle pré-entraîné.

device (`str | torch.device`, *facultatif*) : L'appareil à utiliser pour les pas de temps.

**Levée :** ``ValueError``

- ``ValueError`` -- Si `num_inference_steps` est supérieur à `self.config.num_train_timesteps`.

Définit les pas de temps discrets utilisés pour la chaîne de diffusion (à exécuter avant l'inférence).

#### étape[[diffusers.DDIMScheduler.step]]

```python
step(model_output: Tensor, timestep: int, sample: Tensor, eta: float = 0.0, use_clipped_model_output: bool = False, generator: typing.Optional[torch.Generator] = None, variance_noise: typing.Optional[torch.Tensor] = None, return_dict: bool = True)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L384)

**Paramètres :**

model_output (`torch.Tensor`) : La sortie directe du modèle de diffusion appris.

timestep (`int`) : L'étape discrète actuelle dans la chaîne de diffusion.

sample (`torch.Tensor`) : Une instance actuelle d'un échantillon créé par le processus de diffusion.

eta (`float`, *facultatif*, valeur par défaut 0.0) : Le poids du bruit pour le bruit ajouté à l'étape de diffusion. Une valeur de 0 correspond à DDIM (déterministe) et 1 correspond à DDPM (entièrement stochastique).

use_clipped_model_output (`bool`, *facultatif*, valeur par défaut `False`) : Si `True`, calcule le `model_output` « corrigé » à partir de l'échantillon original prédit tronqué. Nécessaire car l'échantillon original prédit est tronqué à [-1, 1] lorsque `self.config.clip_sample` est `True`. Si aucun troncage n'a eu lieu, le `model_output` « corrigé » coïnciderait avec celui fourni en entrée et `use_clipped_model_output` n'a aucun effet.

generator (`torch.Generator`, *facultatif*) : Un générateur de nombres aléatoires pour un échantillonnage reproductible.

variance_noise (`torch.Tensor`, *facultatif*) : Alternative à la génération de bruit avec `generator` en fournissant directement le bruit pour la variance elle-même. Utile pour des méthodes telles que `CycleDiffusion`.

return_dict (`bool`, *facultatif*, par défaut `True`) : Indique s'il faut retourner un [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/fr/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) ou un `tuple`.

**Retourne :** [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/fr/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) ou `tuple`

If return_dict is `True`, [DDIMSchedulerOutput](/docs/diffusers/v0.43.0/fr/api/schedulers/ddim#diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput) est retourné, sinon un tuple est retourné dont le premier élément est le tenseur d'échantillon.

Prédit l'échantillon de l'étape temporelle précédente en inversant l'EDS. Cette fonction propage le processus de diffusion à partir des sorties du modèle appris (le plus souvent le bruit prédit).

## DDIMSchedulerOutput[[diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput]]

#### diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput[[diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput]]

```python
diffusers.schedulers.scheduling_ddim.DDIMSchedulerOutput(prev_sample: Tensor, pred_original_sample: typing.Optional[torch.Tensor] = None)
```

[Source](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/schedulers/scheduling_ddim.py#L33)

**Paramètres :**

prev_sample (`torch.Tensor` de forme `(batch_size, num_channels, height, width)` pour les images) : Échantillon calculé `(x_{t-1})` de l'étape temporelle précédente. `prev_sample` doit être utilisé comme entrée du modèle suivante dans la boucle de débruitage.

pred_original_sample (`torch.Tensor` de forme `(batch_size, num_channels, height, width)` pour les images) : l'échantillon débruité prédit `(x_{0})` basé sur la sortie du modèle à l'étape temporelle actuelle. `pred_original_sample` peut être utilisé pour prévisualiser la progression ou pour le guidage.

Classe de sortie pour la sortie de la fonction `step` du planificateur.

