Idea is to have more projects here for self-education but so far it's only MNIST 👹
This project is a small handwritten-digit classifier built around the MNIST dataset. It uses plain Python and NumPy (just to speed up the training A LOT) for the neural network logic, reads the raw IDX dataset files directly, and includes a simple Tkinter app for drawing a digit and running inference with saved weights.
- Loads raw MNIST image and label files from
mnist/data/ - Trains a feed-forward neural network without PyTorch or TensorFlow
- Applies light data augmentation during training
- Saves trained weights to
weights.json - Evaluates the model on the MNIST test split
- Lets you draw a digit in a desktop window and predict it
The current model is a 3-layer fully connected network:
- Input:
784values (28x28grayscale image flattened) - Hidden layer 1:
128neurons with ReLU - Hidden layer 2:
64neurons with ReLU - Output:
10logits with softmax for digit classes0-9
Training uses:
- Cross-entropy loss
- Mini-batch gradient descent
- Random shuffling each epoch
- Simple augmentation:
- small shifts
- small rotations
- Gaussian noise
This project is intentionally lightweight. You only need:
- Python 3
numpytkinterfor the drawing UI
Example setup:
python3 -m venv .venv
source .venv/bin/activate
pip install numpytkinter is part of many Python installations by default. If the UI does not launch on your machine, you may need to install your OS-specific Tk package separately.
From the repository root:
python3 mnist/train.pyThis will:
- load the training split from
mnist/data/ - train for a few epochs
- print loss and training accuracy
- overwrite
weights.jsonwith the newly trained parameters
python3 mnist/test.pyThis reads weights.json and prints a final test accuracy score.
python3 mnist/main.pyIn the UI:
- draw a digit on the 28x28-style canvas
- click
Predict - see the predicted number in the window
- The code is written in a straightforward, educational style rather than as a reusable package.
- Some earlier implementation ideas are still visible as commented-out code, which makes the training evolution easier to follow.
weights.jsonis currently ignored by Git according to.gitignore, even though a copy exists in the working tree.- The model has about
109ktrainable parameters, which is enough to do a respectable MNIST baseline while staying easy to understand.
