Phase 08: Generative AI

Modelos de difusión DDPM desde cero

Ho, Jain, Abbeel (2020) dio al campo una receta que no podía dejar de hacer. Destruye los datos con ruido en mil pequeños pasos. Entrenar una red neuronal para predecir el ruido. Invertir el proceso a la inferencia. Hoy en día cada imagen, video, 3D y modelo musical corriente en este bucle, posiblemente con flujo de coincidencia o trucos de consistencia en la parte superior.

Type: Build

Languages: Python

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

Time: ~75 minutes

El problema

¿ Quieres una muestra para ?p_data(x)Los GAN juegan un juego de mínimas que a menudo divergen. Los VAEs producen muestras borrosas de un decodificador gaussiano. Lo que realmente se quiere es un objetivo de entrenamiento que es (a) una sola pérdida estable (sin punto de sella, sin mínimas), (b) un límite inferior en log p(x)(por lo que tiene probabilidades), y (c) muestras que coinciden con la calidad de SOTA.

Sohl-Dickstein et al. (2015) tenía una respuesta teórica: definir una cadena de Markov q(x_t | x_{t-1})que gradualmente añade ruido Gaussian, y entrenar una cadena inversap_θ(x_{t-1} | x_t)En el año 2020 se produjo muestras de última generación. En 2022 se convirtió en la difusión estable. En 2026 es el sustrato.

El concepto

!DDPM: forward noise, reverse denoise

Forward process q.Añadir el ruido Gaussian TLa forma cerrada la razón por la que la matemática es tratable es que el paso acumulativo es también gaussiano:

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

dondeα̅_t = ∏_{s=1..t} (1 - β_s)para un calendario de β_t- Escoge .β_tde 1e-4 a 0,02 linealmente en T=1000 pasos y x_Tes aproximadamente N(0, I)¿ Qué ?

Reverse process p_θ.Aprenda una red neuronal .ε_θ(x_t, t)que predice el ruido que se agregó.x_t, se denota por:

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

dondeσ_tes cualquiera sqrt(β_t)La expresión es fea pero es sólo álgebra resolver para x_{t-1}dado el posterior q(x_{t-1} | x_t, x_0)y sustituyendo x_0con su estimación de ruido prevista.

Training loss.

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

Muestra x_0de los datos, elige un aleatorio t, muestra ε ~ N(0, I), calcular el ruido .x_tEn un tiro a través de la forma cerrada, y regresar al ruido.

Sampling.Comienza .x_T ~ N(0, I). Iterar el paso inverso de t = T¿ Qué ?1- Ya lo he hecho.

Por qué funciona

Tres intuiciones:

  1. Denoising is easy; generating is hard.En elt=TLa red tiene que resolver un problema trivial.t=0La red sólo tiene que limpiar unos pocos píxeles.t, el problema es difícil pero la red tiene muchos gradientes que fluyen a través de los mismos pesos de cada nivel de ruido.
  1. Score matching in disguise.Vincent (2011) demostró que predecir el ruido es equivalente a estimar ∇_x log q(x_t | x_0), el puntaje. El SDE inverso utiliza este puntaje para subir el gradiente de densidad un paseo aleatorio guiado hacia regiones de alta probabilidad.
  1. The ELBO reduces to simple MSE.El límite inferior de variación completa tiene un término KL por paso de tiempo. Con la parámetriz de DDPM, esos términos KL se simplifican a MSE en predicción del ruido con coeficientes específicos; Ho redujo los coeficientes (llamándolo pérdida "simplificada") y la calidad mejorada.

Construye el mismo

code/main.pyLa red es una pequeña MLP que toma un(x_t, t)El entrenamiento es la pérdida de una línea.

Paso 1: el calendario anticipado (formulario cerrado)

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)

Paso 2: muestra x_ten un solo disparo

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

Paso 3: un paso de entrenamiento

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

Paso 4: muestreo inverso

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

Para un problema 1-D con 40 pasos de tiempo y una MLP de 24 unidades, esto aprende la mezcla de dos modos en ~200 épocas.

Condicionamiento del tiempo

La red necesita saber qué paso de tiempo está denonizando.

  • Sinusoidal embedding.Como el codificación de posición de Transformer.embed(t) = [sin(t/ω_0), cos(t/ω_0), sin(t/ω_1), ...]Pasar por una MLP, transmitir a la red.
  • Film / group-norm conditioning.El proyecto de incorporación a escala/bias por canal (FiLM) en cada bloque.

Nuestro código de juguete usa sinusoidal → concat.

Las trampas

  • Schedule matters a lot.Lineal βEs el DDPM predeterminado pero el cronograma cosino (Nichol & Dhariwal, 2021) da una mejor FID para el mismo cálculo.
  • Timestep embedding is fragile.Pasando en brutotcomo un flotador funciona para juguete 1-D pero no para imágenes; siempre use una incorporación adecuada.
  • V-prediction vs ε-prediction.Para regímenes estrechos (t muy pequeños o muy grandes), εEl sistema de predicción de V (v = α·ε - σ·x) es más estable; SDXL, SD3 y Flux lo utilizan.
  • Classifier-free guidance.En la inferencia, calcular tanto condicional como incondicional ε, entoncesε_cfg = (1 + w) · ε_cond - w · ε_uncondconw ≈ 3-7- Se trata de la Lección 8.
  • 1000 steps is a lot.La producción utiliza DDIM (20-50 pasos), DPM-Solver (10-20 pasos) o destilación (1-4 pasos).

Usalo

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 difusión es la columna vertebral generativa universal. La coincidencia de flujo (lección 13) es el competidor 2024-2026 que generalmente gana en velocidad de inferencia por la misma calidad.

Envío

Salva .outputs/skill-diffusion-trainer.md. La habilidad toma un conjunto de datos + presupuesto y resultados de cálculo: horario (lineal/cosino/sigmoide), objetivo de predicción (ε/v/x), número de pasos, escala de orientación, familia de muestras y un protocolo de evaluación.

Los ejercicios

  1. Easy.Cambiar T de 40 a 10 en code/main.py¿Cómo se degrada la calidad de la muestra (histograma visual de las salidas)?
  2. Medium.Cambiar de la predicción ε a la predicción v. Retomar el paso inverso. Comparar la calidad final de la muestra.
  3. Hard.Añadir una guía sin clasificador. Condición en una etiqueta de clase c ∈ {0, 1}, bajar el 10% del tiempo durante el entrenamiento y en el tiempo de muestreo de uso ε = (1+w)·ε_cond - w·ε_uncond. Medir la tasa de impacto en el modo condicional en w = 0, 1, 3, 7¿ Qué ?

Términos clave

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.

Nota de producción: la inferencia de difusión es un problema de recuento de pasos

El documento DDPM ejecuta T=1000 pasos invertidos. Nadie envía eso en producción. Cada pila de inferencias real elige una de tres estrategias y cada mapa limpio a la producción de enmarcado de "de dónde viene la latencia":

  1. Faster sampler, same model.DDIM (20-50 pasos), DPM-Solver++ (10-20), UniPC (8-16).ε_θLos pesos están intactos, reduce la latencia 20 a 50 veces.
  2. Distillation.Entrenar a un estudiante a coincidir con el maestro en menos pasos: Distillación progresiva (2 → 1), Modelos de consistencia (arbitrario → 1-4), LCM, SDXL-Turbo, SD3-Turbo.
  3. Caching and compilation. torch.compile(unet, mode="reduce-overhead"), los retrocesos de difusión de TensorRT-LLM,xformers/SDPA atención, bf16 pesos. Cortes por paso latencia ~ 2×.

Para un servidor de difusión de producción la conversación presupuestaria es la misma que la literatura de producción describe para LLM: la latencia es num_steps × step_cost + VAE_decode, el rendimiento es batch_size × (num_steps × step_cost)^-1. TTFT es pequeño (un paso); TPOT-equivalente es el tiempo de respuesta completo porque la generación de imágenes es "todo a la vez" desde la perspectiva del usuario.

Leer más

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.