Many Cambodians type Khmer using the Latin alphabet. They write brodae for ប្រដែ, because a Latin keyboard is always at hand and Khmer keyboards are slower to use. The text is easy to write but hard to search, store or read back in Khmer.
Turning it back into Khmer script is harder than it looks, because romanized Khmer has no standard spelling. People write the same word in different ways, and one Latin spelling can match several Khmer words. A good transliterator has to infer which word the writer most likely meant.
AkaraAlpha is our attempt at this with a very small model: 78,705 parameters, small enough to suggest words as someone types. In brief:
- The model has a character error rate of 15.07% on held-out words. That is lower than every baseline we trained on the same data, including a Transformer with three times as many parameters.
- A dictionary check after the model raises word-level accuracy a long way. With five candidates, the top suggestion is right 73.6% of the time, against 44.4% for the model's single best guess.
- The whole system takes about 94 ms per word with five candidates, inside the 100 ms that typing tends to tolerate.
The model, dictionary and code are open source under the MIT licence.
Data#
We trained on the Khmer Text Transliteration Dataset (Chhunneng, 2023): 28,569 single words, each written in romanized form and in Khmer script. We held out 20% (5,714 words) for evaluation and trained on the remaining 22,855.
The words are short. No romanized input is longer than 25 characters and no Khmer output longer than 24. The model needs to learn mappings between 26 Latin letters and 77 Khmer characters.

Architecture#
The right Khmer character for a Latin letter often depends on the letters around it, including the ones that come after it. A model that reads only left to right has to commit to each character before it has seen that evidence.
AkaraAlpha's encoder is therefore a bidirectional GRU. It reads the romanized word in both directions, so every position carries context from the whole word. Each Latin character first becomes a 32-dimensional embedding, and the GRU has 64 units.
The decoder is a GRU that writes one Khmer character at a time. At every step, additive attention lets it look back over the encoded input and focus on the letters that matter for the character it is about to write.

We trained for 50 epochs with Adam, a batch size of 64 and sparse categorical cross-entropy. The learning rate was halved whenever validation loss stopped improving for three epochs.
Dictionary post-processing#
A small model often produces output that sounds right but is spelled wrong. Rather than make the model bigger, we check its output against a Khmer dictionary of about 38,700 words.
The model proposes several candidates using beam search, and each is normalized to a standard Khmer spelling. Candidates that are real words come first. Each remaining candidate is replaced by the closest dictionary word within two edits, by Levenshtein distance, where one exists. If no candidate is near any dictionary word, the system returns the model's own suggestions unchanged rather than nothing.

Results#
Model#
We compared AkaraAlpha with five other sequence-to-sequence models, from a plain RNN to a Transformer. All were trained on the same data and scored on the same held-out words. These scores are for the models alone, before any dictionary check.
| CER (%) | 15.07 (best in this row) | 17.78 (second best in this row) | 18.26 | 31.78 | 51.64 | 102.41 |
|---|---|---|---|---|---|---|
| Parameters | 78,705 | 248,337 | 96,753 | 58,417 | 46,385 | 42,609 |
Attention made the biggest difference. Every model without it had an error rate above 30%. The plain RNN's rate is above 100%, which can only happen when a model inserts more wrong characters than the correct word contains. Among the models with attention, AkaraAlpha came first with under a third of the Transformer's parameters.

Full system#
A character error rate of 15% still leaves many words with at least one wrong character, and a word with one wrong character is a wrong word. What a user sees is whether the suggestion is right. So for the full system, with the dictionary check, we measured word-level accuracy:
- Top-1 is the share of words where the first suggestion is exactly right.
- Top-K is the share where the right word is anywhere in the list of suggestions.
| Decoding | Top-1 | Top-K | Latency per word |
|---|---|---|---|
| Greedy (1 candidate) | 44.44% | 44.44% | 21.92 ms |
| Beam, k = 3 | 70.06% | 78.72% | 66.03 ms |
| Beam, k = 5 | 73.60% | 83.41% | 94.15 ms |
| Beam, k = 7 | 74.87% | 85.60% | 122.10 ms |
| Beam, k = 10 | 75.85% | 87.37% | 167.21 ms |
Most of the gain comes from the first few extra candidates. Going from one candidate to five raises Top-1 accuracy by 29.16 percentage points. Going from five to ten adds only 2.25 more, and pushes latency well past 100 ms. We therefore recommend k = 5: fast enough to update as someone types, and the right word appears somewhere in the list 83% of the time.
Limitations#
- Words, not sentences. The model transliterates one word at a time, so it can't use the surrounding sentence to decide between two words with the same romanized spelling.
- No separate test set. The held-out words were also used to adjust the learning rate during training, so these scores may be slightly optimistic.
- One way of romanizing. All the training data comes from a single dataset. People who spell Khmer differently in Latin letters may get worse results.
- The dictionary has edges. A name or new word that isn't in the dictionary may be "corrected" into a real word that happens to be within two edits. Use the model's raw candidates when that matters.
- Latency depends on hardware. The timings above were measured on one machine. They are best read as the relative cost of each setting, not as what every device will see.
Usage#
The model and dictionary ship in a small Python package:
pip install netra-transliterate
from khmer_transliterator import transliterate, transliterate_with_dict
transliterate("brodae") # 'ប្រដែ'
transliterate_with_dict("brodae", n=3) # dictionary-checked suggestions
The package also includes a command-line tool, netra-transliterate. Running netra-transliterate --serve opens a typing interface in the browser that suggests Khmer words as you type romanized ones. Tab cycles through the suggestions and Space accepts one.
References#
- Chhunneng. (2023). Khmer Text Transliteration Dataset [Data set]. GitHub. https://github.com/Chhunneng/khmer-text-transliteration
Cite this paper
@misc{netralab2026akaraalpha,
title = {{AkaraAlpha: A small model that turns romanized Khmer into Khmer script}},
author = {{Netra Lab}},
year = {2026},
url = {https://netra-lab.example/research/akara-alpha}
}