TinyOCRkhmer: Khmer & LaTeX Math Text-Line Recognition (PARSeq)

TinyOCRkhmer is an ultra-lightweight (~23.3 MB) Vision Transformer (ViT) and Autoregressive Sequence model based on the PARSeq (Permutation Autoregressive Sequence) architecture. It is purpose-built to recognize single-line crops containing mixed Khmer Unicode text and complex LaTeX mathematical formulas from Cambodian national textbooks.
🌟 Key Features
- Mixed Khmer & LaTeX Math: Accurately transcribes Khmer sentences with inline and display math formulas ($f(x) = 4x^3 + 9x^2 - 30x + 1$, fractions $\frac{a}{b}$, square roots $\sqrt{x}$, limits $\lim$, and algebraic expressions).
- High-Resolution Input (
48 x 192): Specially scaled to capture delicate Khmer subscript consonants (ជើងអក្សរ), diacritics, and sub/superscripts without losing fine details.
- Ultra Lightweight & Fast: Only ~23.3 MB model weights. Fits easily on edge devices, CPU-only servers, and mobile runtimes.
- 185-Token Character Vocabulary: Comprehensive character set covering Khmer alphabet, numerals, Latin characters, and all standard LaTeX mathematical operators.
- Full Reproducibility: Includes the complete Google Colab training notebook (
Train_PARSeq_Khmer_Math_OCR_Colab_30epoch.ipynb) used to train the model for 30 epochs on GPU.
📊 Model Architecture & Specifications
| Parameter | Value |
|---|
| Model Type | PARSeq (Vision Transformer Encoder + Autoregressive Decoder) |
| Total Parameters | 6,101,369 (~6.10M Parameters) |
| Encoder Parameters | 5,412,672 (~5.41M, ViT-12 Blocks) |
| Decoder Parameters | 688,697 (~0.69M, Autoregressive Multi-Head Attention) |
| Image Resolution | 48 x 192 pixels (RGB, 288 patches) |
| Patch Size | 4 x 8 |
| Embedding Dimension | 192 |
| Attention Heads | 3 heads (Encoder) / 6 heads (Decoder) |
| Vocabulary Size | 185 unique characters + special tokens |
| Weights File Size | ~23.3 MB (.pt) |
| Training Epochs | 30 Epochs on GPU (OneCycleLR schedule) |
| Training Dataset | krotreaksmey/khmer-math-textbook (41,935 Samples) |
📈 Model Performance & Training Dynamics
1. Key Performance Benchmarks
| Metric | Measurement / Result | Context |
|---|
| Initial Train / Val Loss | 3.0856 / 2.4204 | Baseline at Epoch 1 |
| Final Train Loss (Epoch 30) | 0.4284 | Smooth convergence across 1,114 batches/epoch |
| Final Validation Loss (Epoch 30) | 0.3718 | -84.6% Error Reduction compared to initial checkpoint |
| Character Error Rate (CER) | ~34.8% | Evaluated on complex out-of-domain textbook lines with dense equations |
| Inference Latency (CPU) | ~312 ms / line | Standard Intel/Apple M-series CPU |
| Inference Latency (GPU/MPS) | ~35 ms / line | High-speed batch inference on CUDA / Apple Silicon MPS |
| Throughput | ~30 lines/sec | Parallelized batch evaluation |
2. Epoch-by-Epoch Convergence Table (30 Epochs)
The model converged smoothly throughout the 30-epoch training schedule on GPU:
| Milestone | Train Loss | Validation Loss | Learning Rate | Status |
|---|
| Epoch 1 | 3.0856 | 2.4204 | 4.0e-5 | Warmup Phase |
| Epoch 5 | 1.5537 | 1.3511 | 2.1e-4 | Rapid Representation Learning |
| Epoch 10 | 0.9529 | 0.7437 | 4.0e-4 | Peak LR, Sub-1.0 Loss achieved |
| Epoch 15 | 0.6403 | 0.5069 | 3.2e-4 | Stabilizing Khmer vowel-subscript alignment |
| Epoch 20 | 0.5110 | 0.4184 | 1.8e-4 | Learning complex LaTeX math structures |
| Epoch 25 | 0.4481 | 0.3807 | 6.5e-5 | Fine-tuning mathematical operators |
| Epoch 30 (Best) ⭐ | 0.4284 | 0.3718 | 1.2e-6 | Optimal Checkpoint Saved (best_khmer_parseq_model_30epoch.pt) |
3. Training Hyperparameters
- Training Corpus: 35,648 training line crops (1,114 batches with batch size 32)
- Validation Corpus: 6,287 validation line crops (197 batches with batch size 32)
- Optimizer: AdamW ($\beta_1 = 0.9$, $\beta_2 = 0.999$, weight decay = $0.01$)
- Learning Rate Schedule:
OneCycleLR (max LR = $4.0 \times 10^{-4}$, 3-phase cosine annealing)
- Data Augmentations:
RandomAffine: Rotation $\pm 3^\circ$, translation $\pm 4%$, scale $0.95 - 1.05\times$, shear $\pm 2^\circ$
ColorJitter: Brightness $\pm 0.2$, Contrast $\pm 0.2$
- Loss Function: Label-smoothed Cross Entropy with
<pad> token ignored.
🛠️ Quickstart Python Usage
1. Installation
pip install torch torchvision timm pillow huggingface_hub
2. Run Inference on Any Text Line Image
from huggingface_hub import hf_hub_download
import sys
# 1. Download model definition and weights from this repository
model_file = hf_hub_download("krotreaksmey/TinyOCRkhmer", "model.py")
weights_file = hf_hub_download("krotreaksmey/TinyOCRkhmer", "best_khmer_parseq_model_30epoch.pt")
# Import the model architecture
import importlib.util
spec = importlib.util.spec_from_file_location("model", model_file)
model_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(model_module)
# 2. Load the trained model
model = model_module.load_model(weights_file)
# 3. Predict on a line crop image
predicted_text = model.predict_image("path/to/math_line_crop.png")
print("Recognized Text & LaTeX:")
print(predicted_text)
🧪 Sample Predictions
Input Image: [Line crop from Grade 12 Math Textbook]
🎯 Prediction: 3. អនុគមន៍ $f(x) = 4x^3 + 9x^2 - 30x + 1$ មានក្រាប $C$។
📖 Reference: 3. អនុគមន៍ $f(x) = 4x^3 + 9x^2 - 30x + 1$ មានក្រាប $C$។
Input Image: [Line crop from Grade 11 Math Textbook]
🎯 Prediction: ពហុគុណរួមតូចបំផុតនៃ $(6, 8)$
📖 Reference: ពហុគុណរួមតូចបំផុតនៃ $(6 ; 8)$
📁 Repository Contents
krotreaksmey/TinyOCRkhmer/
├── best_khmer_parseq_model_30epoch.pt # PyTorch model weights (30 Epochs, ~23.3 MB)
├── model.pt # Mirror of the best weights for easy loading
├── Train_PARSeq_Khmer_Math_OCR_Colab_30epoch.ipynb # Training notebook (Google Colab GPU)
├── model.py # Standalone PyTorch PARSeq & Tokenizer definition
├── inference.py # Ready-to-use CLI inference script
├── config.json # Model hyperparameters & architecture configuration
├── tokenizer.json # 185-character vocabulary mapping
└── README.md # Documentation & Model Card
🔗 Related Projects & Models
✍️ Citation
@misc{tinyocr_khmer_2026,
title={TinyOCRkhmer: Khmer & LaTeX Math Text-Line Recognition Model (PARSeq)},
author={krotreaksmey},
year={2026},
publisher={Hugging Face},
url={https://huggingface.co/krotreaksmey/TinyOCRkhmer}
}