Downloads · 30 days
21
32% of all-time downloads
pandakingpunc/megazeka-byt5-tr-spellfix
megazeka-byt5-tr-spellfix is a text generation model from pandakingpunc. Use it when you need the model to write or continue text. It is set up for peft. The card lists the license as apache-2.0.
A LoRA adapter for google/byt5-small that corrects Turkish spelling, typos, punctuation, capitalization, spacing, common keyboard errors and chat-style colloquial spellings (gidicem → gideceğim, bilmiyom → bilmiyorum,…
Downloads · 30 days
21
32% of all-time downloads
All-time downloads
66
Public
Repo size
50.1 MB
Likes
0
Public
Click a slice to open those files.
.safetensors25.1 MB · 100%
From the Hugging Face model README
A LoRA adapter for google/byt5-small that corrects Turkish spelling, typos, punctuation,
capitalization, spacing, common keyboard errors and chat-style colloquial spellings
(gidicem → gideceğim, bilmiyom → bilmiyorum, burda → burada). Trained locally on a single
RTX 4060.
This is a small educational experiment, not a production-grade spell checker. Read the limitations before using it for anything that matters.
The first release (v1) did not correct colloquial forms at all — gidicem, buluşcaz, gidicez came
out unchanged — because its training data was almost entirely literary third-person sentences
(gideceğim appeared 8 times in 32,000 pairs). v2 changes the data, not the architecture:
-eceğim → -icem/-cem,
-acağız → -ıcaz/-caz, -yorum → -yom, -yor → -yo, consonant hardening (gideceğim → gitcem),
plus word rules (burada → burda, bir şey → bişey, herkes → herkez, yalnız → yanlız, …).
Colloquial operations in the training split went from 1,001 to 8,178.On the same 160 held-out Common Voice target sentences (noised differently in each version, so the pairs
are not identical), exact match went from 60.6% (v1) to 70.3% (v2). The v1 adapter is still available
with revision="v1".
Turkish spelling errors are overwhelmingly diacritic errors: ı/i, İ/I, ş/s, ğ/g, ç/c,
ö/o, ü/u. Subword tokenizers fragment unpredictably when those characters are corrupted, so a
misspelled word and its correction can land in completely unrelated token space. ByT5 operates on
raw UTF-8 bytes and has no vocabulary to fall out of, which makes it a natural fit for this task.
The cost is sequence length — a Turkish character is often two bytes.
Held-out test set: 1,128 pairs derived from 282 target sentences that appear in no other split —
640 pairs from 160 Common Voice sentences and 488 pairs from 122 everyday sentences.
Copy input is the trivial do-nothing baseline. Base ByT5 is untrained google/byt5-small.
| Metric | Copy input | Base ByT5 | This adapter | Unfiltered |
|---|---|---|---|---|
| CER ↓ | 0.0963 | 0.0963 | 0.0137 | 0.0126 |
| WER ↓ | 0.3576 | 0.3579 | 0.0678 | 0.0658 |
| Exact match ↑ | 25.0% | 24.9% | 76.2% | 76.6% |
| Edit F1 ↑ | 0.000 | 0.000 | 0.898 | 0.905 |
| Overcorrection ↓ | 0.0% | 0.4% (raw 100%) | 1.8% | 1.8% |
By subset (guard on):
| Subset | Pairs | CER ↓ | WER ↓ | Exact match ↑ | Copy-input exact match | Overcorrection ↓ |
|---|---|---|---|---|---|---|
| Common Voice | 640 | 0.0171 | 0.0799 | 70.3% | 25.0% | 3.1% |
| Everyday | 488 | 0.0080 | 0.0472 | 84.0% | 25.0% | 0.0% |
Untrained ByT5 is unusable here — its raw CER is 4.04 and it rewrites every input, so the output guard falls back to the input almost everywhere. That is why its protected column is close to copy-input.
Unfiltered is the raw generation with the output guard (see below) disabled. The guard costs 0.4 points of exact match and buys protection against word substitutions and large rewrites; both are reported because which one you want depends on your use case.
Overcorrection is measured on the 282 test examples where input already equals target (5 of them were changed).
Edit precision/recall/F1 compares sets of (original position, operation, character) Levenshtein
edits; with the guard on, precision is 0.926 and recall 0.871. This is a project-defined metric and
is not comparable to standard GEC M2/ERRANT F0.5.
from transformers import AutoTokenizer, T5ForConditionalGeneration
from peft import PeftModel
tok = AutoTokenizer.from_pretrained("google/byt5-small")
base = T5ForConditionalGeneration.from_pretrained("google/byt5-small")
model = PeftModel.from_pretrained(base, "pandakingpunc/megazeka-byt5-tr-spellfix").eval()
text = "bugün okula gidicem ama hava cok kötü galiba"
ids = tok(text, return_tensors="pt")
out = model.generate(**ids, max_new_tokens=224, num_beams=1, do_sample=False)
print(tok.decode(out[0], skip_special_tokens=True))
# Bugün okula gideceğim ama hava çok kötü galiba.
For the previous release: PeftModel.from_pretrained(base, "pandakingpunc/megazeka-byt5-tr-spellfix", revision="v1").
Things the repo's own inference code (src/megazeka/inference.py) does that the snippet above does not:
gidicem → gideceğim passes, okula → eğitim kurumuna does not.The guard does not guarantee meaning preservation, and it also blocks some correct fixes.
Generation is deterministic greedy decoding (num_beams=1, do_sample=False).
Real outputs from this adapter on hand-picked sentences outside the training data (raw generation and guarded output are identical for all of these):
| Input | Output |
|---|---|
bugün okula gidicem ama hava cok kötü galiba | Bugün okula gideceğim ama hava çok kötü galiba. |
yarin arkadaşlarla buluşcaz sonrada sinemaya gidicez | Yarın arkadaşlarla buluşacağız, sonra da sinemaya gideceğiz. |
Yapıcam dedim ama yapmıcam. | Yapacağım dedim ama yapmayacağım. |
İstanbul'a gidicem ve orda kalıcam. | İstanbul'a gideceğim ve orada kalacağım. |
herkez buraya gelsin | Herkes buraya gelsin. |
Beni duyuyormusun? | Beni duyuyor musun? |
Cok tesekkur ederim. | Çok teşekkür ederim. |
Ben de seninle geleceğim, sen de gelir misin? | unchanged |
bugün sinemaya gitcez sonra yemek yiycez | Bugün sinemaya giteceğiz sonra yemek yiyeceğiz. ✗ (should be gideceğiz) |
bilmiyom ki napcam | Bilmiyorum ki napacağım. ✗ (should be ne yapacağım) |
napıyosun bugun | Napıyorsun bugün? ✗ (should be Ne yapıyorsun) |
yanlız kaldım burda | Yanlız kaldım burada. ✗ (yanlız not fixed) |
Ankaraya yarin gidicem. | Ankaraya yarın gideceğim. ✗ (missing apostrophe: Ankara'ya) |
Işık, İstanbul’a yarın gelecek. | İşık, İstanbul’a yarın gelecek. ✗ (proper noun damaged) |
17 of these 23 hand-picked examples come out exactly right (73.9%); 1 of the 9 already-correct ones was
changed (the Işık proper noun). This is a sanity check, not a success rate.
| Base | google/byt5-small, revision 68377bdc18a2ffec8a0533fef03b1c513a4dd49d |
| Method | LoRA, r=16, alpha=32, dropout 0.05 |
| Target modules | q, k, v, o, wi_0, wi_1, wo |
| Trainable params | 6,258,688 of 305,896,448 (2.05%) |
| Optimizer | AdamW, lr 5e-4, 30-step warmup, grad clip 1.0 |
| Batch | micro-batch 8 × grad accumulation 2 |
| Steps | 4,000 (3,000 with configs/medium.json, then resumed to 4,000); 64,000 examples processed |
| Validation | every 250 steps; early stopping patience 8 |
| Precision | bfloat16 base, float32 LoRA + optimizer state |
| Hardware | Ryzen 5 5600, 16 GB RAM, RTX 4060 8 GB |
| Wall clock | ~33 minutes |
| Seed | 42 |
Best checkpoint selected by target-token-weighted loss on 640 validation pairs: step 4,000, loss 0.0376 (v1: 0.0554).
38,057 training pairs from 9,226 distinct targets:
training/everyday.py, CC0-1.0),Each target yields four variants — clean, easy, medium, hard — targeting 0 / 1 / 2 / 4 applied noise operations; 25% of examples are deliberately left clean so the model learns not to touch correct text. For easy and medium everyday pairs the first operation is always a colloquial transformation.
Noise operations include letter deletion/repetition/transposition, Turkish Q-keyboard neighbours,
diacritic loss, case errors, punctuation, merged/split words, extra whitespace, de/da and ki
clitic merging, question-suffix and apostrophe loss, and suffix-based colloquial spellings. Every applied
operation is recorded with its before/after text in the dataset.
Splitting happens on canonical target form before noise is applied, so no variant of the same sentence crosses splits. This is not a claim that semantically similar sentences are separated, nor that these sentences are absent from ByT5's pretraining corpus — that overlap is unknown.
gitcez → giteceğiz instead of gideceğiz) and contractions like napcam are not fully expanded.tşk, inş) can be held back by the word lock and left unchanged.Işık → İşık), code-switched text, context-dependent de/da/ki,
missing apostrophes on proper nouns, and stylistic punctuation choices.| Version | Revision | Steps | Training pairs | Notes |
|---|---|---|---|---|
| v2 | main, tag v2 | 4,000 | 38,057 | everyday data, colloquial rules, two-layer guard |
| v1 | tag v1 | 1,800 | 32,000 | Common Voice only; colloquial forms not corrected |
google/byt5-small base model.@software{megazeka2026,
title = {Megazeka: Turkish Spelling Correction with ByT5-small and LoRA},
author = {pandakingpunc},
year = {2026},
version = {2},
url = {https://github.com/pandakingpunc/megazeka}
}