Views
No views yet
Fine-tuned vision-language model for Hindi handwritten text recognition from images, trained on the IIIT-INDIC-HW-WORDS-Hindi dataset.
| Property | Value |
|---|---|
| Base model | Qwen/Qwen2-VL-2B-Instruct |
| Fine-tuned model | ianuragbhatt/hindi-handwritten-ocr-qwen2vl-2b |
| Merged model | ianuragbhatt/hindi-handwritten-ocr-qwen2vl-2b-merged |
| Parameters | ~2.2B (base) + LoRA adapter |
| Dataset | 69,853 train / ~12,000 val+test images |
| Training method | LoRA fine-tuning (rank 16) |
| Vision encoder | Frozen |
| Trainable params | ~10–15% of total |
| License | Apache-2.0 (base) / CC-BY-4.0 (dataset) |
Qwen2-VL-2B-Instruct
├─ Vision Encoder (675M params, frozen)
├─ MLP Projector (cross-modal adapter, frozen)
└─ Qwen2-1.5B LLM (1.5B params, LoRA-tuned)
└─ LoRA rank 16 on attention + MLP layerstransformers support (no trust_remote_code)SFTTrainer + PEFT LoRA out of the boxpip install transformers>=4.56 accelerate peft bitsandbytes1from PIL import Image
2import torch
3from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
4
5model_id = "ianuragbhatt/hindi-handwritten-ocr-qwen2vl-2b-merged"
6
7# Load (use load_in_4bit=True for low VRAM)
8model = Qwen2VLForConditionalGeneration.from_pretrained(
9 model_id,
10 torch_dtype=torch.bfloat16,
11 device_map="auto",
12)
13processor = AutoProcessor.from_pretrained(model_id)
14
15# Load image
16image = Image.open("hindi_sample.jpg").convert("RGB")
17
18# Build prompt
19messages = [
20 {
21 "role": "user",
22 "content": [
23 {"type": "image"},
24 {"type": "text", "text": "Transcribe the Hindi handwritten text in this image."},
25 ],
26 }
27]
28
29# Prepare
30prompt = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
31inputs = processor(text=[prompt], images=[image], return_tensors="pt", padding=True)
32inputs = {k: v.to(model.device) for k, v in inputs.items()}
33
34# Generate
35generated = model.generate(**inputs, max_new_tokens=256, do_sample=False)
36output = processor.batch_decode(generated[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)[0]
37print(output)python inference_hindi_ocr.py --image hindi_sample.jpg --model ianuragbhatt/hindi-handwritten-ocr-qwen2vl-2b-merged| Hyperparameter | Value |
|---|---|
| Learning rate | 2e-4 |
| LoRA rank | 16 |
| LoRA alpha | 16 |
| LoRA dropout | 0.05 |
| Batch size | 2 |
| Gradient accumulation | 4 |
| Epochs | 1 |
| Warmup ratio | 0.03 |
| LR scheduler | linear |
| Weight decay | 0.01 |
| Max sequence length | 512 |
| Optimizer | AdamW (via TRL defaults) |
| Mode | GPU VRAM | Notes |
|---|---|---|
| Training (LoRA, bf16) | ~12–16 GB | T4 / RTX 3060 / Colab T4 works |
| Inference (bf16) | ~6–8 GB | Any modern GPU |
| Inference (4-bit) | ~3–4 GB | GTX 1060 6GB, laptop GPUs |
| Inference (CPU) | ~8–12 GB RAM | Very slow but works |
colab_hindi_ocr.ipynb.py (in this repo)1pip install transformers>=4.56 trl peft accelerate datasets bitsandbytes
2python train_hindi_ocr_colab.py1model = Qwen2VLForConditionalGeneration.from_pretrained(
2 model_id,
3 load_in_4bit=True,
4 device_map="auto",
5)1optimum-cli export onnx \
2 --model ianuragbhatt/hindi-handwritten-ocr-qwen2vl-2b-merged \
3 ./onnx_model/OpenGVLab/InternVL2_5-1B (938M params)
BASE_MODEL in the scripttrust_remote_code=True and may need older transformers| File | Description |
|---|---|
train_hindi_ocr_colab.py | Full training script (run on Colab/Kaggle/Local) |
train_internvl2_5_1b.py | Alternative training script for InternVL2_5-1B (sub-1B) |
inference_hindi_ocr.py | CLI inference script |
colab_hindi_ocr.ipynb.py | Colab notebook cells (copy-paste ready) |
README.md | This file |