omniASR-CTC-300M Kazakh (fine-tuned)
A Kazakh-specialised CTC speech-recognition model, fully fine-tuned from
omniASR_CTC_300M_v2 (the 300M-parameter CTC member of Meta's
Omnilingual ASR family,
pretrained on 1600+ languages) on Kazakh speech from
ISSAI Kazakh Speech Corpus 2
and the Kazakh split of
Google FLEURS.
Unlike the multilingual base model, this checkpoint is
specialised for Kazakh: it more
than halves Word Error Rate on Kazakh at the cost of degrading on other languages
(see
Limitations). It is a full fine-tune — the entire encoder and the CTC
projection head were trained — not an adapter.
- Base model:
omniASR_CTC_300M_v2 (Apache 2.0)
- Tokenizer:
omniASR_tokenizer_written_v2
- Task: Kazakh automatic speech recognition (Cyrillic script)
- Decoding: greedy CTC (no external language model)
Results
Evaluated with greedy CTC decoding. WER = Word Error Rate, CER = Unit Error Rate
reported by the omnilingual-asr eval recipe (character-level). Lower is better.
| Model | Test set | WER % | CER % |
|---|
| Fine-tuned | KSC2 (kk) | 18.64 | 4.84 |
| Base | KSC2 (kk) | 40.19 | 11.45 |
| Fine-tuned | FLEURS en | 58.67 | 23.01 |
| Base | FLEURS en | 17.13 | 5.46 |
| Fine-tuned | FLEURS ru | 33.52 | 8.28 |
| Base | FLEURS ru | 28.91 | 6.04 |
Base → fine-tuned (WER):
| Test set | Base | Fine-tuned | Δ |
|---|
| KSC2 (kk) | 40.19 | 18.64 | −21.55 (improved) |
| FLEURS en | 17.13 | 58.67 | +41.53 (regressed) |
| FLEURS ru | 28.91 | 33.52 | +4.61 (regressed) |
The large improvement on Kazakh and the regression on English/Russian are the expected
signature of monolingual specialisation (catastrophic forgetting). Russian degrades less
than English, likely because KSC2 contains Russian loanwords and code-switching that keep
some Russian signal alive during training.
Qualitative comparison (KSC2 test)
Sample transcriptions, base omniASR_CTC_300M_v2 vs this fine-tune, on the same audio.
Picked to show typical base errors (word boundaries, vowels, endings) that fine-tuning fixes.
| Reference | Base | Fine-tuned |
|---|
| алғашқы келушілерді мұражай екі мың бесінші жылдың наурыз айында қабылдаған | алғашқы келушілерді мұража екі мың бесінші жылдың наурүз айында қабылда қаре | алғашқы келушілерді мұражай екі мың бесінші жылдың наурыз айында қабылдаған |
| қуандық аға жалпы түс дегеніміз не түсті жору дегеніміз не | қуандығаға жалпы түс дегенімізіне түсті жору дегенімізіне | қуандық аға жалпы түс дегеніміз не түсті жору дегеніміз не |
| қазір болған аумаққа қаладағы коммуналдық қызмет толық жұмылдырылды | қазыр болған аумаққа қарадағы коммуналдық қызмет толық жұмылдырылды | қазір болған аумаққа қаладағы коммуналдық қызмет толық жұмылдырылды |
| тұрақтылық бейбітшілік пен келісім қай мемлекеттің болмасын басты байлығы | тұрақтылық бебітшілік пен келісім қай мемлекеттің болмасын басты байлығы | тұрақтылық бейбітшілік пен келісім қай мемлекеттің болмасын басты байлығы |
| зияда әбдіқожаева көпбалалы ана шеберхананы ашқан себебім қазіргі таңда ешкім ағашпен жұмыс істегісі келмейді | зияда әбдіқожаева көп балалы ана шеберхананы ашқан себебім қазірғі танда ешкім ағаш пен жұмыс істегісі келмейді | зияда әбдіқожаева көпбалалы ана шеберхананы ашқан себебім қазіргі таңда ешкім ағашпен жұмыс істегісі келмейді |
| артық екен ғаламторсыз сол дала табынбайтын балгерге де балға да | артық екенін ғалам тоырсыз солдала табынбайтын балгергей де балғады | артық екен ғаламторсыз сол дала табынбайтын балгерге де балғады |
| себебі балам менің қасымда еркелеп жылап қалуы мүмкін деп ойладым | себебі бала менің қасымда еркелеп жылап қалу мүмкін деп ойладым | себебі бала менің қасымда еркелеп жылап қалуы мүмкін деп ойладым |
| ол жерде не керек емес аптасына неше рет жаттығу керек | ол жерден неелек эмес аптасына неширет жаттыгуу керек | ол жерде не керек емес аптасына неше рет жатты ғу керек |
| машиналар мен катерлер аударылып шамамен он үш мың үй қирады | машиналармен катерлер аударылып шамамен оныш мін үй қирады | машиналар мен катерлер аударылып шамамен он үш мын үй құрады |
| біріншіден шетелдік мамандар мен спортшыларды тарту тәжірибесінен бас тарту | біріншіден шетелдік мамандармен спортшыларды тарту тәжірбесін бастарту | біріншіден шетелдік мамандар мен спортшыларды тарту тәжірибесін бас тарту |
Limitations
- Monolingual specialisation. This model is intended for Kazakh only. On other
languages it performs worse than the multilingual base model. Do not use it as a
general multilingual ASR system.
- No language model. Reported numbers use greedy CTC decoding. Adding an n-gram LM
(e.g. KenLM) with CTC beam search is expected to reduce WER further at inference time,
with no retraining.
- Domain. Trained primarily on KSC2 (podcasts, radio, TV news, parliament, talk
shows and crowdsourced readings). Far-field, heavy-noise or strongly accented speech
outside this distribution may degrade.
- Audio format. Expects 16 kHz mono audio, amplitude-normalised, ≤ ~40 s per clip
(split longer audio before transcription).
- Output format. Trained on normalised references (lowercased, whitespace-collapsed, no
punctuation), so it emits lowercase Kazakh with no punctuation or capitalisation.
Usage
This is a fairseq2 / omnilingual-asr checkpoint, not a transformers model. Install the
stack first:
1# minimal — inference only:
2pip install omnilingual-asr
3
4# or the full pipeline stack (training, eval, augmentation):
5# pip install -r requirements.txt
6
7# libsndfile is required for audio decoding:
8# Linux: sudo apt-get install libsndfile1
9# macOS: brew install libsndfile
Transcription goes through ASRInferencePipeline, which resolves a model asset card.
Register a user card (in any dir exported as FAIRSEQ2_USER_ASSET_DIR) pointing at the
downloaded omniASR_CTC_300M_kk.pt, then pass its name as model_card:
1# cards/omniASR_CTC_300M_kk.yaml (place in a dir on FAIRSEQ2_USER_ASSET_DIR)
2name: omniASR_CTC_300M_kk
3model_family: wav2vec2_asr
4model_arch: 300m_v2
5checkpoint: "/abs/path/to/omniASR_CTC_300M_kk.pt"
6tokenizer_ref: omniASR_tokenizer_written_v2
1from omnilingual_asr.models.inference.pipeline import ASRInferencePipeline
2
3# CTC cards ignore the language argument, but the pipeline still expects the kwarg.
4pipeline = ASRInferencePipeline(model_card="omniASR_CTC_300M_kk")
5
6audio_files = ["kazakh_audio.flac"] # 16 kHz mono; resampled automatically if needed
7transcriptions = pipeline.transcribe(audio_files, lang=["kaz_Cyrl"], batch_size=1)
8print(transcriptions[0])
Easiest reliable recipe: dump the base card with
python -m fairseq2.assets show omniASR_CTC_300M_v2, copy all of its fields, and override
only name + checkpoint. That pulls in tokenizer / tokenizer_family correctly.
Training
Fine-tuned with the omnilingual-asr wav2vec2.asr recipe (fairseq2 0.6). The recipe seeds
the full model (encoder + CTC head) from the base checkpoint; the convolutional feature
extractor stays frozen for stability.
- Base checkpoint:
omniASR_CTC_300M_v2 (~300M params, full fine-tune)
- Tokenizer:
omniASR_tokenizer_written_v2 (vocab 10288)
- Data: ISSAI KSC2 + Google FLEURS, Kazakh (
kaz_Cyrl)
- Optimizer: AdamW, lr
1.5e-5, betas (0.9, 0.98), weight decay 0.0
- LR schedule: tri-stage, stage ratios
[0.05, 0.35, 0.6], start scale 0.01, final scale 0.05
- Steps: 30,000
- Effective batch: ~36M audio elements/step (
max_num_elements × grad_accum)
- Precision: bfloat16 (AMP)
- Hardware: 1 × NVIDIA RTX PRO 6000 Blackwell (96 GB VRAM)
- Augmentation: 20% of training audio (KSC2 + FLEURS) replaced offline with augmented
versions before parquet building — each clip gets a random mix of additive Gaussian noise,
±10% time-stretch, and room reverberation (
audiomentations). Val/test left untouched.
In-model latent masking stays off (the released CTC checkpoint has no masker module).
Launch (single config file, single GPU):
1CUDA_VISIBLE_DEVICES=0 python -m workflows.recipes.wav2vec2.asr "$OUTPUT_DIR" \
2 --config-file kk-config.yaml
Evaluation reproducibility
Numbers above were produced by transcribing each test set with greedy CTC decoding and
computing WER/CER against the reference transcripts. KSC2 train/dev/test splits were
prepared locally.
Train/test contamination was checked: 22% of test transcripts also occur in train (expected
for read-speech, where prompts are re-read by different speakers), but 0 test clips share
byte-identical audio with train — no recording leaked across the split. Speaker-level
disjointness could not be verified because the parquet carries no speaker field. For a fully
independent benchmark, evaluate on a public set that was not part of training — note that
FLEURS Kazakh was folded into the training data here, so it does not qualify; Common Voice
Kazakh test is a clean option.
License
Apache 2.0, inherited from the base Omnilingual ASR models and code.
Citation
If you use this model, please cite Omnilingual ASR and the KSC2 corpus.
1@article{omnilingualasr2025,
2 title = {Omnilingual ASR: Open-Source Multilingual Speech Recognition for 1600+ Languages},
3 author = {{Omnilingual ASR Team}},
4 journal = {arXiv preprint arXiv:2511.09690},
5 year = {2025}
6}
7
8@inproceedings{mussakhojayeva2022ksc2,
9 title = {KSC2: An Industrial-Scale Open-Source Kazakh Speech Corpus},
10 author = {Mussakhojayeva, Saida and Khassanov, Yerbolat and Varol, Huseyin Atakan},
11 booktitle = {Interspeech},
12 year = {2022}
13}