Views
No views yet
| Property | Value |
|---|---|
| Base Model | Qwen/Qwen2.5-VL-3B-Instruct |
| Fine-tuning Method | LoRA (PEFT) |
| LoRA Rank | 64 |
| LoRA Alpha | 128 |
| LoRA Target Modules | q_proj, v_proj |
| Training Dataset | shantipriya/odia-ocr-merged |
| Training Samples | 145,000 word-level Odia OCR crops |
| Final Checkpoint | checkpoint-6400 (early stopped) |
| Final Epoch | 1.50 |
| Final Train Loss | ~4.83 |
| Best Eval Loss | 5.454 |
| Training Hardware | NVIDIA H100 80GB |
| Training Duration | ~12.7 hours |
| Learning Rate | 3e-4 (cosine decay to 2.7e-5) |
| Batch Size | 8 (per device 2 × grad accum 4) |
shantipriya/odia-ocr-merged, the ground truth label,
the model-extracted text, and a quality remark.| Image | Ground Truth | Extracted Text | Remark |
|---|---|---|---|
![]() | ଫୁଲି | ଫୁଲି | ✅ Exact match |
![]() | ସିମିତ | ସିମିତ | ✅ Exact match |
![]() | କାବୁ | କାବୁ | ✅ Exact match |
![]() | ସେରେସ | ସେରେସ | ✅ Exact match |
![]() | କଳାଭାଲୁ | କଳାଭାଲୁ | ✅ Exact match |
| Image | Ground Truth | Extracted Text | Remark |
|---|---|---|---|
![]() | ପ୍ରେରଣର | ପ୍ରେରଣର | ⚠️ Diacritic or conjunct substitution |
![]() | ମୈସ୍ଚୁସେଟ୍ସ | ମୈସ୍ଚୁସେଟ୍ସ | ⚠️ Diacritic or conjunct substitution |
![]() | ଜ୍ୱରଜାତ | ଜ୍ୱରଜାତ | ⚠️ Diacritic or conjunct substitution |
![]() | ସ୍ୱର୍ଣ | ସ୍ୱର୍ଣ | ⚠️ Diacritic or conjunct substitution |
![]() | ରାଜବଂଶର | ରାଜବଂଶର | ⚠️ Diacritic or conjunct substitution |
| Image | Ground Truth | Extracted Text | Remark |
|---|---|---|---|
![]() | ଜାତି-ଧର୍ମ-ବର୍ଣ୍ଣ-ସଂପ୍ରଦାୟାଦିର | ଜାତି-ଧର୍ମ-ବର୍ଣ | ❌ Truncated — long compound word or low-res image |
![]() | ୬-୦-ମିଥାଇଲଏରିଥ୍ରୋମାଇସିନ | ୬-୦-ମିଥାଇଲଏ | ❌ Truncated — long compound word or low-res image |
![]() | ପ୍ରକାଶକ-ଜ୍ୟୋତିଷ-ବାସ୍ତୁ | ପ୍ରକାଶକ-ଜ୍ୟ | ❌ Truncated — long compound word or low-res image |
![]() | ଚନ୍ଦ୍ରଗିରି-ପଟ୍ଟାଙ୍ଗୀ | ଚନ୍ଦ୍ରଗିରି | ❌ Truncated — long compound word or low-res image |
![]() | ଶ୍ଵେତଚମ୍ପକବର୍ଣ୍ଣାଭା | ଶ୍ଵେତଚମ୍ପ | ❌ Truncated — long compound word or low-res image |
| Category | Approx. Share | Typical Cause |
|---|---|---|
| ✅ Good (exact match) | ~65–70% | Clean, well-segmented printed crops |
| ⚠️ Mixed (1–2 char errors) | ~20–25% | Complex conjuncts, long-vowel matras |
| ❌ Bad (heavily wrong) | ~10–15% | Degraded scans, compound words, low-res |
Note: CER/WER metrics on a curated test split are pending. Percentages are estimated from qualitative review of ~200 samples.
1from transformers import AutoProcessor, Qwen2_5_VLForConditionalGeneration
2from peft import PeftModel
3import torch
4from PIL import Image
5
6base_model = "Qwen/Qwen2.5-VL-3B-Instruct"
7adapter_model = "shantipriya/odia-ocr-qwen-finetuned_v2"
8
9processor = AutoProcessor.from_pretrained(base_model, trust_remote_code=True)
10model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
11 base_model, torch_dtype=torch.float16, device_map="auto", trust_remote_code=True
12)
13model = PeftModel.from_pretrained(model, adapter_model)
14model.eval()
15
16def ocr_image(image_path: str) -> str:
17 image = Image.open(image_path).convert("RGB")
18 messages = [{
19 "role": "user",
20 "content": [
21 {"type": "image", "image": image},
22 {"type": "text", "text": "Extract the Odia text from this image. Return only the text."}
23 ]
24 }]
25 text_prompt = processor.apply_chat_template(
26 messages, tokenize=False, add_generation_prompt=True
27 )
28 inputs = processor(text=[text_prompt], images=[image], return_tensors="pt").to(model.device)
29 with torch.no_grad():
30 output_ids = model.generate(**inputs, max_new_tokens=128, do_sample=False, temperature=1.0)
31 generated = output_ids[:, inputs["input_ids"].shape[1]:]
32 return processor.batch_decode(generated, skip_special_tokens=True)[0].strip()
33
34print(ocr_image("odia_word.png"))| Checkpoint | Step | Epoch | Train Loss |
|---|---|---|---|
| checkpoint-3200 | 3,200 | 0.77 | ~5.2 |
| checkpoint-6000 | 6,000 | 1.45 | ~4.85 |
| checkpoint-6200 | 6,200 | 1.50 | ~4.92 |
| checkpoint-6400 ← Final | 6,400 | 1.51 | ~4.83 |
1@misc{parida2026odiaocr,
2 author = {Shantipriya Parida and OdiaGenAI Team},
3 title = {Odia OCR: Fine-tuned Qwen2.5-VL for Odia Script Recognition},
4 year = {2026},
5 publisher = {HuggingFace},
6 howpublished = {\url{https://huggingface.co/shantipriya/odia-ocr-qwen-finetuned_v2}},
7 note = {LoRA fine-tune of Qwen2.5-VL-3B-Instruct on 145K Odia OCR word crops}
8}1@misc{parida2026odiadataset,
2 author = {Shantipriya Parida},
3 title = {Odia OCR Merged Dataset},
4 year = {2026},
5 publisher = {HuggingFace},
6 howpublished = {\url{https://huggingface.co/datasets/shantipriya/odia-ocr-merged}}
7}