Digit Classifier (MNIST)
Part of the AI Engineer Roadmap
In short
MNIST is the 'Hello, World' of deep learning: 70,000 small handwritten digits. Building a classifier for it end to end teaches you the whole PyTorch workflow in one sitting.
The 'hello world' of deep learning: classify handwritten digits — a small, fast project that exercises the full PyTorch/TensorFlow training loop end to end.

Think of it like this
The post office PIN code reader
At a busy sorting office, someone reads thousands of handwritten PIN codes a day, scrawled in every style. After enough envelopes, they barely need to think. Your model sees 60,000 handwritten digits and learns to read them the same way.
Watch it happen
Your build plan
1/6torchvision downloads 60,000 training and 10,000 test images, each 28 × 28 pixels in greyscale.
The big ideas
What you need to know
Images are grids of numbers
Each image is a 28 × 28 grid of brightness values. Flattened, that's 784 inputs per example.
Ten outputs, one per digit
The last layer gives 10 scores. The highest one is the prediction. Cross-entropy trains them.
Upgrade to a CNN
An MLP gets you a good score. A small CNN, which looks at nearby pixels together, does noticeably better.
Study the mistakes
Plot misclassified digits. Many are 4s that look like 9s, or messy 7s. It tells you what the model finds hard.
See it in code
Walk through the code
1import torch, torch.nn as nn2from torchvision import datasets, transforms3from torch.utils.data import DataLoader4 5tf = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])6train = DataLoader(datasets.MNIST("data", train=True, download=True, transform=tf), batch_size=64, shuffle=True)7 8model = nn.Sequential(nn.Flatten(), nn.Linear(28 * 28, 128), nn.ReLU(), nn.Linear(128, 10))9opt = torch.optim.Adam(model.parameters(), lr=1e-3)10 11for images, labels in train: # one epoch12 opt.zero_grad()13 loss = nn.functional.cross_entropy(model(images), labels)14 loss.backward()15 opt.step()16print("last batch loss:", loss.item())1/3Load MNIST as tensors, normalised with its usual mean and std, in shuffled batches of 64.
One epoch of a simple MLP. Add a test loop with torch.no_grad() next and count correct predictions.
Save yourself the pain
Common mistakes
Oops
Checking accuracy on the training batches and calling it done.
Do this instead
Load the test split with train=False and report accuracy there, inside torch.no_grad().
Oops
Testing your own drawing as black ink on white paper.
Do this instead
MNIST digits are white on black and centred. Invert and centre your image first, or the model will be confused.
Your mission
Milestone 1: beat 95% on the test set
Quick check
Your MNIST model outputs 10 numbers for an image. How do you get the predicted digit?
Go deeper
- 1Build and train a small feedforward or CNN model on MNIST from scratch.
- 2Plot training/validation loss curves to check for overfitting.
- 3Push accuracy above 98% and explain what architecture changes got you there.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.