Downloads · 30 days
6
8% of all-time downloads
kaan84/sinhala-print-trocr
sinhala-print-trocr is a image-to-text model from kaan84. Use it when you need a caption or text from an image. It is set up for transformers. The card lists the license as apache-2.0.
TrOCR fine-tune for printed Sinhala text lines, with a repaired decoder tokenizer that preserves Zero Width Joiner.
Downloads · 30 days
6
8% of all-time downloads
All-time downloads
80
Public
Parameters
315M
3.8 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors1.3 GB · 100%
From the Hugging Face model README
TrOCR fine-tune for printed Sinhala text lines, with a repaired decoder tokenizer that preserves Zero Width Joiner.
Use this repo. The predecessor,
kaan84/sinhala-print-trocr-pilot,
is frozen and contains a tokenizer defect; it is kept only as the published record
of that finding.
| this repo | predecessor | |
|---|---|---|
| name | sinhala-print-trocr | sinhala-print-trocr-pilot |
| role | current model | frozen "before" state |
| tokenizer | ZWJ preserved | deletes ZWJ |
Input is a single line image (~2600×128). This is not a page or document recogniser — see Real documents for what page-level use requires.
The predecessor's BertNormalizer ran with clean_text=True, deleting all Unicode
Cf characters including U+200D ZWJ — the character that forms Sinhala conjuncts
such as ශ්රී. Two changes were needed, and the order matters:
[UNK] if any character
is missing from the vocabulary. Patching the normalizer alone would have made
output strictly worse. Five tokens were injected directly into model.vocab
(32,000 → 32,005). add_tokens() does not work here: it creates standalone
AddedTokens that bypass WordPiece, so the decoder inserts spaces around them.clean_text=False.New embedding rows were warm-started (##x copies the row for x; ZWJ takes the
matrix mean), then fine-tuned.
tok = AutoTokenizer.from_pretrained("kaan84/sinhala-print-trocr")
s = "ශ්\u200Dරී"
tok.decode(tok.encode(s, add_special_tokens=False)) == s # True
Controlled ablation: identical base checkpoint, data, seed (42), epochs and effective batch size. The tokenizer is the only difference. Held-out 5% split, 349 lines.
| pilot (as published) | control (retrained, old tokenizer) | this model | |
|---|---|---|---|
| char-CER (codepoint) | 0.1820 | 0.1709 | 0.1690 |
| g-CER (grapheme cluster) | 0.2045 | 0.1886 | 0.1852 |
| emitted any ZWJ | 0/20 (impossible) | 0/20 (impossible) | 2/20 |
| conjunct recall (exact) | 0/19 | 0/26 | 0/26 |
Compare against control, not against the pilot — the pilot-to-fixed gap includes extra training and would overstate the change.
The fix removes a hard ceiling. It does not improve accuracy at current error rates.
g-CER uses grapheme clusters from
grapheme-kit. Report it alongside
codepoint CER, never instead of it: grapheme-CER runs higher when errors corrupt a
cluster from inside (a stripped ZWJ) and lower when a whole multi-codepoint
grapheme is misread. A number that falls when you switch units is a change of ruler,
not a better model.
' ', '##‼') arose from ZWJ adjacent to spaces and punctuation in the corpus.
They are unreachable in practice (BertPreTokenizer splits on whitespace) but
indicate upstream noise.avishadilhara/sinhala-ocr-lk-acts-1010 contains full page scans (~1650×2450 to
2480×3509, 1,200–2,500 characters per page), while this model reads single lines.
Pages must be segmented before recognition.
Preliminary, one page from the test split with Tesseract layout analysis: 37 lines detected, char-CER 0.4657. Page-level ground truth means concatenated line predictions conflate recognition errors with reading-order errors. A full 202-page benchmark is pending.
The defect fixed here is in the normalizer, not the pre-tokenizer.
BertPreTokenizer preserves ZWJ and yields one pre-token per conjunct, so the
pre-tokenization compression ceiling described in the COLING paper does not apply to
this tokenizer.