| name | cv-classifier-free-guidance-diffusion |
| description | Manual stable diffusion inference loop with classifier-free guidance that interpolates between unconditional and conditional noise predictions for controllable image generation |
Classifier-Free Guidance Diffusion
Overview
Classifier-free guidance (CFG) steers diffusion model generation toward a text prompt without a separate classifier. At each denoising step, the model predicts noise twice — once conditioned on the prompt, once unconditionally — and the final noise is an extrapolation: noise = uncond + scale * (cond - uncond). Higher guidance scales produce images more faithful to the prompt at the cost of diversity.
Quick Start
import torch
from torch.cuda.amp import autocast
uncond_input = tokenizer([""], padding="max_length", max_length=77, return_tensors="pt")
text_input = tokenizer([prompt], padding="max_length", max_length=77, truncation=True, return_tensors="pt")
with torch.no_grad():
uncond_emb = text_encoder(uncond_input.input_ids.cuda())[0]
text_emb = text_encoder(text_input.input_ids.cuda())[0]
text_embeddings = torch.cat([uncond_emb, text_emb])
latents = torch.randn(1, 4, 64, 64).cuda() * scheduler.init_noise_sigma
for i, t in enumerate(scheduler.timesteps):
inp = torch.cat([latents] * 2)
inp = scheduler.scale_model_input(inp, t)
with torch.no_grad():
noise_pred = unet(inp, t, encoder_hidden_states=text_embeddings).sample
uncond, cond = noise_pred.chunk(2)
noise_pred = uncond + 7.5 * (cond - uncond)
latents = scheduler.step(noise_pred, t, latents).prev_sample
Workflow
- Encode empty string and target prompt into text embeddings, concatenate
- Initialize random latents scaled by the scheduler's initial noise sigma
- For each timestep: duplicate latents, run UNet to get both unconditional and conditional noise predictions
- Interpolate:
noise = uncond + guidance_scale * (cond - uncond)
- Step the scheduler to update latents
- Decode final latents through VAE (scale by 1/0.18215 first)
Key Decisions
- Guidance scale: 7.5 is the standard default; 3-5 for more diversity, 10-15 for strict prompt adherence
- Scheduler: LMS, DDIM, or Euler-A — LMS is smooth, DDIM allows fewer steps, Euler-A adds stochasticity
- Inference steps: 20-50; diminishing returns beyond 50 for most schedulers
- VAE scaling: always divide latents by 0.18215 before decoding (SD v1.x convention)
References