Model Card for Ottoman_Print_OCR_QWEN4B

This model is a vision-language adapter for Qwen3.5-4B with LoRA (via Unsloth) for Ottoman Turkish printed texts in printed Naskh font. It mainly operates at the line level. It might still work on multi-line level.

The output is not modern Turkish transliteration but the original Perso-Arabic script. In this way, researchers can analyze the ortographic patterns in Ottoman Turkish directly, such as how the question suffix, +mI, was written etc. Since there are different ways to transliterate a text (e.g., IJMES Transliteration and Modern Turkish alphabet) this approach preserves the information on the text as its original form and lets other researchers to build their of transliteration tools by using the output of this OCR model.

The model processes the data with 96% character-level accuracy and 80% word-level accuracy. With further normalization, these values go to 98% character-level and 88% word-level.

You can find an example on how this model can be used here Through this link, you can find Eşar-ı Ziya as processed for OCR. You can search for a word or phrase. Such an interface can be expandable to other works with this model as well.

Data

The training data consists of 48,306 words in 5,375 lines across nine printed Ottoman Turkish works (Eşar-ı Ziya to represent poetry, New Testament (vol 2, 1857 edition) for religious/narrative works, Medhal-i Fıkh for Islamic law language, Muahedat Mecmuası for diplomatic language), Solakzade Tarihi and Muhtasar Tarih-i Umumi for history domain, Mir'at-ı Alem for the language in magazines, Kozmoğrafya, yahut, İlm-i ahval-i sema for science/astrology domain, and Mecmua-i Fünûn-i Askeriyye for military domain).

The OCR training data was manually prepared by the author.

Since the training data does not cover all genres, it might not be comprehensively effective in all Ottoman Turkish documents.

The distribution of data per work can be seen below.

Source Name Lines Words
Medhal-i Fıkh 544 4749
New Testament 1420 15672
Eşar-ı Ziya 1191 7162
Muahedat Mecmuası 470 4744
Mir'at-ı Alem 500 4006
Solakzade Tarihi 300 3680
Mecmua-i Fünûn-i Askeriyye 300 2792
Muhtasar Tarih-i Umumi 500 4271
Kozmoğrafya, yahut, İlm-i ahval-i sema 150 1230
TOTAL 5375 48306

Training Hyperparameters

The following hyperparameters were used during training:

Hyperparameter Value
Learning Rate 2e-05
Train Batch Size (per device) 4
Gradient Accumulation Steps 4
Optimizer 8-bit AdamW (adamw_8bit)
LR Scheduler Type Cosine (cosine)
Warmup Ratio 0.1
Weight Decay 0.05
Number of Epochs 3
Max Sequence Length 256
LoRA R 64
LoRA Alpha 64
Seed 3407

Training Results

The training process was stopped at 550 steps, achieving the following best evaluation metric:

  • Best Validation Loss: 0.139433

Evaluation Results

The model was evaluated on a test set of 807 lines.

Metric Baseline Normalized (Ye + Kef)
CER (Character Error Rate) 4.12% 2.37%
WER (Word Error Rate) 19.9% 12.13%
  • Mean Line CER: 3.03%
  • Median Line CER: 1.69%
  • Perfect Matches: 350 out of 807 lines (CER = 0)

Normalization Process

To achieve the best results, the following character normalization is recommended for the output:

  • \u064a and \u0649 $\rightarrow$ \u06cc (Persian/Arabic Ye)
  • \u0643 $\rightarrow$ \u06a9 (Kef/Keheh)
  • Removal of ZWNJ (\u200c) and ZWJ (\u200d)

The first two processes do not make any significant change on how the data looks like. The last one is optional. It is basically the invisible character to write a letter in the word-ending word in the middle of a word (like داىٔره‌ده). The model is supposed to put this character in its output.

How to Use

This model requires the unsloth library and torch.

from unsloth import FastVisionModel
import torch
from PIL import Image

# 1. Load Model & Tokenizer
model, tokenizer = FastVisionModel.from_pretrained(
    "enesyila/Ottoman-Print-OCR-Qwen4B",
    load_in_4bit=True,
)
FastVisionModel.for_inference(model)
tokenizer.padding_side = "left"

# 2. Load Image
image_path = "path_to_your_line_image.png"  # You should put the path of your image here.
image = Image.open(image_path).convert("RGB")

# 3. Prepare Prompt
instruction = "Transcribe the Ottoman Turkish printed text in this image."  # Please do not change this instruction. The model was trained with this instruction so it should work the best with this.
messages = [
    {"role": "user", "content": [
        {"type": "image"},
        {"type": "text", "text": instruction},
    ]}
]
prompt = tokenizer.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False) # disabling thinking ensures that the model will only give the OCR output and not its reasoning.

# 4. Tokenize & Generate
inputs = tokenizer(
    images=[image],
    text=[prompt],
    add_special_tokens=False,
    return_tensors="pt",
).to("cuda")

if "pixel_values" in inputs:
    inputs["pixel_values"] = inputs["pixel_values"].to(torch.bfloat16)

with torch.inference_mode():
    output_ids = model.generate(
        **inputs,
        max_new_tokens=128,  # This value is enough for just one line. If you want to process larger pieces of text, you can increase this value but I can't guarantee that the model will work on multi-line level.
        use_cache=True,
        do_sample=False,
        temperature=0.0,
        repetition_penalty=1.1,
    )

# 5. Decode Result
input_len = inputs.input_ids.shape[1]
result = tokenizer.decode(output_ids[0][input_len:], skip_special_tokens=True).strip()

print("Transcription:", result)

Copyright

This model is licensed under Creative Commons Attribution Non Commercial 4.0. Therefore, the commercial use is strictly forbidden. However, you can use this model for your research freely.

Contact

enes.yilandiloglu@helsinki.fi

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for enesyila/Ottoman-Print-OCR-Qwen4B

Finetuned
Qwen/Qwen3.5-4B
Finetuned
(245)
this model