Phase 08: Generative AI

Modèles de diffusion DDPM à partir de zéro

Ho, Jain, Abbeel (2020) a donné au champ une recette qu'il ne pouvait pas arrêter. Destruire les données avec du bruit sur mille petits pas. Formez un filet neuronal pour prédire le bruit. Inversez le processus à l'inférence. Aujourd'hui, chaque image, vidéo, 3D et modèle musical traditionnel fonctionne sur cette boucle, éventuellement avec des astuces de correspondance de flux ou de cohérence en haut.

Type: Build

Languages: Python

Prerequisites: Phase 3 · 02 (Backprop), Phase 8 · 02 (VAE)

Time: ~75 minutes

Le problème

Tu veux un échantillon pour p_data(x)Les GAN jouent un jeu de minimax qui diverge souvent. Les VAE produisent des échantillons flou à partir d'un décodeur gaussien. Ce que vous voulez vraiment, c'est un objectif d'entraînement qui est (a) une seule perte stable (pas de point de selle, pas de minimax), (b) une limite inférieure sur log p(x)(pour que vous ayez des probabilités), et (c) des échantillons correspondant à la qualité de la SOTA.

Sohl-Dickstein et coll. (2015) ont eu une réponse théorique: définir une chaîne Markov q(x_t | x_{t-1})qui ajoute progressivement le bruit gaussien, et entraîne une chaîne inversep_θ(x_{t-1} | x_t)Ho, Jain, Abbeel (2020) ont montré que la perte pouvait être simplifiée à une ligne prédire le bruit et nettoyé les mathématiques. En 2020 c'était une curiosité. En 2021 il a produit des échantillons de pointe. En 2022 il est devenu Stable Diffusion. En 2026 il est le substrat.

Le concept

!DDPM: forward noise, reverse denoise

Forward process q.Ajoutez le bruit gaussien TLa forme fermée la raison pour laquelle la mathématique est traitable est que la mesure cumulée est également gaussienne:

q(x_t | x_0) = N( sqrt(α̅_t) · x_0,  (1 - α̅_t) · I )

où α̅_t = ∏_{s=1..t} (1 - β_s)pour un calendrier de β_t- Je vous en prie .β_tde 1e-4 à 0,02 linéairement sur T=1000 étapes et x_Test approximativement N(0, I)- Je suis désolé .

Reverse process p_θ.Apprenez à utiliser un réseau neuronal .ε_θ(x_t, t)qui prédit le bruit qui a été ajouté.x_t, désigne par:

x_{t-1} = (1 / sqrt(α_t)) · ( x_t - (β_t / sqrt(1 - α̅_t)) · ε_θ(x_t, t) )  +  σ_t · z

où σ_test soit sqrt(β_t)L'expression est laide mais c'est juste l'algèbrex_{t-1}vu le retrait q(x_{t-1} | x_t, x_0)et en remplacement x_0avec son estimation prévue pour le bruit.

Training loss.

L_simple = E_{x_0, t, ε} [ || ε - ε_θ( sqrt(α̅_t) · x_0 + sqrt(1 - α̅_t) · ε,  t ) ||² ]

Pratique x_0à partir des données, choisissez un aléatoire t, échantillon ε ~ N(0, I), calculer le bruit x_tUne perte, pas de minimax, pas de KL, pas de trucs de réparamétrisation.

Sampling.Commencezx_T ~ N(0, I)- Répétez l' étape inverse de t = Tà 1- C'est fait.

Pourquoi ça marche ?

Trois intuitions:

  1. Denoising is easy; generating is hard.À t=TLes données sont de bruit pur, le réseau doit résoudre un problème trivial.t=0Le réseau ne doit nettoyer que quelques pixels.tLe problème est difficile mais le filet a de nombreux gradients qui circulent à travers les mêmes poids à partir de chaque niveau de bruit.
  1. Score matching in disguise.Vincent (2011) a prouvé que prédire le bruit équivaut à estimer∇_x log q(x_t | x_0)Le SDE inverse utilise ce score pour monter le gradient de densité une marche aléatoire guidée vers des régions à forte probabilité.
  1. The ELBO reduces to simple MSE.La limite inférieure variationnelle complète a un terme KL par étape temporelle. Avec la paramétrisation du DDPM, ces termes KL simplifient à MSE la prédiction du bruit avec des coefficients spécifiques; Ho a diminué les coefficients (appelant cela "perte simple") et la qualité améliorée.

Faites-le

code/main.pyLe réseau est un petit MLP qui prend(x_t, t)Le train est la perte d'une ligne.

Étape 1: calendrier anticipé (formule fermé)

pythonbetas = [1e-4 + (0.02 - 1e-4) * t / (T - 1) for t in range(T)]
alphas = [1 - b for b in betas]
alpha_bars = []
cum = 1.0
for a in alphas:
    cum *= a
    alpha_bars.append(cum)

Étape 2: échantillon x_ten une seule prise

pythondef forward_sample(x0, t, alpha_bars, rng):
    a_bar = alpha_bars[t]
    eps = rng.gauss(0, 1)
    x_t = math.sqrt(a_bar) * x0 + math.sqrt(1 - a_bar) * eps
    return x_t, eps

Étape 3: une étape de formation

pythondef train_step(x0, model, alpha_bars, rng):
    t = rng.randrange(T)
    x_t, eps = forward_sample(x0, t, alpha_bars, rng)
    eps_hat = model_forward(model, x_t, t)
    loss = (eps - eps_hat) ** 2
    return loss, gradient_step(model, ...)

Étape 4: prélèvement inverse

pythondef sample(model, alpha_bars, T, rng):
    x = rng.gauss(0, 1)
    for t in range(T - 1, -1, -1):
        eps_hat = model_forward(model, x, t)
        beta_t = 1 - alphas[t]
        x = (x - beta_t / math.sqrt(1 - alpha_bars[t]) * eps_hat) / math.sqrt(alphas[t])
        if t > 0:
            x += math.sqrt(beta_t) * rng.gauss(0, 1)
    return x

Pour un problème 1D avec 40 étapes de temps et un MLP de 24 unités, il apprend le mélange des deux modes en ~200 époques.

Conditionnement du temps

Le réseau doit savoir quel temps il détecte.

  • Sinusoidal embedding.Comme le codage positionnel de Transformer.embed(t) = [sin(t/ω_0), cos(t/ω_0), sin(t/ω_1), ...]Passer par un MLP, diffuser sur le net.
  • Film / group-norm conditioning.L'intégration de projet à l'échelle/bias par canal (FiLM) à chaque bloc.

Notre code jouet utilise le synusoïdal → concat.

Les pièges

  • Schedule matters a lot.Linear βLe calendrier de calcul de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de la valeur de cette valeur de cette valeur est de cette valeur est de cette valeur est de cette valeur est de cette valeur est de cette valeur est de cette valeur.
  • Timestep embedding is fragile.Passer cru tcomme un flot fonctionne pour le jouet 1-D mais ne fonctionne pas pour les images; utilisez toujours une intégration appropriée.
  • V-prediction vs ε-prediction.Pour les régimes étroits (très petits ou très grands t), εIl est très faible en signal-au-bruit.v = α·ε - σ·x) est plus stable; SDXL, SD3 et Flux l'utilisent.
  • Classifier-free guidance.Pour l'inférence, calculer à la fois conditionnelle et inconditionnelle εAlors ...ε_cfg = (1 + w) · ε_cond - w · ε_uncondavec w ≈ 3-7- C'est le sujet de la leçon 8.
  • 1000 steps is a lot.La production utilise du DDIM (20-50 étapes), du DPM-Solver (10-20 étapes) ou de la distillation (1-4 étapes). Voir leçon 12.

Utilisez-le

RoleTypical stack in 2026
Image pixel-space diffusion (small, toy)DDPM + U-Net
Image latent diffusionVAE encoder + U-Net or DiT (Lesson 07)
Video latent diffusionSpatiotemporal DiT (Sora, Veo, WAN)
Audio latent diffusionEncodec + diffusion transformer
Science (molecules, proteins, physics)Equivariant diffusion (EDM, RFdiffusion, AlphaFold3)

La diffusion est la colonne vertébrale générative universelle. Le flux de correspondance (leçon 13) est le concurrent 2024-2026 qui gagne généralement sur la vitesse d'inférence pour la même qualité.

La faire partir

  • Ça va .outputs/skill-diffusion-trainer.md. Les compétences prennent un ensemble de données + budget et des résultats de calcul: calendrier (linéaire/cosine/sigmoïde), objectif de prédiction (ε/v/x), nombre d'étapes, échelle de guidage, famille de prélèvements et protocole d'évaluation.

Exercices

  1. Easy.Changez le T de 40 à 10 en code/main.py- Comment la qualité de l'échantillon (histogramme visuel des sorties) se dégrade-t-elle ?
  2. Medium.Passez de la prédiction à la prédiction, faites la dérive inverse, comparez la qualité de l'échantillon final.
  3. Hard.Ajouter des instructions sans classifiant. Condition sur une étiquette de classe c ∈ {0, 1}, en la déduisant 10% du temps pendant la formation et lors de l'utilisation de l'échantillonnage ε = (1+w)·ε_cond - w·ε_uncond. Mesurer le taux de touches en mode conditionnel à w = 0, 1, 3, 7- Je suis désolé .

Les termes clés

TermWhat people sayWhat it actually means
Forward process"Adding noise"Fixed Markov chain q(x_t | x_{t-1}) that destroys the data.
Reverse process"Denoising"Learned chain p_θ(x_{t-1} | x_t) that reconstructs the data.
β schedule"The noise ladder"Per-step variance; linear, cosine, or sigmoid.
α̅"Alpha bar"Cumulative product ∏(1 - β); gives closed-form x_t from x_0.
Simple loss"MSE on noise"||ε - ε_θ(x_t, t)||²; all variational derivations collapse to this.
ε-prediction"Predict noise"Output is the noise added; standard DDPM.
V-prediction"Predict velocity"Output is α·ε - σ·x; better conditioning across t.
DDPM"The paper"Ho et al. 2020; linear β, 1000 steps, U-Net.
DDIM"Deterministic sampler"Non-Markov sampler, 20-50 steps, same training objective.
Classifier-free guidance"CFG"Mix conditional and unconditional noise predictions to amplify conditioning.

Note de production: l'inférence de diffusion est un problème de décompte par étapes

Le papier DDPM exécute T=1000 étapes inverses. Personne ne le fait en production. Chaque pile d'inférence réelle choisit une des trois stratégies et chaque carte détermine clairement le cadre de production de "d'où vient la latence":

  1. Faster sampler, same model.DDIM (20-50 étapes), DPM-Solver++ (10-20), UniPC (8-16).ε_θLes poids sont intacts, réduit la latence de 20 à 50 fois.
  2. Distillation.Formez un élève à correspondre à l'enseignant en moins d'étapes: Distillation progressive (2 → 1), Modèles de cohérence (arbitrary → 1-4), LCM, SDXL-Turbo, SD3-Turbo.
  3. Caching and compilation. torch.compile(unet, mode="reduce-overhead"), les arrière-plans de diffusion de TensorRT-LLM,xformersAttention SDPA, poids bf16. Coupe de latence par étape ~ 2x.

Pour un serveur de diffusion de production, la conversation budgétaire est la même que celle décrite dans la littérature de production pour les LLM: la latence est num_steps × step_cost + VAE_decode, le débit est batch_size × (num_steps × step_cost)^-1. Le TTFT est petit (une étape); l'équivalent TPOT est le temps de réponse complet car la génération d'images est " tout à la fois " du point de vue de l'utilisateur.

Pour en savoir plus

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.