MNIST digit recognition in JavaScript in real-time
Reads handdrawn digits with machine learning, trained on the MNIST dataset.
Neural network with TensorFlow
Prediction Probabilities
This page can recognize hand-drawn digits on a Canvas object. For this, a simple neural network created and trained with TensorFlow is used. The model requires only about half a MB to function compared to an earlier KNN implementation that required 200MB. The model can run so fast that it works in real-time. Every time the user makes a change in the Canvas by drawing, the model runs. Through this, you can see which strokes affect the recognition process the most, for example you can see how the model transitions from recognizing the digit 3 to 8 by changing the drawing.
The model was trained in Python because TensorFlow is very user-friendly and made it easy to create
the neural network. The training was done in a Jupyter Notebook.
The model is defined like this in TensorFlow:
It has relatively many layers for a simple MNIST digit recognition, but I noticed that performance
improved through this. The model was trained on a laptop without a graphics card. For future and
larger neural networks I will likely use a graphics card to accelerate training.
TensorFlow makes it much easier to train neural networks. You don't need to define all the functions yourself as I had to do for the earlier KNN model. Beyond that, it's much easier to export trained models. In this case, the model was trained in Python with TensorFlow and exported. It could then easily be imported and used with TensorFlowJS on the website.
The ten sliders on the right are enabled by the neural network. As you can see above, it has 10 output neurons. These are connected to each slider. If the network, for example, recognizes a five, the neuron representing 5 will get a large activation, and this makes the slider on the website wider.
Future Improvements
The network works but is very sensitive to size differences between training data and input data. This leads to high accuracy on test data, but in practical use, the model can be unreliable. In the future, I will try to modify the input so it has the same size as the training data. This will hopefully improve performance since the input will more closely resemble the training data then.