on this page
Project

MNIST Digit Classifier

Neural network built from scratch achieving ~98% accuracy on MNIST.

I built this to understand how neural networks actually work. The math behind a multi-layer perceptron is surprisingly kinda simple - matrix multiplies, ReLU, softmax, chain rule, but frameworks like PyTorch abstract all of it away behind nn.Module and autograd. So I decided to write everything from scratch: forward pass, backpropagation, gradient descent, all of it.

I also trained a CNN using PyTorch for comparison, to see how much spatial awareness/features matter for image classification.

Try it yourself

Draw a digit below. Both models classify it in real-time, entirely in your browser.

012345678978425625625610
MLP(98.32% accuracy)

Loading weights…

CNN(99.31% accuracy)

Loading weights…

Draw a digit to see CNN feature maps


Architecture

MLP (from scratch)

A 4-layer fully connected network:

  • Input: 784 neurons (28×28 pixels, flattened)
  • Hidden layers: 3 × 256 neurons with ReLU
  • Output: 10 neurons with softmax

CNN

The CNN uses spatial structure that the MLP throws away by flattening:

  • Conv1: 32 filters (3×3), BatchNorm, ReLU, MaxPool
  • Conv2: 32 filters (3×3), BatchNorm, ReLU, MaxPool
  • FC: 800 → 10

Convolutional layers detect local patterns like edges and curves that are translation-invariant. For example, a “7” gets recognized whether it’s drawn in the center or corner.


Training

MLP: trained for 5 epochs with Xavier weight initialization, learning rate 0.5 with cosine annealing, batch size 128. Cross-entropy loss implemented from scratch. The entire training loop: forward pass, backpropagation, weight updates, was written without any automatic differentiation. Gradients derived by hand and computed explicitly for each layer.

CNN: standard PyTorch training with Adam optimizer, dropout (0.25), 45 epochs.


Results

ModelDemo AccuracyParameters
MLP (from scratch)97.76%~397K
CNN (PyTorch)96.58%~18K

The CNN in the repoExternal link achieves 99.31% when fully trained. The demo runs a lighter checkpoint to keep browser inference fast. Both models run entirely in your browser using pure TypeScript. No server, no ONNX, no WebAssembly.

Test Samples

Some digits from the MNIST test set.

Loading samples…

Confusion Matrices

Which digits does each model mix up?

Loading confusion matrix…