Cheat sheets

Diffusion and Generative Models

Train and sample a VAE, a GAN, DDPM, latent diffusion and flow matching, then measure them. Toy Python from the lessons.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Latent diffusion with CFG#

cross attntwo epsT stepstrainadd noiseText encoderfrozen, CLIP orT5Noisy latentstarts as N(0, I)DenoiserU-Net or DiTCFG mixcond and uncondClean latent64 x 64 x 4VAE decoderlatent to pixelsImage512 x 512 x 3VAE encodertraining andimg2imgcross attntwo epsT stepstrainadd noiseText encoderfrozen, CLIP or T5Noisy latentstarts as N(0, I)DenoiserU-Net or DiTCFG mixcond and uncondClean latent64 x 64 x 4VAE decoderlatent to pixelsImage512 x 512 x 3VAE encodertraining and img2img

From Lesson 08.07, Lesson 08.02

DDPM train and sample#

1Schedulelinear $\beta_t$ from 1e-4 to 0.02 over $T$steps, then $\bar\alpha_t$.2Draw$x_0$ from data, $t$ at random, $\epsilon \sim\mathcal{N}(0, I)$.3Noisecompute $x_t$ in one shot from the closed form.4Predictthe net takes $x_t$ and a sinusoidal embeddingof $t$ and outputs $\hat\epsilon$.5Losssquared error between $\epsilon$ and$\hat\epsilon$, then a gradient step.6Start samplingdraw $x_T \sim \mathcal{N}(0, I)$.7Reverseapply the reverse step from $t = T$ to 1. Addnoise on every step except the last.

From Lesson 08.06, 08.06 code/main.py

Key formulas#

Forward
q(x_t \mid x_0) = \mathcal{N}\left( \sqrt{\bar\alpha_t} \, x_0, (1 - \bar\alpha_t) I \right)
Alpha bar
\bar\alpha_t = \prod_{s=1}^{t} (1 - \beta_s)
Simple loss
L_{\text{simple}} = \lVert \epsilon - \epsilon_\theta(x_t, t) \rVert^2
Reverse step
x_{t-1} = \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{\beta_t}{\sqrt{1 - \bar\alpha_t}} \epsilon_\theta(x_t, t) \right) + \sigma_t z
VAE loss
\lVert x - \hat{x} \rVert^2 + \beta \sum_i \frac{\sigma_i^2 + \mu_i^2 - \log \sigma_i^2 - 1}{2}
GAN game
\min_G \max_D \, \mathbb{E}[\log D(x)] + \mathbb{E}[\log(1 - D(G(z)))]
CFG
\epsilon_{\text{cfg}} = (1 + w) \epsilon_{\text{cond}} - w \epsilon_{\text{uncond}}
Flow matching
x_t = t x_1 + (1 - t) x_0, L = \lVert v_\theta(x_t, t) - (x_1 - x_0) \rVert^2

From Lesson 08.06, Lesson 08.02, Lesson 08.03, Lesson 08.07, Lesson 08.13

Tasks in code#

TaskCode
Noise x_0 to step tx_t = math.sqrt(a_bar) * x0 + math.sqrt(1 - a_bar) * eps
VAE reparameterize[m + s * e for m, s, e in zip(mu, sigma, eps)]
Non-saturating G loss-sum(math.log(max(p, 1e-8)) for p in d_fake) / len(d_fake)
Drop the label for CFGuse_c = NULL_CLASS if rng.random() < 0.1 else c
Mix with CFGeps_cfg = (1 + w) * eps_cond - w * eps_uncond
Flow matching targettarget = x1 - x0
Euler step, flowx -= dt * net_forward(x, t)
Tile the VAE decodepipe.vae.enable_tiling()

From 08.06 code/main.py, Lesson 08.02, Lesson 08.03, Lesson 08.07, 08.07 code/main.py, Lesson 08.13

DDPM schedule, noise and reverse loop#

betas = [1e-4 + (0.02 - 1e-4) * t / (T - 1) for t in range(T)]linear
alphas = [1 - b for b in betas]
alpha_bars, cum = [], 1.0
for a in alphas:
cum *= a
alpha_bars.append(cum)cumulative product
eps = rng.gauss(0, 1)training noise
x_t = math.sqrt(a_bar) * x0 + math.sqrt(1 - a_bar) * epsone shot
x = rng.gauss(0, 1)sampling starts at noise
for t in range(T - 1, -1, -1):T-1 down to 0
eps_hat, _ = forward([x], t_emb, net)predicted noise
mean = (x - beta_t / math.sqrt(1 - alpha_bars[t]) * eps_hat[0]) / math.sqrt(alphas[t])
x = mean + math.sqrt(beta_t) * rng.gauss(0, 1)only when t > 0

From 08.06 code/main.py

Samplers and steps#

SamplerSteps
DDPM1000 reverse steps in the paper
DDIM20 to 50, same training objective
DPM-Solver++10 to 20
UniPC8 to 16
Flow matching, Euler4 to 8 on straight paths
Rectified flow, 2 reflows2 to 4
Distillation, consistency1 to 4, needs retraining
VAE or GANone forward pass

From Lesson 08.06, Lesson 08.13, Lesson 08.02, Lesson 08.03

Defaults and numbers#

SettingDefaultNote
\beta start1e-4linear schedule
\beta end0.02x_T is close to \mathcal{N}(0, I)
Steps T1000the toy code uses 40
CFG scale w33 to 7 is the sweet spot
CFG label dropout10%null token in training
SD 1.x VAE scaling factor0.18215applied after encoding
LoRA rank r4-16attention layers, 64 to 128 for heavy fine tunes
FID sample count10klow N gives a falsely low FID

From Lesson 08.06, 08.06 code/main.py, Lesson 08.07, Lesson 08.08, Lesson 08.14

Troubleshooting#

SymptomCauseFix
z carries no information about xposterior collapse, KL winsanneal \beta from 0 to 1, or free bits
GAN makes one mode onlymode collapsenoise on D inputs, minibatch discrimination or WGAN-GP
G stops improving, D over 95% accuracyD is too strongcut the D learning rate by 2-5x
Saturated, oily imagesCFG too highkeep w at 3 to 7
Denoiser trains on wrong latent varianceVAE scaling factor missingapply the checkpoint scaling factor
NaNs from the SD 1.x VAE at 1024²fp16 castuse the fp16-fix VAE or bf16
LoRA has no effecttrained on another baseuse the matching base model
FID looks too goodN under 10kuse 10k samples or more and 3 seeds

From Lesson 08.02, Lesson 08.03, Lesson 08.07, Lesson 08.08, Lesson 08.14

Abbreviations#

VAE
Variational autoencoder. The encoder outputs a distribution, a KL term shapes the code space.
ELBO
Evidence lower bound. Reconstruction minus KL, a lower bound on \log p(x).
GAN
Generator G(z) and discriminator D(x) in a minimax game.
DDPM
Ho et al. 2020. Linear \beta, 1000 steps, U-Net.
DDIM
Non-Markov sampler. 20 to 50 steps, same training objective.
CFG
Classifier-free guidance. Mixes conditional and unconditional predictions.
DiT
Diffusion Transformer. A transformer over latent patches in place of the U-Net.
FID
Fréchet Inception Distance. Distance of Gaussian fits to real and generated features.

From Lesson 08.02, Lesson 08.03, Lesson 08.06, Lesson 08.07, Lesson 08.08, Lesson 08.14

Questions#

Why output log σ² and not σ?
The output stays unconstrained. Gradients die at σ near 0 with softplus.
Why are VAE samples blurry?
MSE reconstruction gives the mean of the plausible outputs.
Why diffuse in latent space?
The 64×64×4 latent needs about 64x fewer FLOPs for comparable quality.
Are flow matching and DDPM different?
For Gaussian paths they are algebraically equivalent.
How is FID computed?
\lVert \mu_r - \mu_g \rVert^2 + \mathop{\mathrm{Tr}}(\Sigma_r + \Sigma_g - 2 (\Sigma_r \Sigma_g)^{0.5}) on Inception-v3 features. Lower is better.

From Lesson 08.02, Lesson 08.07, Lesson 08.13, Lesson 08.14, Lesson 08.03

Tips#

  • Use the closed form KL. A Monte Carlo KL is 3x slower.
  • Give G fresh fakes at each step, or its gradients are stale.
  • Use a proper time embedding for images. Raw t fails.
  • Try the cosine schedule when quality plateaus.
  • Keep the sum of ControlNet weights near 1.0. Keep LoRA \alpha \le 1.5.
  • Report FID, CLIP score and human preference together.

From Lesson 08.02, Lesson 08.03, Lesson 08.06, Lesson 08.08, Lesson 08.14