Draw any digit (0–9) on the canvas. AI predicts it instantly.
Hosted on a free Hugging Face Space: if it has been idle, it may take a moment to wake up.
- 🖊️ Interactive canvas — draw digits freehand in the browser
- ⚡ Instant prediction — real-time inference with no page reloads
- 🧠 CNN model — trained on MNIST, 99.43% test accuracy with only 161K parameters
- 🌐 Full-stack — TypeScript/React frontend + Python backend
- 🐳 Dockerized — single container runs the entire app
- 🤗 Hugging Face Spaces — live and publicly accessible
Numera/
├── UI/ # Frontend — TypeScript / React
├── main.py # Python backend (API server)
├── model.py # CNN architecture (PyTorch)
├── model.pt # Pre-trained model weights
├── MNIST_Training.ipynb # Training notebook
├── scripts/benchmark.py # Parameter count, size and CPU latency
├── requirements.txt # Python dependencies
├── Dockerfile # Container definition
└── README.md
User draws on canvas
↓
Canvas exported as PNG → Next.js API route (/api/predict)
↓
POST request → FastAPI backend (main.py)
↓
Image converted to grayscale, resized to 28×28, normalized
↓
CNN model (model.py + model.pt) runs inference
↓
Predicted digit returned → displayed in UI
- Docker (recommended)
- Or: Python 3.10+ and Node.js 18+
# Clone the repo
git clone https://github.com/abdurafay19/Digit-Classifier.git
cd Digit-Classifier
# Build and run
docker build -t numera .
docker run -p 7860:7860 numeraOpen http://localhost:7860 in your browser.
1. Backend
pip install -r requirements.txt
uvicorn main:app --port 80002. Frontend
cd UI
npm install
npm run devOpen http://localhost:3000.
The classifier is a CNN trained from scratch on the MNIST dataset.
Four convolutional blocks followed by a small classifier head. Every conv block is
Conv2d → BatchNorm2d → ReLU → MaxPool2d(2) → Dropout2d(0.25).
| Block | Layer | Output shape | Parameters |
|---|---|---|---|
| Input | 28×28 grayscale image | 1 × 28 × 28 | — |
| Conv block 1 | Conv2d 1→32, 3×3, padding 1 | 32 × 14 × 14 | 384 |
| Conv block 2 | Conv2d 32→64, 3×3, padding 1 | 64 × 7 × 7 | 18,624 |
| Conv block 3 | Conv2d 64→128, 3×3, padding 1 | 128 × 3 × 3 | 74,112 |
| Conv block 4 | Conv2d 128→256, 1×1 | 256 × 1 × 1 | 33,536 |
| Classifier | Flatten → Linear 256→128 → ReLU → Dropout(0.25) | 128 | 32,896 |
| Output | Linear 128→10 (logits) | 10 | 1,290 |
| Total | 160,842 |
Trained for 50 epochs with AdamW (lr 3e-3, weight decay 1e-4), a OneCycle cosine schedule, label smoothing 0.1 and random rotation/affine augmentation. See MNIST_Training.ipynb.
| Metric | Value |
|---|---|
| Test accuracy | 99.43% (9,943 / 10,000 MNIST test images) |
| Parameters | 160,842 |
| Model size | 643 KB (model.pt, 658,805 bytes) |
| CPU inference | ~2 ms per image |
Per-class test accuracy:
| Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| Accuracy | 100.0% | 99.7% | 99.3% | 99.8% | 99.4% | 99.2% | 99.1% | 99.2% | 99.4% | 99.1% |
Inference time is the model's forward pass for a single image (batch size 1) on CPU, measured with scripts/benchmark.py on an Intel Core i5-5200U laptop CPU (PyTorch 2.1.2, 2 threads). The mean ranged from 1.2 to 2.2 ms across runs. It excludes image preprocessing and the network round trip. To reproduce:
python scripts/benchmark.pyThis project is deployed on Hugging Face Spaces using the Docker SDK.
The Dockerfile builds and serves the full app (UI + backend) in a single container on port 7860.
To deploy your own fork:
- Create a Space at huggingface.co/spaces with Docker as the SDK
- Push this repo:
git remote add space https://huggingface.co/spaces/your-username/Digit-Classifier
git push space mainContributions are welcome! Ideas:
- 🧠 Improve the CNN (residual connections, data augmentation)
- 🎨 Add confidence score display or prediction history
- 🐳 Reduce Docker image size
- 📱 Improve mobile canvas experience
git checkout -b feature/your-feature
git commit -m "feat: describe your change"
git push origin feature/your-feature
# Open a Pull RequestAbdul Rafay — CS student at ITU and AI Engineer
Released under the MIT License.



