Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Devanagari CNN

Handwritten Devanagari character recognition. A convolutional network built from scratch in PyTorch classifies the 46 characters of the script, 36 consonants and 10 digits, from 32x32 grayscale images, and a Gradio interface lets you photograph or draw a character and see what the model makes of it.

Devanagari is the script behind Hindi, Marathi, Sanskrit and Nepali. Reading it reliably by machine is the first step towards digitising handwritten records, sorting post, and processing forms across India and Nepal.

96.80% test accuracy, trained on 100 images per class.

Gradio interface predicting the character pha

Results

Measured on a held out test set of 4,600 images, 100 per class.

Metric Value
Test accuracy 96.80%
Test loss 0.1037
Best validation accuracy 96.52%
Correct predictions 4,453 of 4,600
Macro average F1 0.968
Weighted average precision 0.969
Trainable parameters 824,206
Saved model size 3.2 MB
Training time 11.8 minutes, 25 epochs, CPU only

The headline number is worth reading alongside the data budget. The full DHCD dataset offers roughly 2,000 training images per class. This run deliberately subsamples to 100 per class, about 5% of what was available, leaving 3,910 images for training and 690 for validation. Reaching 96.80% on that budget says more about the architecture and the augmentation than a number trained on the full set would.

Training ran on CPU at roughly 28 seconds per epoch. Early stopping was configured with a patience of 7 but never triggered, so all 25 epochs completed.

Where it struggles

Per class accuracy is above 90% for 45 of the 46 characters. The failures cluster where the script itself is ambiguous.

Character Accuracy
kshya (क्ष) 84.0%
jha (झ) 90.0%
shha (ष) 92.0%
pa (प) 92.0%
bha (भ) 93.0%

The pattern is visual similarity rather than anything systematic: श against ष, ब against व, and conjuncts like क्ष that carry more stroke detail than a 32x32 grid comfortably holds. Variation in the shirorekha, the horizontal headline running across the top of each character, accounts for a further share of the confusions.

Architecture

Three convolutional blocks, each with two convolutions so the network can build richer features before losing spatial resolution, followed by a fully connected classifier head.

Input 1 x 32 x 32
  Block 1   Conv 1 -> 32, Conv 32 -> 32     BatchNorm, ReLU, MaxPool 2, Dropout2d 0.25   -> 32 x 16 x 16
  Block 2   Conv 32 -> 64, Conv 64 -> 64    BatchNorm, ReLU, MaxPool 2, Dropout2d 0.25   -> 64 x 8 x 8
  Block 3   Conv 64 -> 128, Conv 128 -> 128 BatchNorm, ReLU, MaxPool 2, Dropout2d 0.25   -> 128 x 4 x 4
  Head      Flatten 2048 -> Linear 256, BatchNorm1d, ReLU, Dropout 0.5 -> Linear 46

Every convolution uses a 3x3 kernel with padding 1, so spatial size is reduced only by pooling. Three blocks suit a 32x32 input: a fourth would shrink the feature map below a useful size, and two would not capture enough of the character's structure. Batch normalisation after every convolution keeps training stable at a learning rate of 1e-3. Dropout is the main regulariser, light and spatial inside the blocks at 0.25, heavier at 0.5 before the final layer where the parameter count is concentrated.

Training setup

Setting Value
Loss Cross entropy
Optimiser Adam, lr 1e-3, weight decay 1e-4
Scheduler ReduceLROnPlateau, factor 0.5, patience 3
Epochs 25, early stopping patience 7
Batch size 64
Train and validation split 85 / 15, seed 42

Training images are augmented to match how people actually write: rotation up to 10 degrees, translation up to 10% of the frame, and scaling between 0.9x and 1.1x. Validation and test images get no augmentation, only resize and normalisation, so the numbers above reflect clean inputs. All images are converted to single channel grayscale, resized to 32x32, and normalised to the range [-1, 1].

The interface

The Gradio app has two tabs. Upload Image takes a photograph of a character written on paper. Draw lets you sketch one directly in the browser. Both return the predicted character with its confidence and a top-5 breakdown, which is the more honest view when the model is uncertain between visually close characters.

Photographs need more preprocessing than the dataset images do, and the pipeline handles it: grayscale conversion, colour inversion to match the dataset's white on black convention, contrast stretching, and an automatic crop to the character's bounding box before the resize. Skipping the contrast step was the single largest source of wrong predictions on real photographs.

The public Gradio share link from the original submission has expired, as those links last one week. Re-running the final notebook cell issues a new one.

Running it

The notebook is self contained and runs top to bottom. It expects the Devanagari Handwritten Character Dataset laid out as Train/ and Test/ folders of per class subfolders, which is how it ships.

Google Colab. Open devanagari_cnn.ipynb, run the upload cell, and pick the dataset zip. It unzips, locates the Train/ folder wherever it ended up nested, and sets the data path itself.

Kaggle or local. Uncomment the matching DATA_DIR line in the dataset setup cell and skip the upload.

A GPU is optional. The published run used CPU throughout and finished in under twelve minutes.

Note that one cell permanently deletes images to subsample the dataset to 100 per class. Run it against a copy, not your only download.

Built with

PyTorch Model definition, training loop, autograd, Adam, LR scheduling
torchvision ImageFolder loading, augmentation and normalisation transforms
scikit-learn Confusion matrix, per class precision, recall and F1 report
NumPy Array handling, per class accuracy, confusion pair ranking
Matplotlib Loss and accuracy curves, prediction grids, per class bar charts
Seaborn Confusion matrix heatmap
Pillow Photograph preprocessing: inversion, autocontrast, bounding box crop
Gradio Two tab web interface with upload and draw input
Google Colab Hosted runtime, file upload widget, public demo tunnel
Jupyter Notebook format, narrative alongside executable cells

Python 3 throughout. Matplotlib needs a Devanagari capable font to label plots in the native script; the notebook installs fonts-lohit-deva and falls back to fonts-indic, and transliterated names are used where a glyph is unavailable.

Contents

File What it is
devanagari_cnn.ipynb The full project: data loading, model, training, evaluation, Gradio app
devanagari_cnn.pdf Rendered copy of the notebook with outputs, readable without Jupyter
gradio_demo.png The interface predicting फ (pha) at 93.7% confidence

The trained weights, devanagari_cnn_best.pth at 3.2 MB, are written by the notebook's save cell rather than committed here.

About

A 3-block CNN built from scratch in PyTorch that recognises all 46 handwritten Devanagari characters, 36 consonants and 10 digits, at 96.8% test accuracy from only 100 training images per class. Photograph or draw a character in the Gradio app for a top-5 prediction. PyTorch, torchvision, scikit-learn, NumPy, Matplotlib, Seaborn, Pillow, Gradio.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages