MNIST Handwritten Digits
Tiny grayscale photos of handwritten digits with one label each, the standard first dataset for image classification before moving to harder data.
Why Does This Exist?
Every newcomer to vision needs one dataset where the plumbing works before the research starts. Raw web photos bring variable sizes, color shifts, missing labels and licensing questions. MNIST removes all of that: centered digits, one channel, one label per image, fixed splits, so a first classifier trains in minutes and fails for modeling reasons rather than data reasons.
This page covers the I/O contract, a split walkthrough with toy counts, and appropriate use. Cleaning and splitting practice lives in dataset preparation, and batched loading lives in dataloaders. Fashion-MNIST reuses the same contract with clothing items instead of digits.
Think of It Like This
Flashcards with one answer on the back
A teacher holds up flashcards, each with one digit, and the back says which digit it is. The cards are all the same size and the writing sits in the middle, so you practice reading rather than handling cards.
MNIST is that deck. Same size, centered writing, one answer per card. Fashion-MNIST swaps digits for shirts and boots but keeps the deck rules.
How It Actually Works
MNIST is a classification dataset: input is one grayscale image, output is one integer label from 0 to 9. Purpose is baseline image classification. I/O contract is image tensor plus integer label. Appropriate use is smoke tests, teaching, and pipeline checks. Move past it once a model saturates, because near-perfect scores there say little about natural photos.
Split walkthrough with toy counts
Take a small illustration batch of 100 labeled cards to practice the split math. Keep 80 for train, 10 for validation, 10 for test. With 10 digit classes balanced, that is about 8 train, 1 validation and 1 test per digit. Accuracy on test is correct predictions divided by 10, so 9 right gives . The same ratio logic applies to the full fixed splits, whatever their published sizes.
Code
A minimal loader contract check with no external files, showing the expected I/O shapes.
import numpy as np
def one_hot(label: int, classes: int = 10) -> np.ndarray: vec = np.zeros(classes, dtype=float) # one slot per digit 0 to 9 vec[label] = 1.0 return vec
image = np.zeros((28, 28), dtype=float) # stand-in grayscale frameimage[14, 14] = 1.0print(image.shape, one_hot(3).sum())# -> (28, 28) 1.0The image is two-dimensional and the label vector sums to 1, which is the contract a classifier expects.
Watch Out For
Reading high MNIST accuracy as vision progress
Scores near the top are common within a few epochs, and teams report them as if they transfer. The symptom is a model that aces centered digits and fails on tilted, noisy phone photos. Fix it by treating MNIST as a pipeline test and evaluating on harder natural data before claiming anything.
The Quick Version
- MNIST maps one small grayscale digit image to one label 0 to 9 for baseline classification.
- Input is an image tensor, output is a single integer label, with fixed train and test roles.
- Fashion-MNIST keeps the same contract with clothing items for a slightly harder variant.
- A toy 80/10/10 split of 100 cards gives about 8 train per digit and test accuracy as correct over 10.
- Use it to verify plumbing, then move on once scores saturate.