LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 158 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/8
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/11
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageClustering and PCACore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/24
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernanceData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/8
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned Classifier
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/15
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/19
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning & Test-Time Compute
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
Back to Topics
LearnSystem Design CapstonesDiffusion Models: Images & Text
👁️HardMultimodal Models

Diffusion Models: Images & Text

Design a governed image-generation service while learning DDPM noising, stochastic sampling, latent diffusion, classifier-free guidance, DiT backbones, and text diffusion.

47 min read
Learning path
Step 152 of 158 in the full curriculum
Multimodal LLM ArchitectureReal-Time Voice AI Agent

Multimodal LLM Architecture showed how systems consume visual and audio evidence. Diffusion flips direction: it builds samples from conditioning signals by iteratively denoising a state.

Most learners meet diffusion through text-to-image systems. The same cleanup idea can also generate text by refining masked token blocks instead of predicting one token at a time.[1]Reference 1DiffusionGemmahttps://ai.google.dev/gemma/docs/diffusiongemma Start with a single image brightness value so you can compute the signal-to-noise trade by hand, then generalize that toy into full images and language.

Product brief: a governed design-asset generator

Design a service for product teams that creates synthetic campaign backgrounds and illustration previews. It must never present generated UI text, charts, or incident screenshots as verified evidence.

Requirements and API

  • POST /v1/image-jobs accepts prompt, negative_prompt, width, height, variant_count, route (preview or quality), seed, and an idempotency key. It returns job_id, accepted model and policy versions, and an estimated completion window.
  • GET /v1/image-jobs/{job_id} returns queued, running, review, failed, or complete, plus asset URLs, seed, sampler, step count, safety disposition, and synthetic-content label.
  • Preview requests target p95 first preview below 2 seconds. Quality jobs may take longer but must finish within 30 seconds or return a visible failure.
  • Prompts and outputs pass policy checks. Logo use, realistic UI claims, and safety-sensitive imagery route to review. Tenant data and fine-tune adapters stay isolated.

Data flow and sizing

The request path is API -> prompt policy -> route scheduler -> text encoder -> seeded latent -> repeated denoiser/scheduler steps -> VAE decode -> output policy -> object store -> job record. Store model, adapter, scheduler, policy, and seed versions with every asset so an operator can reproduce or explain it.

Size denoiser evaluations rather than HTTP requests alone. A peak of 20 preview jobs/s with 4 variants and a 6-step distilled route needs 20 x 4 x 6 = 480 denoiser evaluations/s. A smaller quality lane at 2 jobs/s with 4 variants, 50 steps, and ordinary two-pass CFG needs 2 x 4 x 50 x 2 = 800 evaluations/s. Separate queues prevent offline quality work from starving interactive previews.

Failure recovery, rollout, and evaluation

Admission is idempotent, so a client retry returns the same job. A worker may rerun an unpublished job from its stored seed and versioned configuration. A stochastic DDPM retry must restore the RNG state or restart the full sample; resuming with fresh noise changes the asset. Timeout, out-of-memory, or failed safety checks move the job to failed or review rather than publishing a partial image.

Roll out a new model or sampler against a frozen prompt suite, then shadow it, canary 1% of eligible jobs, expand to 10%, and finally ramp by route. Roll back on safety-policy regressions, memorization alerts, p95 latency breaches, or a material drop in human preference. Evaluation covers prompt adherence, human preference, diversity, text and layout fidelity, unsafe-output rate, memorization checks, p95 latency, failure rate, and cost per accepted asset.

A one-pixel forward process first

Before any transition kernels, fix one normalized pixel with brightness x0=1.0x_0 = 1.0x0​=1.0 and a known noise sample ϵ=−0.4\epsilon = -0.4ϵ=−0.4. At each noise level αˉ\bar{\alpha}αˉ, the closed-form mix is:

xt=αˉ x0+1−αˉ ϵx_t = \sqrt{\bar{\alpha}} \, x_0 + \sqrt{1 - \bar{\alpha}} \, \epsilonxt​=αˉ​x0​+1−αˉ​ϵ

αˉ\bar{\alpha}αˉSignal αˉ x0\sqrt{\bar{\alpha}}\,x_0αˉ​x0​Noise 1−αˉ ϵ\sqrt{1-\bar{\alpha}}\,\epsilon1−αˉ​ϵxtx_txt​SNR αˉ/(1−αˉ)\bar{\alpha}/(1-\bar{\alpha})αˉ/(1−αˉ)
0.90.949-0.1260.8229.0
0.50.707-0.2830.4241.0
0.0010.032-0.400-0.3680.001

At αˉ=0.5\bar{\alpha}=0.5αˉ=0.5, about half the original brightness remains and SNR is 1.0. At αˉ=0.001\bar{\alpha}=0.001αˉ=0.001, the pixel is almost pure noise. That is the whole forward story in miniature: larger forward-noising timesteps ask the model to recover structure from weaker and weaker signal.

adding-noise-gradually.py
1import json 2import math 3 4def forward_diffusion_value(x0: float, alpha_bar: float, epsilon: float) -> dict[str, float]: 5 signal = math.sqrt(alpha_bar) * x0 6 noise = math.sqrt(1 - alpha_bar) * epsilon 7 return { 8 "alpha_bar": alpha_bar, 9 "signal": round(signal, 3), 10 "noise": round(noise, 3), 11 "xt": round(signal + noise, 3), 12 "snr": round(alpha_bar / (1 - alpha_bar), 3), 13 } 14 15x0 = 1.0 16epsilon = -0.4 17steps = [ 18 forward_diffusion_value(x0, alpha_bar, epsilon) 19 for alpha_bar in [0.9, 0.5, 0.001] 20] 21 22print(json.dumps(steps, indent=2))
Output
1[ 2 { 3 "alpha_bar": 0.9, 4 "signal": 0.949, 5 "noise": -0.126, 6 "xt": 0.822, 7 "snr": 9.0 8 }, 9 { 10 "alpha_bar": 0.5, 11 "signal": 0.707, 12 "noise": -0.283, 13 "xt": 0.424, 14 "snr": 1.0 15 }, 16 { 17 "alpha_bar": 0.001, 18 "signal": 0.032, 19 "noise": -0.4, 20 "xt": -0.368, 21 "snr": 0.001 22 } 23]

Real images apply the same formula elementwise to every pixel or latent channel. Generation will later reverse the path: start near pure noise and clean structure back in step by step.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239

Latent diffusion path where prompt conditioning is reused across denoising steps, noisy latent grids become structured, and one final VAE decode produces pixels. Latent diffusion path where prompt conditioning is reused across denoising steps, noisy latent grids become structured, and one final VAE decode produces pixels.
Prompt conditioning is reused at every denoising step, and pixels appear only after one final VAE decode.

Why iterative refinement?

A natural first guess is to train a single neural network that maps a random vector straight to a 512x512 image. Generative Adversarial Networks (GANs) pair that generator with a discriminator. Their adversarial objective can be difficult to tune and can suffer mode collapse, while strong GAN implementations can still produce excellent samples. Diffusion changes the training objective and serving cost rather than guaranteeing better output for every domain.

Diffusion models take a different path. They don't ask the network to produce a clean image in one step. They ask it to remove a bit of noise, like undoing one row of the table above. Repeating that cleanup turns a random field into a structured image. The task at each step is much simpler, the training objective is a plain supervised loss, and the model naturally supports conditioning because the prompt can steer every step.

Classical DDPM training starts from an evidence lower bound (ELBO), a trainable lower bound on data log-likelihood, but its common simple objective is a noise-prediction regression loss derived from it. Unlike GANs, this removes the adversarial minimax game; it doesn't by itself prove coverage, memorization safety, or output suitability.

Generative models comparison

GANs, Variational Autoencoders (VAEs), and diffusion models make different trade-offs between sample quality, coverage, likelihood modeling, and inference cost. Treat the table as an architecture comparison, not a universal ranking:

FeatureGANsVAEsDiffusion Models
Training ObjectiveMinimax Game (Adversarial)ELBO (Evidence Lower Bound)Variational ELBO / MSE
Sample QualityCan be sharp; data and tuning dependentOften reconstruction-smoothedStrong results; model and sampler dependent
Coverage RiskMode collapse is an explicit riskCompression can remove detailMust evaluate diversity and memorization
Training BehaviorAdversarial instability riskStable reconstruction objectiveSupervised denoising objective
Inference WorkOne generator passOne decoder passRepeated denoiser evaluations unless accelerated
LikelihoodImplicitApproximateTractable lower bound

Forward diffusion process

Adding noise gradually

Forward diffusion resembles a drop of ink dispersing in water. At first, the ink is a structured blob (the data). Over time, it diffuses until the water is uniformly colored (pure noise). The single-pixel table above is that story for one brightness value. The formal process extends it to full tensors and draws its principles from non-equilibrium thermodynamics.[3]Reference 3Deep Unsupervised Learning using Nonequilibrium Thermodynamics.https://arxiv.org/abs/1503.03585

Starting from a clean image x0x_0x0​, we iteratively add Gaussian noise over TTT steps. This process is a fixed Markov chain, which is just a sequence where each new state depends only on the previous one, not on the full history. It gradually destroys structure until the data becomes indistinguishable from isotropic Gaussian noise, meaning random static that has the same variance on every pixel and every color channel.[3]Reference 3Deep Unsupervised Learning using Nonequilibrium Thermodynamics.https://arxiv.org/abs/1503.03585

Forward diffusion visual with five image tiles from clean structure to terminal Gaussian noise, plus signal and noise bars showing signal fading as noise grows. Forward diffusion visual with five image tiles from clean structure to terminal Gaussian noise, plus signal and noise bars showing signal fading as noise grows.
Forward diffusion gradually erases image structure while the noise term grows, and closed-form noising lets training jump straight to any timestep.

The transition kernel generalizes the one-pixel mix. Each step adds a little more Gaussian noise:

q(xt∣xt−1)=N(xt;1−βt⋅xt−1,βtI)q(x_t | x_{t-1}) = \mathcal{N}(x_t; \sqrt{1-\beta_t} \cdot x_{t-1}, \beta_t \mathbf{I})q(xt​∣xt−1​)=N(xt​;1−βt​​⋅xt−1​,βt​I)

Where βt\beta_tβt​ is the noise schedule. The original DDPM experiments used a linear schedule from β1=10−4\beta_1 = 10^{-4}β1​=10−4 to βT=0.02\beta_T = 0.02βT​=0.02 over T=1000T = 1000T=1000 steps; newer systems may choose different schedules.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239 Because the sum of Gaussians is also a Gaussian, the derivation can marginalize over intermediate steps. Let αt=1−βt\alpha_t = 1 - \beta_tαt​=1−βt​ and αˉt=∏s=1tαs\bar{\alpha}_t = \prod_{s=1}^{t} \alpha_sαˉt​=∏s=1t​αs​:

q(xt∣x0)=N(xt;αˉt⋅x0,(1−αˉt)I)q(x_t | x_0) = \mathcal{N}(x_t; \sqrt{\bar{\alpha}_t} \cdot x_0, (1 - \bar{\alpha}_t) \mathbf{I})q(xt​∣x0​)=N(xt​;αˉt​​⋅x0​,(1−αˉt​)I)

That is exactly the formula you already computed by hand: sample xtx_txt​ at any timestep ttt directly from x0x_0x0​ and one noise draw, without simulating every intermediate step. At t=Tt = Tt=T, αˉT≈0\bar{\alpha}_T \approx 0αˉT​≈0, so xT≈N(0,I)x_T \approx \mathcal{N}(0, \mathbf{I})xT​≈N(0,I) (pure isotropic Gaussian noise).

At small forward timestep ttt, the input still retains recognizable structure. At large forward ttt near TTT, it contains very little original signal. The SNR curve αˉt/(1−αˉt)\bar{\alpha}_t / (1 - \bar{\alpha}_t)αˉt​/(1−αˉt​) describes that spectrum without confusing forward time with the direction of reverse sampling.

Reverse process: learned denoising

DDPM training

Diffusion training learns the reverse process pθ(xt−1∣xt)p_\theta(x_{t-1} | x_t)pθ​(xt−1​∣xt​), which corresponds to denoising the image step-by-step.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239

The subtle point is that the exact reverse posterior q(xt−1∣xt)q(x_{t-1} \mid x_t)q(xt−1​∣xt​) is intractable because it marginalizes over every possible clean image x0x_0x0​ that could have produced xtx_txt​. What is tractable is q(xt−1∣xt,x0)q(x_{t-1} \mid x_t, x_0)q(xt−1​∣xt​,x0​), which stays Gaussian. DDPM uses that closed form in the derivation, then trains a model that predicts enough information from xtx_txt​ and ttt to approximate the reverse step without ever observing x0x_0x0​ at inference time.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239

The model doesn't have to predict the clean image x0x_0x0​ directly. In standard DDPM (Denoising Diffusion Probabilistic Models), the model predicts the noise component ϵ\epsilonϵ that was added at step ttt.

We train a neural network ϵθ(xt,t)\epsilon_\theta(x_t, t)ϵθ​(xt​,t) to predict the noise ϵ\epsilonϵ from a noisy input xtx_txt​:

Lsimple=Et,x0,ϵ[∥ϵ−ϵθ(xt,t)∥2]\mathcal{L}_{\text{simple}} = \mathbb{E}_{t, x_0, \epsilon}[\|\epsilon - \epsilon_\theta(x_t, t)\|^2]Lsimple​=Et,x0​,ϵ​[∥ϵ−ϵθ​(xt​,t)∥2]

In this formula, we sample a timestep ttt, a clean image x0x_0x0​, and noise ϵ\epsilonϵ, then train the network to predict that noise from the noisy input xtx_txt​. The squared error is averaged over many such samples.

In practice, people usually optimize the "simple" objective: an MSE loss on the predicted noise. It comes from simplifying and reweighting the original ELBO, but the implementation is just a supervised regression problem from xtx_txt​ to ϵ\epsilonϵ.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239 The training step samples a timestep, creates xt, asks the model to predict the known noise, and computes mean squared error:

ddpm-training.py
1import json 2 3def mse(true_values: list[float], predicted_values: list[float]) -> float: 4 squared_errors = [ 5 (true - predicted) ** 2 6 for true, predicted in zip(true_values, predicted_values, strict=True) 7 ] 8 return sum(squared_errors) / len(squared_errors) 9 10training_rows = [ 11 { 12 "timestep": 100, 13 "true_noise": [0.20, -0.10, 0.05], 14 "predicted_noise": [0.18, -0.08, 0.02], 15 }, 16 { 17 "timestep": 700, 18 "true_noise": [0.90, -0.40, 0.30], 19 "predicted_noise": [0.72, -0.35, 0.10], 20 }, 21] 22 23losses = [ 24 { 25 "timestep": row["timestep"], 26 "mse_loss": round(mse(row["true_noise"], row["predicted_noise"]), 4), 27 } 28 for row in training_rows 29] 30 31print(json.dumps(losses, indent=2))
Output
1[ 2 { 3 "timestep": 100, 4 "mse_loss": 0.0006 5 }, 6 { 7 "timestep": 700, 8 "mse_loss": 0.025 9 } 10]

The entire training step is a supervised regression problem. You know the exact noise ϵ\epsilonϵ you added, so the model has a ground-truth target. There is no adversarial game and no discriminator. The difficulty is that the same network must learn to denoise at every timestep ttt, from nearly-clean images to nearly-pure static.

Noise schedule and SNR

The schedule isn't just bookkeeping. In the closed-form forward equation, the signal coefficient is αˉt\sqrt{\bar{\alpha}_t}αˉt​​ and the noise coefficient is 1−αˉt\sqrt{1 - \bar{\alpha}_t}1−αˉt​​, so the effective signal-to-noise ratio at timestep ttt is:

SNR(t)=αˉt1−αˉt\mathrm{SNR}(t) = \frac{\bar{\alpha}_t}{1 - \bar{\alpha}_t}SNR(t)=1−αˉt​αˉt​​

High-SNR timesteps still contain recognizable structure. Low-SNR timesteps are close to pure noise. If the schedule destroys signal too quickly, many late timesteps become almost uninformative and the model spends capacity denoising inputs with very little semantic content left. That's why schedule design and loss weighting matter in practice: they decide where along the SNR curve the model spends most of its learning budget.

Line chart showing signal power falling and noise power rising across diffusion timesteps, explaining the signal-to-noise ratio schedule. Line chart showing signal power falling and noise power rising across diffusion timesteps, explaining the signal-to-noise ratio schedule.
Noise schedule shape decides where signal survives and where denoising becomes hardest.

Prediction targets

Original DDPM predicts ϵ\epsilonϵ directly.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239 That's not the only valid parameterization. Some systems predict the clean sample x0x_0x0​, and others predict a velocity-style target vvv, which is a different linear parameterization of the same reverse step.[4]Reference 4Progressive Distillation for Fast Sampling of Diffusion Models.https://arxiv.org/abs/2202.00512 These targets are mathematically convertible, but they change optimization behavior and how errors are distributed across timesteps. In interviews, it's often enough to explain that the scheduler still defines the reverse update, while the prediction target controls what the network is trained to output.

Sampling (reverse process)

To generate a new image, we start from pure noise xT∼N(0,I)x_T \sim \mathcal{N}(0, \mathbf{I})xT​∼N(0,I) and iteratively denoise it using the learned model. A DDPM reverse step includes both a learned mean and fresh stochastic noise on non-final steps:

xt−1=1αt(xt−βt1−αˉtϵθ(xt,t))+σtz,z∼N(0,I)\begin{aligned} 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, \\ z &\sim \mathcal{N}(0,\mathbf{I}) \end{aligned}xt−1​z​=αt​​1​(xt​−1−αˉt​​βt​​ϵθ​(xt​,t))+σt​z,∼N(0,I)​

Set z=0z=0z=0 for the final step into x0x_0x0​. The original formulation allows a chosen reverse variance; the scalar teaching example uses σt=βt\sigma_t=\sqrt{\beta_t}σt​=βt​​. Each step depends on the previous state, so the reverse process remains sequential even when denoiser calls are batched. A seeded random generator makes the stochastic trace reproducible:

sampling-reverse-process.py
1import json 2import math 3import random 4 5betas = [0.02, 0.03, 0.04] 6alphas = [1 - beta for beta in betas] 7alpha_bars: list[float] = [] 8running = 1.0 9for alpha in alphas: 10 running *= alpha 11 alpha_bars.append(running) 12 13def predicted_noise(x: float, step: int) -> float: 14 return 0.45 * x + 0.02 * step 15 16x = 1.25 17trace = [] 18rng = random.Random(7) 19for step in reversed(range(len(betas))): 20 beta_t = betas[step] 21 alpha_t = alphas[step] 22 alpha_bar_t = alpha_bars[step] 23 eps = predicted_noise(x, step) 24 mean = (x - (beta_t / math.sqrt(1 - alpha_bar_t)) * eps) / math.sqrt(alpha_t) 25 z = rng.gauss(0, 1) if step > 0 else 0.0 26 x = mean + math.sqrt(beta_t) * z 27 trace.append({ 28 "step": step, 29 "predicted_noise": round(eps, 3), 30 "reverse_mean": round(mean, 3), 31 "stochastic_z": round(z, 3), 32 "next_x": round(x, 3), 33 }) 34 35print(json.dumps(trace, indent=2))
Output
1[ 2 { 3 "step": 2, 4 "predicted_noise": 0.603, 5 "reverse_mean": 1.193, 6 "stochastic_z": -0.256, 7 "next_x": 1.141 8 }, 9 { 10 "step": 1, 11 "predicted_noise": 0.534, 12 "reverse_mean": 1.086, 13 "stochastic_z": 0.511, 14 "next_x": 1.174 15 }, 16 { 17 "step": 0, 18 "predicted_noise": 0.528, 19 "reverse_mean": 1.111, 20 "stochastic_z": 0.0, 21 "next_x": 1.111 22 } 23]

The original DDPM sampler evaluates the denoiser across its configured reverse chain, commonly presented with T=1000T=1000T=1000 steps. That baseline is expensive compared with one-pass generation and motivates sparse samplers and distilled models.

Model architectures: U-Net and DiT

The U-Net backbone

A denoiser must recover both layout and small spatial details. For a UI illustration scene, it needs to place panels and visual anchors coherently while preserving edges, textures, and lighting cues. A U-Net's down path builds broader context, its up path restores spatial resolution, and skip connections carry local cues around the deepest bottleneck.

For years, U-Net (U-shaped convolutional network with skip connections) has been the standard backbone for diffusion models. It combines a contracting path that builds context with an expanding path that restores spatial detail through skip connections, which makes it a strong fit for multiscale denoising. In text-conditioned image models, timestep embeddings modulate every residual block, and cross-attention is usually inserted at several resolutions so prompt tokens can steer both coarse layout and fine detail.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752

U-Net denoiser path showing down blocks building context, a mid block, up blocks restoring detail, and side conditioning from timestep and text at many blocks. U-Net denoiser path showing down blocks building context, a mid block, up blocks restoring detail, and side conditioning from timestep and text at many blocks.
U-Net builds context on the way down, restores detail on the way up, and keeps local cues through skip paths.

These are representative conditioning sites, not every single block. Stable Diffusion-style U-Nets use cross-attention in multiple down, middle, and up blocks rather than only at the bottleneck.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752

The Transformer shift (DiT)

DiT (Diffusion Transformer) doesn't mean "transformers are always better." It means the denoiser patchifies its input into tokens and processes them with transformer blocks instead of a convolutional U-Net. In the DiT experiments, increasing model compute improved Fréchet Inception Distance (FID), an image-quality metric where lower is better, for latent diffusion settings.[6]Reference 6Scalable Diffusion Models with Transformers.https://arxiv.org/abs/2212.09748 That's evidence for a scaling path, not a promise that a DiT is cheaper or better for every resolution, latency budget, or dataset.

A concrete published example is Stable Diffusion 3's MM-DiT (multimodal diffusion transformer). Instead of feeding text only through one-directional cross-attention, its text and image representations participate in a joint attention operation while retaining separate modality-specific weights.[7]Reference 7Scaling Rectified Flow Transformers for High-Resolution Image Synthesishttps://arxiv.org/abs/2403.03206 The SD3 authors report prompt-following, typography, and scaling results for that recipe; those measured results shouldn't be generalized to every transformer-based image generator.

Flow matching and rectified flow

DDPM frames generation as reversing a stochastic noising chain. Flow matching reframes it as learning a velocity field that transports samples along a path between a noise distribution and the data distribution.[8]Reference 8Flow Matching for Generative Modelinghttps://arxiv.org/abs/2210.02747 Rectified flow picks the simplest possible path: a straight line that interpolates noise x1∼N(0,I)x_1 \sim \mathcal{N}(0, \mathbf{I})x1​∼N(0,I) and data x0x_0x0​ as xτ=(1−τ)x0+τx1x_\tau = (1 - \tau) x_0 + \tau x_1xτ​=(1−τ)x0​+τx1​ for τ∈[0,1]\tau \in [0, 1]τ∈[0,1].[9]Reference 9Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flowhttps://arxiv.org/abs/2209.03003 The network is trained to predict the constant velocity x1−x0x_1 - x_0x1​−x0​ along that line, which is just another regression target much like ϵ\epsilonϵ or vvv:

LFM=Eτ,x0,x1[ ∥ vθ(xτ,τ)−(x1−x0) ∥2 ]\mathcal{L}_{\text{FM}} = \mathbb{E}_{\tau, x_0, x_1}\big[\,\|\,v_\theta(x_\tau, \tau) - (x_1 - x_0)\,\|^2\,\big]LFM​=Eτ,x0​,x1​​[∥vθ​(xτ​,τ)−(x1​−x0​)∥2]

Straight-line paths are designed to make numerical integration effective with fewer solver steps, but quality at any step count remains a measurement, not a guarantee. Stable Diffusion 3 reports rectified flow together with MM-DiT and a shifted timestep-sampling strategy.[7]Reference 7Scaling Rectified Flow Transformers for High-Resolution Image Synthesishttps://arxiv.org/abs/2403.03206 For interview purposes, connect flow matching to diffusion-style deployment concerns such as conditioning, latent representation, and sampler cost, while keeping their training objectives and scheduler equations distinct.

Text diffusion and DiffusionGemma

Image diffusion usually corrupts continuous pixel or latent values with Gaussian noise. Text is different because a sentence is a sequence of discrete token IDs. A text diffuser therefore uses a discrete corruption process, often replacing tokens with masks or sampling from categorical transitions, then trains a model to reconstruct the original tokens from noisy context.[10]Reference 10Structured Denoising Diffusion Models in Discrete State-Spaceshttps://arxiv.org/abs/2107.03006

Autoregressive language models generate left to right: p(xi∣x<i)p(x_i \mid x_{<i})p(xi​∣x<i​). Once token 12 is emitted, token 4 usually won't be revised. A diffusion language model starts from a noisy or masked sequence and refines many positions over several rounds. Each round can use context from both sides of a missing token, so the model can repair an earlier word after seeing later words.

Google's DiffusionGemma is a current open model using this idea. Google describes it as a 26B-parameter mixture-of-experts model with 4B active parameters per token that accepts text, image, and video inputs and generates text through discrete diffusion rather than left-to-right autoregressive decoding.[1]Reference 1DiffusionGemmahttps://ai.google.dev/gemma/docs/diffusiongemma[11]Reference 11DiffusionGemma Model Cardhttps://ai.google.dev/gemma/docs/diffusiongemma/model_card The public docs describe generation as iterative refinement over a target output canvas, with output lengths handled in 256-token blocks.[1]Reference 1DiffusionGemmahttps://ai.google.dev/gemma/docs/diffusiongemma

Autoregressive decoding commits tokens left to right while discrete text diffusion refines masked token slots over repeated passes. Autoregressive decoding commits tokens left to right while discrete text diffusion refines masked token slots over repeated passes.
Autoregressive decoding commits left to right, while text diffusion refines a whole token canvas over several passes.

The important systems difference is dependency shape. Autoregressive decoding has a hard sequential dependency between adjacent generated tokens. Text diffusion still needs multiple model passes, but each pass can update many uncertain positions in the block. That makes it attractive for high-throughput short or medium outputs, infilling, and editing workflows where bidirectional context matters. It also introduces new engineering questions: how long should the canvas be, how many refinement rounds are enough, and how should the UI handle text that can change across the whole block before it's final?

The toy example below isn't a language model. It shows only the state shape: a masked canvas gets refined in rounds, and later rounds can fill earlier positions after seeing surrounding context.

text-diffusion-refinement.py
1import json 2 3target = ["write", "unit", "tests", "first"] 4canvas = ["<mask>"] * len(target) 5update_plan = [ 6 {"round": 1, "positions": [0, 3]}, 7 {"round": 2, "positions": [1]}, 8 {"round": 3, "positions": [2]}, 9] 10 11trace = [] 12for step in update_plan: 13 for position in step["positions"]: 14 canvas[position] = target[position] 15 trace.append({ 16 "round": step["round"], 17 "canvas": " ".join(canvas), 18 "remaining_masks": canvas.count("<mask>"), 19 }) 20 21print(json.dumps(trace, indent=2))
Output
1[ 2 { 3 "round": 1, 4 "canvas": "write <mask> <mask> first", 5 "remaining_masks": 2 6 }, 7 { 8 "round": 2, 9 "canvas": "write unit <mask> first", 10 "remaining_masks": 1 11 }, 12 { 13 "round": 3, 14 "canvas": "write unit tests first", 15 "remaining_masks": 0 16 } 17]

Text diffusion shouldn't be described as "Stable Diffusion but with words." The forward corruption is discrete, the scheduler decides which token positions remain uncertain, and the output length often has to be planned up front. The shared idea is denoising; the data type, conditioning, and serving constraints are different.

Timestep conditioning

U-Net-style models usually encode the timestep ttt with a sinusoidal embedding, project it with an MLP, and use the result to modulate residual blocks through FiLM (Feature-wise Linear Modulation) or AdaGN (Adaptive Group Normalization). DiT carries the same timestep signal, but typically injects it through adaptive LayerNorm inside transformer blocks instead of GroupNorm-based residual blocks.[6]Reference 6Scalable Diffusion Models with Transformers.https://arxiv.org/abs/2212.09748 A framework-free scale-and-shift sketch makes the shared idea visible:

timestep-conditioning.py
1import json 2 3def modulate(features: list[float], scale: float, shift: float) -> list[float]: 4 return [round(value * (1 + scale) + shift, 3) for value in features] 5 6feature_map = [0.20, -0.10, 0.50] 7timestep_controls = { 8 "reverse_start_high_noise": {"scale": 0.50, "shift": -0.05}, 9 "reverse_end_low_noise": {"scale": 0.05, "shift": 0.02}, 10} 11 12outputs = { 13 name: modulate(feature_map, **control) 14 for name, control in timestep_controls.items() 15} 16 17print(json.dumps(outputs, indent=2))
Output
1{ 2 "reverse_start_high_noise": [ 3 0.25, 4 -0.2, 5 0.7 6 ], 7 "reverse_end_low_noise": [ 8 0.23, 9 -0.085, 10 0.545 11 ] 12}

This modulation acts like a global controller. Reverse sampling starts at large ttt with high noise, where the network must establish broad structure. It ends near t=0t=0t=0 with low noise, where the network refines texture and detail. In the forward noising direction, those same endpoints are called large or late ttt and small or early ttt, respectively, so naming the direction avoids an ambiguous word such as "early."

Classifier-free guidance (CFG)

How CFG steers generation without a classifier

How does the model know to draw an "oak dining table" and not a "red running shoe"? Early conditional diffusion systems used classifier guidance: they trained a separate image classifier on noisy inputs, then added the classifier's gradient into the sampling step to push the image toward a target label. That worked, but it required training and maintaining an extra classifier.

CFG (Classifier-Free Guidance) removes that extra classifier entirely. It gets a similar steering effect by training one denoiser to handle both conditional and unconditional prediction.[12]Reference 12Classifier-Free Diffusion Guidance.https://arxiv.org/abs/2207.12598

CFG works by training a single model to be both a conditional and an unconditional predictor. At inference time, we "extrapolate" away from the unconditional prediction toward the conditional one.

During training, we randomly drop the conditioning (e.g., a text prompt) with some probability puncondp_{uncond}puncond​ (typically 10%). In real text-to-image systems, the unconditional branch is usually represented by an empty-prompt embedding or a learned null token, not a literal all-zero vector. This batch mixes conditional and unconditional rows:

cfg-training-step.py
1import json 2import random 3 4def cfg_conditioning_batch(prompts: list[str], drop_prob: float, seed: int = 7) -> list[dict[str, str]]: 5 rng = random.Random(seed) 6 rows = [] 7 for prompt in prompts: 8 dropped = rng.random() < drop_prob 9 rows.append({ 10 "original_prompt": prompt, 11 "conditioning_used": "<null>" if dropped else prompt, 12 "branch": "unconditional" if dropped else "conditional", 13 }) 14 return rows 15 16batch = cfg_conditioning_batch( 17 [ 18 "oak dining table in soft light", 19 "oak dining table in natural light", 20 "mobile dashboard empty state", 21 "annotated latency chart hero image", 22 ], 23 drop_prob=0.35, 24) 25 26print(json.dumps(batch, indent=2))
Output
1[ 2 { 3 "original_prompt": "oak dining table in soft light", 4 "conditioning_used": "<null>", 5 "branch": "unconditional" 6 }, 7 { 8 "original_prompt": "oak dining table in natural light", 9 "conditioning_used": "<null>", 10 "branch": "unconditional" 11 }, 12 { 13 "original_prompt": "mobile dashboard empty state", 14 "conditioning_used": "mobile dashboard empty state", 15 "branch": "conditional" 16 }, 17 { 18 "original_prompt": "annotated latency chart hero image", 19 "conditioning_used": "<null>", 20 "branch": "unconditional" 21 } 22]

During sampling, we combine the conditional and unconditional predictions. Common guidance scales above 111 extrapolate beyond the conditional prediction:

ϵ^=ϵθ(xt,t,∅)+w⋅(ϵθ(xt,t,c)−ϵθ(xt,t,∅))\hat{\epsilon} = \epsilon_\theta(x_t, t, \emptyset) + w \cdot (\epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \emptyset))ϵ^=ϵθ​(xt​,t,∅)+w⋅(ϵθ​(xt​,t,c)−ϵθ​(xt​,t,∅))

Here, www is the guidance scale. When w=1w=1w=1, the equation reduces to just the conditional prediction ϵθ(xt,t,c)\epsilon_\theta(x_t, t, c)ϵθ​(xt​,t,c). When w>1w>1w>1, the model amplifies the difference between the conditional and unconditional predictions, actively pushing the generated image away from generic features and toward the specific meaning of the text prompt.

Watch the convention. This is the guidance-scale form used in Stable Diffusion and the diffusers library, where w=1w=1w=1 means no extra steering. The original paper writes the same thing as ϵ^=(1+w′)ϵθ(xt,t,c)−w′ϵθ(xt,t,∅)\hat{\epsilon} = (1 + w')\epsilon_\theta(x_t, t, c) - w' \epsilon_\theta(x_t, t, \emptyset)ϵ^=(1+w′)ϵθ​(xt​,t,c)−w′ϵθ​(xt​,t,∅), where w′=0w'=0w′=0 means no steering.[12]Reference 12Classifier-Free Diffusion Guidance.https://arxiv.org/abs/2207.12598 The two map exactly via w=1+w′w = 1 + w'w=1+w′, so a reported guidance scale of 7.57.57.5 here corresponds to w′=6.5w' = 6.5w′=6.5 in the paper's notation.

A concrete way to read the formula: if the unconditional prediction says "this patch looks like generic wood grain" and the conditional prediction says "this patch looks like oak grain," a guidance scale of w=7.5w = 7.5w=7.5 pushes the result seven and a half times farther along that direction. The patch becomes more distinctly oak-like rather than generic wood.

The practical implementation below shows the CFG extrapolation formula on short vectors. Real systems batch the unconditional and conditional inputs together for one forward pass, then split the two predictions before applying the same math.

cfg-guidance-formula.py
1import json 2 3def guided_noise( 4 unconditional: list[float], 5 conditional: list[float], 6 guidance_scale: float, 7) -> list[float]: 8 return [ 9 round(base + guidance_scale * (target - base), 3) 10 for base, target in zip(unconditional, conditional, strict=True) 11 ] 12 13noise_uncond = [0.20, -0.10, 0.05] 14noise_cond = [0.05, -0.35, 0.20] 15 16rows = [ 17 { 18 "guidance_scale": scale, 19 "guided_noise": guided_noise(noise_uncond, noise_cond, scale), 20 } 21 for scale in [0.0, 1.0, 7.5, 15.0] 22] 23 24print(json.dumps(rows, indent=2))
Output
1[ 2 { 3 "guidance_scale": 0.0, 4 "guided_noise": [ 5 0.2, 6 -0.1, 7 0.05 8 ] 9 }, 10 { 11 "guidance_scale": 1.0, 12 "guided_noise": [ 13 0.05, 14 -0.35, 15 0.2 16 ] 17 }, 18 { 19 "guidance_scale": 7.5, 20 "guided_noise": [ 21 -0.925, 22 -1.975, 23 1.175 24 ] 25 }, 26 { 27 "guidance_scale": 15.0, 28 "guided_noise": [ 29 -2.05, 30 -3.85, 31 2.3 32 ] 33 } 34]
Guidance Scale wwwEffect
0.0Unconditional sample. Ignores the prompt entirely.
1.0Pure conditional prediction. Good baseline, no extra CFG boost.
3.0 to 8.0Illustrative tuning range. Measure adherence, diversity, and artifacts for this model and route.
15.0+Over-guided. Higher artifact risk, oversaturation, and repeated textures.
Illustrative classifier-free guidance curves compare prompt adherence, diversity, and artifact risk as guidance scale rises, with low, balanced, and over-guided operating zones. Illustrative classifier-free guidance curves compare prompt adherence, diversity, and artifact risk as guidance scale rises, with low, balanced, and over-guided operating zones.
Low guidance drifts, middle guidance aligns, and high guidance oversteers.

DDIM: fast sampling

Diffusion sampler schedule comparison showing DDPM, DDIM, distillation, and consistency model routes as denoising state tiles with different numbers of reverse steps. Diffusion sampler schedule comparison showing DDPM, DDIM, distillation, and consistency model routes as denoising state tiles with different numbers of reverse steps.
Shorter samplers skip more of the reverse chain, so latency improves only if quality, editability, and control still pass evaluation.

Compare denoiser-evaluation budgets. The original DDPM setup is commonly demonstrated with about 1000 reverse steps; a DDIM deployment may try a sparse schedule such as 20 or 50 steps, while distilled or consistency models target still fewer. Whether a reduced schedule preserves acceptable quality depends on model, prompts, guidance, and evaluation slice.

DDIM (Denoising Diffusion Implicit Models) constructs a non-Markovian forward family with the same per-timestep marginals and training objective used by DDPM. Its reverse trajectory still updates one selected state into the next selected state. The practical difference is that generation can follow a shorter timestep subsequence, and one setting makes that trajectory deterministic.[13]Reference 13Denoising Diffusion Implicit Models.https://arxiv.org/abs/2010.02502

DDIM lets us skip steps. Instead of sampling t,t−1,t−2t, t-1, t-2t,t−1,t−2, the sampler can step t,t−Δ,t−2Δt, t-\Delta, t-2\Deltat,t−Δ,t−2Δ. This can reduce denoiser evaluations substantially; it doesn't eliminate the need to compare prompt adherence, detail preservation, and edit behavior against the slower baseline.

xt−1=αˉt−1⋅x^0⏟predicted x0+1−αˉt−1−σt2⋅ϵθ(xt,t)+σt⋅z\begin{aligned} x_{t-1} &= \sqrt{\bar{\alpha}_{t-1}} \cdot \underbrace{\hat{x}_0}_{\text{predicted } x_0} \\ &\quad + \sqrt{1 - \bar{\alpha}_{t-1} - \sigma_t^2} \cdot \epsilon_\theta(x_t, t) \\ &\quad + \sigma_t \cdot z \end{aligned}xt−1​​=αˉt−1​​⋅predicted x0​x^0​​​+1−αˉt−1​−σt2​​⋅ϵθ​(xt​,t)+σt​⋅z​

Where x^0\hat{x}_0x^0​ is the model's clean-image estimate, ϵθ(xt,t)\epsilon_\theta(x_t,t)ϵθ​(xt​,t) is the predicted noise direction, and σtz\sigma_t zσt​z injects randomness (or vanishes for deterministic DDIM when σt=0\sigma_t = 0σt​=0).

Setting σt=0\sigma_t = 0σt​=0 makes the trajectory deterministic. By bypassing the strict Markovian requirement, DDIM decoupled generation from the exact number of forward steps used during training. That means you can train on 1000 noise levels but sample on a sparse subset during deployment. The systems lesson is that training and inference schedules don't need to be identical.

Each step can require more than one denoiser evaluation. For ordinary CFG, a system needs conditional and unconditional predictions unless it batches or distills that work. Count evaluations before claiming an interactive route is affordable:

sampler-evaluation-budget.py
1import json 2 3routes = [ 4 {"name": "offline_ddim_cfg", "steps": 50, "predictions_per_step": 2}, 5 {"name": "interactive_distilled", "steps": 6, "predictions_per_step": 1}, 6] 7 8budget = [ 9 { 10 "route": route["name"], 11 "denoiser_evaluations": route["steps"] * route["predictions_per_step"], 12 "quality_gate_required": True, 13 } 14 for route in routes 15] 16 17print(json.dumps(budget, indent=2))
Output
1[ 2 { 3 "route": "offline_ddim_cfg", 4 "denoiser_evaluations": 100, 5 "quality_gate_required": true 6 }, 7 { 8 "route": "interactive_distilled", 9 "denoiser_evaluations": 6, 10 "quality_gate_required": true 11 } 12]

Latent diffusion

Architecture

Pixel-space diffusion is computationally expensive because the model must process high-resolution feature maps (e.g., 512×512×3512 \times 512 \times 3512×512×3) at every denoising step. Latent Diffusion Models (LDMs), like Stable Diffusion, solve this by training the diffuser in the latent space of a high-capacity autoencoder.

If you haven't worked with VAEs recently, recall that a variational autoencoder has two parts: an encoder that compresses an image into a compact latent representation, and a decoder that reconstructs the image from it. The latent space is learned lossy compression: it preserves enough perceptual structure for the training objective, while its reconstruction errors remain part of final output quality.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752

This is the continuous-latent branch of the autoencoder family. A VQ-VAE uses a discrete codebook instead: each patch is snapped to a learned code ID, which makes the compressed image look more like a sequence of tokens.[14]Reference 14Neural Discrete Representation Learning.https://arxiv.org/abs/1711.00937 That design is useful when a Transformer is trained to predict image tokens autoregressively or with masking. Latent diffusion usually takes the other route: keep the compressed representation continuous, add noise to it, then train a denoiser over that continuous latent tensor.

During training, the VAE encoder maps an image to a clean latent z0z_0z0​, and the model learns to denoise noisy versions of that latent. During inference, there's no input image: we start from random latent noise zT∼N(0,I)z_T \sim \mathcal{N}(0, \mathbf{I})zT​∼N(0,I) and run the reverse process entirely in latent space before decoding once at the end.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752

Latent diffusion keeps repeated denoising work in compressed latent space. Latent diffusion keeps repeated denoising work in compressed latent space.
Latent diffusion spends iterative work in compressed space and decodes pixels once.

Only the final denoised latent gets decoded. If the denoiser predicts noise or velocity, the scheduler uses that prediction to update zt→zt−1z_t \rightarrow z_{t-1}zt​→zt−1​; the decoder never consumes raw predicted noise.

Why latent space?

Operating directly in pixel space demands substantial computational resources. Moving the diffusion process to a compressed latent space splits the workload into two phases. The autoencoder compresses and reconstructs pixels with some measured detail loss, while the diffusion model performs repeated denoising on the smaller latent state.

A 64×64×464 \times 64 \times 464×64×4 latent tensor has 48×48\times48× fewer scalar values than a 512×512×3512 \times 512 \times 3512×512×3 image. That reduction explains why the repeated denoising loop can be substantially cheaper than pixel-space denoising; actual throughput still depends on architecture, step count, batch policy, hardware, and safety checks.

  • Efficiency: A 64×64×464 \times 64 \times 464×64×4 latent tensor has 48×48\times48× fewer scalar values than a 512×512×3512 \times 512 \times 3512×512×3 image, and 64×64\times64× fewer spatial locations.
  • Compression: The latent representation removes information; reconstruction quality must be evaluated on details the route cares about.
  • Practical effect: The expensive denoising loop runs on a much smaller state, reducing computational demand relative to pixel-space diffusion.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752
latent-work-state.py
1import json 2import math 3 4pixel_shape = (512, 512, 3) 5latent_shape = (64, 64, 4) 6pixel_values = math.prod(pixel_shape) 7latent_values = math.prod(latent_shape) 8 9print(json.dumps({ 10 "pixel_values": pixel_values, 11 "latent_values": latent_values, 12 "scalar_reduction": pixel_values // latent_values, 13 "spatial_reduction": (pixel_shape[0] * pixel_shape[1]) // (latent_shape[0] * latent_shape[1]), 14 "throughput_requires_benchmark": True, 15}, indent=2))
Output
1{ 2 "pixel_values": 786432, 3 "latent_values": 16384, 4 "scalar_reduction": 48, 5 "spatial_reduction": 64, 6 "throughput_requires_benchmark": true 7}

Text conditioning via cross-attention

Text-conditioning recipes are model-specific. The latent diffusion paper demonstrates cross-attention conditioning and uses pretrained encoders such as CLIP for text-to-image experiments.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752[15]Reference 15Learning Transferable Visual Models From Natural Language Supervision.https://arxiv.org/abs/2103.00020 Other image generators may use T5-family encoders, multiple text encoders, or different freeze/train choices. The stable concept is that prompt embeddings condition repeated denoising updates, not that every text encoder is frozen.

The CrossAttentionBlock takes flattened image or latent features as queries, and text embeddings as keys and values. A stable softmax turns compatibility scores into weights. The runnable version below shows one latent patch attending to prompt tokens:

text-conditioning-via-cross-attention.py
1import json 2import math 3 4def dot(left: list[float], right: list[float]) -> float: 5 return sum(a * b for a, b in zip(left, right, strict=True)) 6 7def softmax(values: list[float]) -> list[float]: 8 largest = max(values) 9 exp_values = [math.exp(value - largest) for value in values] 10 total = sum(exp_values) 11 return [value / total for value in exp_values] 12 13latent_query = [0.25, 0.10, 0.70] 14text_tokens = [ 15 {"token": "oak", "key": [0.30, 0.05, 0.65], "value": [0.70, 0.20]}, 16 {"token": "dining", "key": [0.10, 0.80, 0.10], "value": [0.20, 0.70]}, 17 {"token": "table", "key": [0.35, 0.10, 0.55], "value": [0.80, 0.10]}, 18] 19 20logits = [ 21 dot(latent_query, token["key"]) / math.sqrt(len(latent_query)) 22 for token in text_tokens 23] 24weights = softmax(logits) 25conditioned_patch = [ 26 sum(weight * token["value"][i] for weight, token in zip(weights, text_tokens, strict=True)) 27 for i in range(2) 28] 29 30print(json.dumps({ 31 "attention_weights": { 32 token["token"]: round(weight, 3) 33 for token, weight in zip(text_tokens, weights, strict=True) 34 }, 35 "conditioned_patch": [round(value, 3) for value in conditioned_patch], 36}, indent=2))
Output
1{ 2 "attention_weights": { 3 "oak": 0.359, 4 "dining": 0.292, 5 "table": 0.349 6 }, 7 "conditioned_patch": [ 8 0.589, 9 0.311 10 ] 11}

Control and specialization

Production image systems rarely stop at plain text-to-image. Teams may add targeted modules around a base diffuser instead of retraining the whole backbone.

  • LoRA (Low-Rank Adaptation): Full fine-tuning is expensive. LoRA[16]Reference 16LoRA: Low-Rank Adaptation of Large Language Models.https://arxiv.org/abs/2106.09685 inserts small trainable matrices into selected layers so you can specialize a base model with a much smaller parameter update.
  • Inpainting and outpainting: The model conditions on known pixels and a mask, which lets it fill holes, replace objects, or extend the canvas while preserving local context.
  • ControlNet / adapters: ControlNet (a neural network architecture for adding conditional control to diffusion models)[17]Reference 17Adding Conditional Control to Text-to-Image Diffusion Models.https://arxiv.org/abs/2302.05543 keeps the pretrained backbone and adds trainable control branches for signals like depth, edges, or human pose. This is how you turn "draw a person" into "draw a person in exactly this pose."

Fast inference in practice

DDIM shows the first big shortcut; a production system can combine optimizations after measuring each route:

  1. Sampler choice: DDPM is the canonical stochastic sampler. DDIM keeps the same training objective but allows deterministic skipped-step trajectories.[13]Reference 13Denoising Diffusion Implicit Models.https://arxiv.org/abs/2010.02502
  2. Distillation: Progressive distillation halves the number of required sampling steps by teaching a student model to match multiple teacher steps at once.[4]Reference 4Progressive Distillation for Fast Sampling of Diffusion Models.https://arxiv.org/abs/2202.00512
  3. Consistency models: Consistency training learns mappings that stay valid across noise levels, which enables one-step or few-step generation.[18]Reference 18Consistency Models.https://arxiv.org/abs/2303.01469
  4. Straight-line objectives: Rectified flow and flow matching learn transport paths between noise and data intended to support effective numerical integration with fewer steps.[9]Reference 9Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flowhttps://arxiv.org/abs/2209.03003[8]Reference 8Flow Matching for Generative Modelinghttps://arxiv.org/abs/2210.02747
  5. Guidance distillation: A distilled model can absorb guidance behavior so serving avoids separate conditional and unconditional denoiser evaluations per step; quality must be reevaluated after distillation.
  6. Kernel efficiency: Transformer-heavy denoisers benefit from fused kernels such as FlashAttention, which reduce memory traffic and make larger batch sizes practical.[19]Reference 19FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness.https://arxiv.org/abs/2205.14135

In a design-tool setting, these optimizations determine which governed routes are affordable: offline concept boards tolerate slower samplers, while an interactive preview route may require fewer evaluations and stricter latency budgets. No step-count choice makes an output faithful to a real screenshot; quality and representation checks remain separate gates.

Skills to defend in review

  • Foundational: Derive the forward process q(xt∣xt−1)q(x_t \mid x_{t-1})q(xt​∣xt−1​) as Gaussian noise addition.
  • Intermediate: Explain the DDPM training objective as noise prediction and why the reverse posterior is approximated.
  • Intermediate: Explain how the noise schedule controls the SNR trajectory across timesteps.
  • Advanced: Describe U-Net and DiT denoisers with timestep and text conditioning.
  • Advanced: Show the classifier-free guidance interpolation formula.
  • Advanced: Distinguish classifier guidance, classifier-free guidance, and prediction targets such as ϵ\epsilonϵ, x0x_0x0​, and vvv.
  • Advanced: Explain latent-space diffusion with a VAE encoder, latent denoiser, and VAE decoder.
  • Advanced: Explain how discrete text diffusion differs from Gaussian image diffusion.
  • Advanced: Describe why DiffusionGemma-style generation refines a token canvas instead of appending one token at a time.
  • Advanced: Explain the reparameterization trick for closed-form forward sampling.
  • Advanced: Contrast pixel-space diffusion with latent-space diffusion.
  • Advanced: Explain fast inference tradeoffs across DDIM, distillation, and consistency models.
  • Advanced: Relate rectified flow / flow matching to diffusion and describe the published Stable Diffusion 3 MM-DiT example.
  • Advanced: Define an asynchronous image-job API, size denoiser evaluations by route, preserve seeded retry semantics, and gate a staged rollout on quality and safety slices.

Production questions to answer

How does classifier-free guidance trade diversity for fidelity?

CFG extrapolates away from the unconditional prediction toward the conditional one. At w=0w = 0w=0, you get the unconditional model. At w=1w = 1w=1, you recover the plain conditional prediction. On a chosen evaluation slice, increasing www may improve prompt fidelity while reducing diversity or increasing artifacts; tune it with measured outputs rather than as a fixed rule.

Why does Stable Diffusion operate in latent space instead of pixel space?

Operating in pixel space, for example 512×512×3512 \times 512 \times 3512×512×3, is expensive because the denoiser must process a large spatial grid at every step. A VAE compresses the image into a smaller latent tensor such as 64×64×464 \times 64 \times 464×64×4, which is 48×48\times48× smaller in raw values and 64×64\times64× smaller in spatial locations. That's what makes the iterative denoising loop practical at high resolution, while the decoder reconstructs pixel-space detail at the end.

What is the difference between DDPM and DDIM sampling?

DDPM defines a reverse Markov chain; the original baseline is commonly shown with a long schedule such as 1000 denoiser evaluations. DDIM defines a non-Markovian process that allows deterministic sampling on a sparse timestep subset. A route can evaluate schedules such as 20 or 50 steps for latency, quality, and inversion/edit behavior rather than assuming they match the baseline.

How do text encoders integrate with a U-Net or DiT?

The text prompt is tokenized and encoded into a sequence of embeddings, often by a CLIP-family or T5-family encoder depending on the model family. Stable Diffusion-style U-Nets inject those embeddings through cross-attention layers, where image or latent features provide the queries and text embeddings provide keys and values. Newer multimodal DiTs may instead use joint text-image attention with modality-specific weights, as Stable Diffusion 3 does.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752[7]Reference 7Scaling Rectified Flow Transformers for High-Resolution Image Synthesishttps://arxiv.org/abs/2403.03206

How does DiffusionGemma-style text generation differ from ordinary LLM decoding?

Ordinary decoder-only LLMs append tokens left to right, so each new token depends on a committed prefix. DiffusionGemma-style text generation starts with a target token canvas and repeatedly refines uncertain positions through discrete diffusion.[1]Reference 1DiffusionGemmahttps://ai.google.dev/gemma/docs/diffusiongemma That can reduce strict next-token dependency inside a block and can use bidirectional context during refinement. Serving now has new knobs: target length blocks, number of refinement passes, confidence thresholds, and UI behavior for text that can change before final commit.

Why does the noise schedule matter so much in diffusion training?

The schedule determines the signal-to-noise ratio at every timestep. In the closed-form forward process, remaining signal power is proportional to αˉt\bar{\alpha}_tαˉt​ and noise power is proportional to 1−αˉt1 - \bar{\alpha}_t1−αˉt​, so SNRt≈αˉt/(1−αˉt)\mathrm{SNR}_t \approx \bar{\alpha}_t / (1 - \bar{\alpha}_t)SNRt​≈αˉt​/(1−αˉt​). If signal disappears too quickly, many late steps become nearly pure noise and contribute weak learning signal. If too much signal remains, the model never learns hard denoising steps.

What is the reparameterization trick in the forward process?

The reparameterization trick lets us sample xtx_txt​ at any timestep directly from x0x_0x0​ without iterating through all previous noising steps. Because sums of Gaussian variables remain Gaussian, the full forward Markov chain can be marginalized and expressed as a linear combination of x0x_0x0​ and one standard normal noise variable ϵ\epsilonϵ. That enables parallel, random timestep sampling across batches during training.

Common design failures

  • Confusing noise prediction, ϵ\epsilonϵ, with clean-image prediction, x0x_0x0​.
  • Assuming the forward process requires a neural network, even though it's fixed math.
  • Confusing classifier guidance with classifier-free guidance.
  • Thinking classifier-free guidance requires a separate classifier model.
  • Thinking the VAE decoder consumes the denoiser's raw noise prediction instead of the final denoised latent.
  • Overlooking the perceptual compression loss introduced by the VAE in latent diffusion.
  • Treating guidance scale as a probability rather than an extrapolation coefficient.
  • Assuming fewer sampling steps are a free speedup with no quality or editability tradeoff.
  • Assuming diffusion always means Gaussian noise over pixels, even though text diffusion uses discrete token corruption and refinement.
  • Treating DiffusionGemma-style generation as ordinary next-token decoding with a different sampler.

Traps that catch beginners

  • CFG scale isn't a probability. It's an extrapolation coefficient. w=0 is unconditional, w=1 is conditional without extra boost, and larger values trade diversity for prompt fidelity.[12]Reference 12Classifier-Free Diffusion Guidance.https://arxiv.org/abs/2207.12598
  • Latent diffusion doesn't remove the autoencoder bottleneck. It moves the denoising loop into a smaller space, but decoder quality still caps the final image quality.[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752
  • The denoiser's raw prediction isn't what gets decoded. If the model predicts ϵ\epsilonϵ or vvv, the scheduler converts that into the next latent and only the final clean latent goes through the VAE decoder.[2]Reference 2Denoising Diffusion Probabilistic Models.https://arxiv.org/abs/2006.11239[5]Reference 5High-Resolution Image Synthesis with Latent Diffusion Models.https://arxiv.org/abs/2112.10752
  • DiT doesn't automatically mean cheaper inference. Self-attention scales well with model size, but token count still matters. Latent-space patching is what makes DiT practical for image generation.[6]Reference 6Scalable Diffusion Models with Transformers.https://arxiv.org/abs/2212.09748
  • Text diffusion isn't pixel diffusion with token labels. The noisy state is discrete, the model refines masked or corrupted token positions, and target length planning becomes part of serving.

Teams building design-asset pipelines can't treat synthetic imagery as verified UI or incident evidence. Generated outputs can show incorrect labels, brand marks, chart values, legal text, or unsafe content. High-risk routes need output filtering, provenance labeling, and human review before publication.

synthetic-output-release-gate.py
1import json 2 3outputs = [ 4 {"asset": "campaign_background", "claims_real_screenshot": False, "contains_logo": False}, 5 {"asset": "ui_mockup_with_text", "claims_real_screenshot": True, "contains_logo": False}, 6 {"asset": "incident_screenshot_evidence", "claims_real_screenshot": True, "contains_logo": True}, 7] 8 9decisions = [] 10for output in outputs: 11 needs_review = output["claims_real_screenshot"] or output["contains_logo"] 12 decisions.append({ 13 "asset": output["asset"], 14 "decision": "human_review" if needs_review else "synthetic_labeled_preview", 15 }) 16 17print(json.dumps(decisions, indent=2))
Output
1[ 2 { 3 "asset": "campaign_background", 4 "decision": "synthetic_labeled_preview" 5 }, 6 { 7 "asset": "ui_mockup_with_text", 8 "decision": "human_review" 9 }, 10 { 11 "asset": "incident_screenshot_evidence", 12 "decision": "human_review" 13 } 14]

Diffusion model checklist

What diffusion models do

  1. Forward process: a fixed Markov chain gradually destroys information by adding Gaussian noise.
  2. Reverse process: a learned model (U-Net or DiT) predicts and removes noise step-by-step.
  3. Classifier-Free Guidance (CFG): a common text-steering mechanism that extrapolates between unconditional and conditional predictions.
  4. Latent diffusion: iterative denoising happens in a compressed representation, which reduces work while introducing a measured reconstruction bottleneck.
  5. Text diffusion: the same denoising idea moves onto discrete token sequences, where masked positions are refined over several passes instead of appended left to right.
  6. Modern architecture: Stable Diffusion 3 is a published example of MM-DiT with rectified flow; DiffusionGemma is a current Google example of discrete diffusion for text.
  7. Inference engineering: sampler choice, denoiser evaluations, refinement rounds, output canvas length, distillation, and quality checks determine whether a route is usable in production.

Common misconceptions

  • "The model predicts the image directly." Most standard diffusion models predict the noise ϵ\epsilonϵ, though predicting the original image x0x_0x0​ or its velocity vvv is also possible.
  • "More steps always equal better quality." Quality improves only until sampler error, model error, and guidance artifacts dominate. Few-step models exist, but they're an engineering trade-off, not a free lunch.
  • "Latent diffusion throws away everything important." The VAE is lossy, but it's trained for useful perceptual reconstruction. Measure compression errors separately from denoiser errors on the details the route requires.
  • "DiffusionGemma is just faster next-token decoding." It changes the generation dependency pattern: a masked token canvas is refined over passes, so serving has different length, streaming, and confidence controls.

Trace a full image diffusion pipeline from prompt to pixel, explain why the forward process uses a closed-form noise sample, and read a training loop to identify exactly where the noise is added, where the MSE loss is computed, and why the model is learning anything at all. Also explain why Stable Diffusion runs in latent space, what CFG does to the noise prediction, why fewer sampling steps are a speed-quality trade-off, and how DiffusionGemma-style text generation changes the dependency pattern from prefix appending to canvas refinement.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score above 75% to mark this lesson complete.

1.A design-platform team is comparing a one-pass GAN-style generator with a diffusion system for prompt-driven visual mockups. Which claim is the safest technical reason diffusion is attractive, and what still must be evaluated before release?
2.A trainer samples a clean pixel with x0 = 1.0, alpha_bar_t = 0.5, and epsilon = -0.4. Which result and training implication follow from the closed-form forward equation?
3.A DDPM training row has true added noise [0.20, -0.10, 0.05] and model prediction [0.18, -0.08, 0.02]. Which statement correctly describes the simple objective and why the learned prediction is needed at sampling time?
4.A DDPM sampler computes only its learned reverse mean at every step and never adds stochastic noise. What correction matches the DDPM reverse update while preserving deterministic tests?
5.A team is choosing between a Stable Diffusion-style U-Net and a DiT/MM-DiT-style backbone for UI illustration generation. Which comparison is accurate?
6.A text-to-image U-Net denoiser is receiving a noisy latent z_t at several noise levels and a prompt embedding sequence. Which conditioning wiring matches the diffusion setup?
7.Using the Stable Diffusion classifier-free guidance convention, epsilon_uncond = [0.20, -0.10, 0.05], epsilon_cond = [0.05, -0.35, 0.20], and w = 7.5. What guided noise prediction is used?
8.A 512 x 512 x 3 visual mockup is generated with a Stable Diffusion-style 64 x 64 x 4 latent denoising loop. Which pipeline description is correct?
9.Route A uses 50 DDIM steps with ordinary CFG, requiring conditional and unconditional predictions per step. Route B uses a distilled 6-step model with one prediction per step. Which budget and deployment conclusion are correct?
10.A team is evaluating DiffusionGemma-style text generation for short code-review summaries. Which statement best captures the architecture change and the new serving questions?

10 questions remaining.

Next Step
Continue to Real-Time Voice AI Agent

You can now reason about iterative generation under latency and quality trade-offs. Next you'll apply that systems discipline to live audio, where streaming stages, interruptions, and first-audio latency shape the architecture.

PreviousMultimodal LLM Architecture
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

DiffusionGemma

Google · 2026

Denoising Diffusion Probabilistic Models.

Ho, J., Jain, A., & Abbeel, P. · 2020 · NeurIPS 2020

Deep Unsupervised Learning using Nonequilibrium Thermodynamics.

Sohl-Dickstein et al. · 2015

Progressive Distillation for Fast Sampling of Diffusion Models.

Salimans, T., & Ho, J. · 2022 · ICLR 2022

High-Resolution Image Synthesis with Latent Diffusion Models.

Rombach, R., et al. · 2022 · CVPR 2022

Scalable Diffusion Models with Transformers.

Peebles, W., & Chen, S. · 2023 · ICCV 2023

Scaling Rectified Flow Transformers for High-Resolution Image Synthesis

Esser, P., Kulal, S., Blattmann, A., et al. · 2024

Flow Matching for Generative Modeling

Lipman, Y., Chen, R. T. Q., Ben-Hamu, H., Nickel, M., & Le, M. · 2022

Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flow

Liu, X., Gong, C., & Liu, Q. · 2022

Structured Denoising Diffusion Models in Discrete State-Spaces

Austin, J., Johnson, D. D., Ho, J., Tarlow, D., & van den Berg, R. · 2021 · NeurIPS 2021

DiffusionGemma Model Card

Google · 2026

Classifier-Free Diffusion Guidance.

Ho, J., & Salimans, T. · 2022 · NeurIPS 2021 Workshop

Denoising Diffusion Implicit Models.

Song, J., Meng, C., & Ermon, S. · 2020 · ICLR 2021

Neural Discrete Representation Learning.

Oord, A. van den, Vinyals, O., & Kavukcuoglu, K. · 2017

Learning Transferable Visual Models From Natural Language Supervision.

Radford, A., et al. · 2021 · ICML 2021

LoRA: Low-Rank Adaptation of Large Language Models.

Hu, E. J., et al. · 2021 · ICLR

Adding Conditional Control to Text-to-Image Diffusion Models.

Zhang, L., et al. · 2023 · ICCV 2023

Consistency Models.

Song, Y., et al. · 2023 · ICML 2023

FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness.

Dao, T., Fu, D. Y., Ermon, S., Rudra, A., & Ré, C. · 2022 · NeurIPS 2022

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.