The diffusion overview named three layers. This lecture is layer one: the forward process. Every later idea—denoising, DDPM training, img2img strength, SVD motion noise—is a use of the same Gaussian corruption. If you do not understand the schedule, you cannot debug “too noisy / too clean / burnt CFG” artifacts in Stable Diffusion or SDXL.
Volume 16 treated noise as a slider. Volume 17 treats it as a probability path: βt, ᾱt, and signal-to-noise ratio (SNR). Next lecture flips the arrow.
Learning Objectives
By the end of this lesson, students should be able to:
- Explain why diffusion uses isotropic Gaussian noise (closure, CLT, tractable KL).
- Define βt, αt = 1 − βt, and ᾱt = ∏s=1..t αs.
- Write and code the closed-form q(xt | x0) without simulating every intermediate step.
- Compare linear vs cosine β schedules and state what SNR means for training.
- Contrast variance-preserving (VP) DDPM noise with variance-exploding (VE) score-SDE noise at a conceptual level.
- Connect “noise strength” in img2img / SVD to a starting timestep, not to a different algorithm.
Noise, in diffusion, is almost always standard Gaussian ε ~ N(0, I) added according to a schedule. In discrete DDPM form, each forward step is q(xt | xt−1) = N(xt; √(1−βt) xt−1, βt I). Because Gaussians compose, the marginal from the clean sample is q(xt | x0) = N(xt; √ᾱt x0, (1−ᾱt) I). At t = T, ᾱT ≈ 0, so xT is nearly N(0, I)—the prior you sample from at inference.
Why Gaussian?
You could corrupt images with dropout, blur, or salt-and-pepper. Gaussian noise wins for three engineering reasons: (1) the sum of Gaussians is Gaussian, so many tiny steps collapse to one closed-form draw; (2) KL divergences between Gaussians are analytic, which is how the DDPM variational bound simplifies; (3) high-dimensional isotropic Gaussians concentrate on a thin shell, giving a well-behaved prior. The central limit theorem also says many small independent corruptions look Gaussian anyway—so you might as well model that directly.
The Schedule Alphabet
| Symbol | Meaning | Typical range |
|---|---|---|
| βt | Per-step noise variance (DDPM parameterization) | ~10−4 → ~0.02 (linear, T=1000) |
| αt | 1 − βt, residual signal scale this step | Just under 1 |
| ᾱt | ∏ αs, remaining signal variance from x0 | 1 at t=0 → ~0 at t=T |
| SNR(t) | ᾱt / (1 − ᾱt) | High (clean) → low (pure noise) |
| σt | Noise scale in some SDE / VE parameterizations | Grows with t (VE) |
Linear vs Cosine (and Why It Matters)
Linear β (Ho 2020)
- Simple: linspace(1e-4, 0.02).
- Destroys high frequencies early.
- Still the mental default for DDPM.
Cosine (Nichol & Dhariwal)
- Slower drop of ᾱt in early t.
- More training signal at mid noise.
- Common in improved DDPM / some SD stacks.
Later schedules
- Zero terminal SNR, offset noise.
- Logit-normal t sampling (SD3-class).
- Flow models use a different path—see FLUX.
VP vs VE, Briefly
Variance-preserving (VP) processes (classic DDPM) shrink the signal as they add noise so Var(xt) stays near 1 if x0 was scaled that way. Variance-exploding (VE) processes (NCSN / some SDEs) leave the signal and pile on increasing σt. Same intuition—destroy structure—different algebra. Stable Diffusion’s discrete samplers are VP-family. Score-SDE unification (Song et al.) shows both are discretizations of stochastic differential equations; you do not need the SDE to train SD, but it explains why many samplers exist.
Implementing Schedules and q_sample
Training never loops t = 1..t to build xt. That would be O(T) per example. Use the closed form. Keep ᾱ on CPU or GPU as a length-T buffer; index it with the batch of timesteps.
Noise as a Control, Not a Bug
In img2img you encode a real image (or latent), then partially noise it to some tstart < T and denoise from there. High strength ≈ large tstart ≈ more freedom to ignore the input. Low strength keeps layout. Inpainting noises only the masked region. SVD’s motion bucket / noise aug parameters perturb the conditioning image’s latent so the video can move. Same Gaussian, different mask in time or space.
Get the noise right
- Match train and sample schedules.
- Scale latents (SD’s 0.18215) before noising.
- Fix the RNG seed when you need reproducibility.
Common failure modes
- Wrong ᾱ indexing (off-by-one t).
- Forgetting VAE scaling → over/under noise.
- Assuming “more noise always = worse” (training needs all SNRs).
“We add a little Gaussian grain like a film filter, then the UNet sharpens it.” Film grain is tiny and optional. Diffusion noise at large t destroys almost all spatial structure—xT is not a noisy photo, it is a draw from the prior. The network does not “degrain”; it transports a Gaussian toward the data manifold, one SNR step at a time. Also: ε is usually the same dimensionality as x (or z), not a scalar volume knob.
Knowledge Check
- Short Answer: What is αt in terms of βt? Answer: αt = 1 − βt.
- True/False: You must simulate all t intermediate Gaussians to obtain xt from x0. Answer: False—the closed form q(xt|x0) is one draw.
- Multiple Choice: SNR(t) = ᾱt/(1−ᾱt) is typically: (a) increasing in t, (b) decreasing in t, (c) constant. Answer: (b).
- Short Answer: Give one reason diffusion uses Gaussian noise. Answer: Gaussians are closed under addition / KLs are analytic / CLT (any one of these).
- True/False: A linear β schedule and a cosine schedule produce the same ᾱt curve. Answer: False.
- Multiple Choice: Classic DDPM noise is: (a) variance-preserving, (b) variance-exploding only, (c) salt-and-pepper. Answer: (a).
- Short Answer: In img2img, what does a higher denoise strength correspond to? Answer: Starting the reverse process from a larger timestep t (more corruption of the input).
- Short Answer: What is ᾱt? Answer: The product of αs from s=1 to t (remaining signal scale from x0).
- Multiple Choice: At t = T with a well-chosen schedule, xT is approximately: (a) x0, (b) N(0, I), (c) the dataset mean. Answer: (b).
- True/False: Stable Diffusion noises RGB pixels at 512×512 during UNet training. Answer: False—it noises the VAE latent (after scaling).
Key Takeaways
- Forward diffusion is a Gaussian Markov chain with a β schedule; ᾱt summarizes how much x0 remains.
- Always use the closed-form q(xt|x0) in training; never step noise one t at a time unless you are debugging.
- SNR(t) is the right language for “how hard is this timestep.” Linear vs cosine changes where the hard timesteps sit.
- Img2img, inpaint, and SVD motion controls are partial applications of the same noise, not new physics.
- Next: Denoising—predicting ε and walking back down t.
Hands-on idea: Plot ᾱt and SNR(t) for linear vs cosine on the same axes. Then show the same photo at t corresponding to SNR = 10, 1, 0.1, 0.01 for each schedule—students see that “t=400” is not a universal physical time.
Discussion prompt: If someone trains with cosine ᾱ but samples with a linear scheduler in diffusers, what breaks and why?
Recap: Noise is a scheduled Gaussian path from data to prior, fully determined by ᾱt. Continue with Denoising.