Aller au contenu principal

Module 6 — Modèles de diffusion : bruiter puis débruiter

Les modèles de diffusion ont détrôné les GAN sur la génération d'images entre 2020 et 2022. Leur idée fondatrice est étonnamment simple : au lieu d'apprendre à générer une image en un coup, on apprend à retirer un petit peu de bruit à chaque étape, et on répète. La difficulté n'est plus l'entraînement (stable) mais l'échantillonnage (coûteux), et toutes les avancées récentes visent à l'accélérer.

Deux processus, l'un connu, l'autre à apprendre

Le processus avant ajoute du bruit gaussien à une image en TT étapes (T=1000T = 1000 typiquement) :

q(xtxt1)=N ⁣(1βtxt1, βtI)q(x_t \mid x_{t-1}) = \mathcal{N}\!\left(\sqrt{1 - \beta_t}\, x_{t-1},\ \beta_t I\right)

Les βt\beta_t forment un planning croissant de 10410^{-4} à 21022 \cdot 10^{-2} typiquement. Après TT pas, xTx_T est indiscernable d'un bruit gaussien pur N(0,I)\mathcal{N}(0, I). Une propriété clé rend le processus utilisable : on peut tirer xtx_t directement depuis x0x_0 sans passer par les pas intermédiaires, grâce à αˉt=s=1t(1βs)\bar{\alpha}_t = \prod_{s=1}^{t} (1 - \beta_s) :

xt=αˉtx0+1αˉtε,εN(0,I)x_t = \sqrt{\bar{\alpha}_t}\, x_0 + \sqrt{1 - \bar{\alpha}_t}\, \varepsilon,\quad \varepsilon \sim \mathcal{N}(0, I)

Le processus arrière est celui qu'on apprend. Il essaie d'estimer q(xt1xt)q(x_{t-1} \mid x_t), qui n'a pas de forme close en général. La distribution vraie est intractable ; on la remplace par une gaussienne dont on apprend la moyenne, avec une variance fixée (ou apprise à part).

Ce que le réseau prédit vraiment

Voici le point qui simplifie tout et qui est à retenir. Plutôt que de prédire xt1x_{t-1} ou x0x_0, on entraîne un réseau εθ(xt,t)\varepsilon_\theta(x_t, t) à prédire le bruit ajouté au pas tt. C'est la formulation DDPM (Ho, 2020).

La perte prend une forme remarquablement simple, sans terme KL et sans variance :

L(θ)=Et,x0,ε ⁣[εεθ(xt,t)2]\mathcal{L}(\theta) = \mathbb{E}_{t, x_0, \varepsilon}\!\left[\| \varepsilon - \varepsilon_\theta(x_t, t) \|^2\right]

En pseudo-code, une itération d'entraînement tient en cinq lignes :

import torch
import torch.nn.functional as F

def perte_diffusion(modele, x0, alphas_barre, T):
t = torch.randint(0, T, (x0.size(0),), device=x0.device)
eps = torch.randn_like(x0)
a = alphas_barre[t].view(-1, 1, 1, 1)
x_t = a.sqrt() * x0 + (1 - a).sqrt() * eps
eps_pred = modele(x_t, t)
return F.mse_loss(eps_pred, eps)

Trois lignes de vérité importantes :

  • Le réseau ne voit jamais l'image propre x0x_0 pendant l'entraînement : il ne voit que xtx_t et le pas tt, et cherche à retrouver le bruit.
  • La perte est une MSE, la plus stable qu'on connaisse en deep learning ; c'est pourquoi les modèles de diffusion s'entraînent beaucoup plus tranquillement que les GAN.
  • L'ELBO théorique se simplifie à ce terme au prix d'une repondération implicite qui donne plus d'importance aux pas intermédiaires ; c'est un choix de Ho (2020) qui a mieux marché en pratique que la version pondérée par la vraie borne.

Le U-Net et le conditionnement par le pas de temps

L'architecture standard pour εθ\varepsilon_\theta est un U-Net avec des connexions de saut entre l'encodeur et le décodeur, des blocs résiduels, et souvent des couches d'attention aux résolutions basses. Ce qu'il faut ajouter par rapport au U-Net de segmentation : injecter l'information du pas tt à chaque bloc.

La méthode standard suit trois étapes. On construit un plongement sinusoïdal de tt (comme le positional encoding des transformers), on le passe dans deux couches denses pour produire un vecteur, puis on l'ajoute (ou on module) les activations des blocs résiduels. Sans ce conditionnement, le réseau ne sait pas quel niveau de bruit il doit retirer, et il échoue à couvrir la trajectoire.

def plongement_sinusoidal(t, dim):
demi = dim // 2
freqs = torch.exp(-torch.arange(demi, device=t.device) * (10.0 / demi))
angles = t.float().unsqueeze(1) * freqs.unsqueeze(0)
return torch.cat([angles.sin(), angles.cos()], dim=-1)

Échantillonner : DDPM contre DDIM

Générer une image consiste à partir de xTN(0,I)x_T \sim \mathcal{N}(0, I) et à appliquer TT pas de débruitage. La procédure DDPM est stochastique : chaque pas ré-injecte un peu de bruit.

xt1=1αt ⁣(xtβt1αˉtεθ(xt,t))+σtz,zN(0,I)x_{t-1} = \frac{1}{\sqrt{\alpha_t}}\!\left(x_t - \frac{\beta_t}{\sqrt{1 - \bar{\alpha}_t}}\, \varepsilon_\theta(x_t, t)\right) + \sigma_t z,\quad z \sim \mathcal{N}(0, I)

Le problème est la lenteur : 1000 passes avant du réseau pour une seule image. C'est là que DDIM (Song, 2021) intervient. En remarquant que l'équation d'échantillonnage peut être déterministe (σt=0\sigma_t = 0), on peut sauter des pas et n'en garder que 20 à 50 sans perte majeure de qualité.

ÉchantillonneurNb de pas typiqueStochastiqueReproductible
DDPM1000ouinon pour un même xTx_T
DDIM20-50nonoui pour un même xTx_T
DPM-Solver, UniPC10-20nonoui

Les échantillonneurs modernes (DPM-Solver 2024, UniPC) descendent jusqu'à une dizaine de pas avec des images encore convaincantes, en interprétant la diffusion comme une équation différentielle stochastique dont on cherche une meilleure intégration numérique.

Réutilisez le même bruit initial pour comparer

Pour comparer deux modèles de diffusion ou deux échantillonneurs, fixez torch.manual_seed(...) et tirez le même xTx_T pour les deux. Sans cela, la variance des images générées écrase les différences réelles. Sur DDIM avec la même graine, deux entraînements devraient produire des images visuellement proches, ce qui rend les régressions faciles à voir.

Diffusion latente : le passage à l'échelle

Faire tourner une diffusion pixel par pixel sur des images en 512×512512 \times 512 est prohibitif. La diffusion latente (Rombach, 2022, à la base de Stable Diffusion) coupe le problème en deux :

  1. Un autoencodeur (module 2, cette fois convolutif) compresse l'image en une carte latente 8 fois plus petite, par exemple 64×64×464 \times 64 \times 4.
  2. La diffusion s'apprend et s'échantillonne dans cet espace latent, pas dans l'espace pixel.
  3. Le décodeur de l'autoencodeur reconstruit l'image finale à partir du latent débruité.

Le gain de calcul est spectaculaire — deux ordres de grandeur — et la qualité perceptuelle reste comparable parce que l'autoencodeur préserve la structure sémantique. Cette architecture est le socle sur lequel repose presque toute la génération d'images de production actuelle, et c'est elle que le module suivant va conditionner par du texte.

En résumé

  • Un modèle de diffusion apprend à débruiter par petits pas ; le processus avant est fixé, seul le processus arrière est appris via un U-Net conditionné par le pas tt.
  • L'objectif se réduit à une MSE sur le bruit prédit εθ(xt,t)\varepsilon_\theta(x_t, t), ce qui explique la stabilité de l'entraînement comparée aux GAN.
  • L'échantillonnage DDPM est stochastique et lent (1000 pas) ; DDIM le rend déterministe et supporte 20-50 pas sans perte majeure.
  • La diffusion latente déplace le processus dans l'espace comprimé d'un autoencodeur, réduit le coût de deux ordres de grandeur et sert de socle à Stable Diffusion.

Module suivant : conditionner la génération par du texte pour passer de « générer une image » à « générer l'image décrite par une consigne ».