DDPM on CIFAR-10: a paper-faithful reproduction (FID 3.14)

A from-scratch, paper-faithful reproduction of DDPM (Ho et al., 2020) for unconditional 32×32 CIFAR-10, trained on a single RTX 5090. It reaches a legacy-TF FID of 3.139 (50k samples, 1000-step ancestral sampling, best of 3 seeds), matching the paper's 3.17.

These are the EMA weights (decay 0.99995) of the 700k-step snapshot, the best snapshot of the run. The model is the baseline entry of a single-GPU diffusion speedrun benchmark: https://github.com/Euswbnix/DDPM-Diffusion-Model.

64 uncurated samples

64 uncurated samples: DDPM-1000 ancestral sampling, seed 0.

Results

FID is computed with clean-fid in legacy_tensorflow mode against CIFAR-10 train statistics, on 50k samples from DDPM-1000 ancestral sampling with EMA 0.99995. Each record uses exactly three distinct sampling seeds and reports the minimum. clean-mode FID is given as a disclosure.

Snapshot Training time FID (min of 3) FID per seed (0 / 1 / 2) clean-FID (min)
600k 8.24 h 3.1912 3.1912 / 3.2637 / 3.2757 3.8690
700k (this model) 9.61 h 3.1385 3.1385 / 3.2275 / 3.2149 3.8051
800k (paper budget) 10.98 h 3.1500 3.1500 / 3.1824 / 3.1643 3.8349

Training time is on-clock wall time from process start to the snapshot save. It includes torch.compile warmup, data loading and EMA updates, and excludes evaluation.

  • The 700k snapshot beats the paper's full 800k-step budget on both FID and time: this recipe plateaus near FID 3.14 by 700k steps.
  • The time to reach FID 3.17 falls between 8.24 h and 9.61 h. The 600k snapshot misses the target on all three seeds; the 700k snapshot clears it.
  • FID gaps below about 0.04 are within seed-to-seed noise.

The raw evaluation files are in eval/.

Usage

You need torch, safetensors and huggingface_hub. The architecture and the samplers are the two Python files in this repository.

import json, sys
import torch
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file

repo = "euswbnix/ddpm-cifar10"
for f in ("unet.py", "diffusion.py"):
    hf_hub_download(repo, f, local_dir=".")
sys.path.insert(0, ".")
from unet import UNet
from diffusion import GaussianDiffusion

cfg = json.load(open(hf_hub_download(repo, "config.json")))
model = UNet(
    ch=cfg["ch"], ch_mult=tuple(cfg["ch_mult"]), num_res_blocks=cfg["num_res_blocks"],
    attn_res=tuple(cfg["attn_res"]), dropout=cfg["dropout"], img_res=cfg["img_res"],
)
model.load_state_dict(load_file(hf_hub_download(repo, "model.safetensors")))

device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device).eval()
diffusion = GaussianDiffusion(cfg["T"], cfg["beta_start"], cfg["beta_end"]).to(device)

gen = torch.Generator(device).manual_seed(0)
x = diffusion.p_sample_loop(model, (16, 3, 32, 32), device, generator=gen)  # in [-1, 1]
images = (x.clamp(-1, 1) + 1) / 2                                           # in [0, 1]

Use the ancestral sampler (p_sample_loop) to match the reported numbers. Few-step DDIM sampling hurts this ε-prediction, linear-β model badly: in 10k-sample checks, DDIM with 100 steps scored about 8 FID where DDPM-1000 scored about 5.

Training details

  • Architecture: 35.7M-parameter U-Net as in the official implementation. Base width 128, channel multipliers (1, 2, 2, 2), two residual blocks per resolution, self-attention at 16×16, dropout 0.1, sinusoidal timestep embedding. Output layers are zero-initialized; all other weights use Xavier-uniform initialization.
  • Diffusion: T = 1000, linear β from 1e-4 to 0.02, ε-prediction, simple MSE loss.
  • Optimization: Adam, learning rate 2e-4 with a 5k-step linear warmup, gradient clipping at 1.0, batch size 128, random horizontal flips, seed 0.
  • EMA: four decay rates tracked during training. 0.99995 gave the best FID and is the one released.
  • Systems: bf16 autocast, torch.compile, PyTorch 2.11, one RTX 5090.
  • Sampling: DDPM ancestral, 1000 steps, variance σ² = β, predicted x₀ clipped to [-1, 1].

Limitations

  • Unconditional CIFAR-10 at 32×32 only. This is a research and benchmark artifact.
  • Sampling takes 1000 network evaluations per image.

Citation

@inproceedings{ho2020denoising,
  title     = {Denoising Diffusion Probabilistic Models},
  author    = {Ho, Jonathan and Jain, Ajay and Abbeel, Pieter},
  booktitle = {Advances in Neural Information Processing Systems},
  volume    = {33},
  pages     = {6840--6851},
  year      = {2020}
}
Downloads last month
9
Safetensors
Model size
35.7M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train euswbnix/ddpm-cifar10

Evaluation results

  • FID (legacy-TF, 50k samples, min of 3 seeds) on CIFAR-10
    self-reported
    3.139