Handwritten digits recognition using NN and Ruby 🧠💎
This project is using neural network written in ruby for handwritten digits recognition. It is complete solution with frontend and backend parts. Model was trained and tested on MNIST handwritten digits set converted into libsvm format dataset. Set contains 60k train and 10k test examples.
Application is using Rumale::Torch, which requires to install LibTorch:
Build image:
docker build -t hdr_app .
Run container:
docker run -p 4567:4567 hdr_app:latest
For MacOS:
brew install automake libtorch
Then execute:
bundle install
For Linux please follow Dockerfile when installing libtorch.
Download MNIST file and extract it in /utils
folder:
cd utils/
wget https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/mnist.t.bz2
wget https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/mnist.bz2
bzip2 -d mnist.t.bz2 mnist.bz2
MNIST files does not contain zero values, which is problematic when using Rumale library. The simple fix is to fill it with zeros, and make sure we have 784 values (28x28 pixels) in one line. For that there is script:
// in utils/
ruby fill_libsvm_with_zeros.rb mnist
ruby fill_libsvm_with_zeros.rb mnist.t
Libsvm files contain datas in multiple lines with format:
<label> <index1>:<value1> <index2>:<value3> ...
.
.
.
For MNIST data which are just 28x28 pixels images of digits index is the position of pixel (x=index%size
, y=floor(index/size)
) and value is color of pixel (0-white, 255-black).
Now you can start training with train.rb
script.
// in utils/
ruby train.rb
Mind that it has parameters such as:
- batch_size
- max_epoch
- validation_split
- layers
For training you can tweak them and see how it impacts the learning process and accuracy.
To test model simply run:
// in utils/
ruby test.rb
Make sure scipt is using the right model file, and NN has the same dimensions as in training.
To use you own model copy your .dat and .pth file to models folder, and rename it to model.dat
and model.pth
.
The default model has ~97% accuracy.