ML Projects
A handwritten digit recognizer. Draw a number on the canvas and a CNN predicts it in real time, running entirely in your browser.
Draw a digit on the canvas and a CNN trained on MNIST predicts it in real time, running entirely on your device via TensorFlow.js. The model was trained in Keras and converted to a browser-friendly format, so there's no server involved. The same weights that ran in the notebook are doing inference right in your tab.
How it works
The digit you draw goes in as a 28×28 grid of pixels and passes through two Conv2D layers (32 filters each) that learn to detect small visual patterns like edges and curves, a max-pool step that shrinks the image down, and dropout that randomly zeroes out some activations during training so the model can't just memorize the training set.
That repeats once more with a 64-filter Conv2D layer, then everything gets flattened into a 128-unit dense layer and squeezed down to a final layer of 10 numbers, one per digit, that sum to 1, i.e. the model's confidence for each possible digit 0–9.
The CNN is trained in Python/Keras on the MNIST handwritten digit dataset, then exported to TensorFlow.js format.
Each demo is a self-contained folder of plain HTML/CSS/JS with its model weights bundled alongside it. Nothing is fetched from a server at runtime, and TensorFlow.js runs the forward pass directly in the browser. The whole site is static and hosted on GitHub Pages.
Technical Breakdown
This is the actual shape of the CNN running in your browser, not just a generic neural network picture. A handwritten digit goes in as a 28×28 image, passes through a convolutional stage that picks up on strokes and curves, then a fully-connected stage that turns those patterns into a decision between the 10 possible digits.
The MNIST CNN architecture
The general shape: convolution + max-pooling blocks that shrink the image down while learning visual patterns, followed by fully-connected layers that make the final call. The real model follows the same shape, with two 32-filter convolutions before the first pooling step and a 64-filter convolution before the second, dropout after each pooling step so it can't just memorize the training set, then a 128-unit fully-connected layer feeding a final layer of 10 numbers, one confidence score per digit, that's read off as the predicted digit.

