Generating Handwritten Digits Using Diffusion

February 07, 2025

Lately I’ve been trying to build intuition for diffusion models by implementing small versions from scratch, without worrying too much about scale, benchmarks, or clever tricks. The goal was the same as with a lot of my recent side projects: make the math feel concrete by watching it run.

This notebook is a minimal(ish) implementation of a class-conditional diffusion model trained on MNIST, using a small UNet and DDIM sampling. It’s not meant to be optimal or fast, and it definitely isn’t production-ready. I mostly wanted to understand:

  • how the forward noising process behaves as a function of time
  • what the model is really learning when it predicts noise
  • how classifier-free guidance changes samples in practice
  • how much you can get away with using a very simple architecture

The model is trained to predict noise at random diffusion steps, and sampling is done with a deterministic DDIM update for speed. At the end, I use the conditional model to generate individual digits, and even stitch together multiple digits to generate full numbers.

Nothing fancy, but it was satisfying to see the whole loop work.

Below is the full notebook.

That is it for now.