Views
No views yet
facebook/w2v-bert-2.0 — a large-scale, multilingual self-supervised
speech encoder pretrained with a BERT-style masked prediction
objective — is used as the backbone, with a from-scratch
character-level CTC (Connectionist Temporal Classification) head
fine-tuned specifically for Shona.-best checkpoint when you want
cased/punctuated output directly from the acoustic model.train split only from WAXAL, all splits pooled from
each of the four extra sources, deduplicated by audio hash and by
transcription-within-source):| Source | Role |
|---|---|
google/WaxalNLP (sna_asr config) | Benchmark dataset — train split pooled into training, validation split held out untouched as the fixed evaluation benchmark |
| badrex/shona-speech | All splits (train/val/test) pooled into training |
| Beijuka/DigitalUmuganda_AfriVoice_shona | All splits pooled into training (only has train) |
| shunyalabs/shona-speech-dataset | All splits (train/val/test) pooled into training |
| realtime-speech/shona2 | All splits (train/val/test) pooled into training |
validation split
is the only data used for evaluation, and it was never included in
training.facebook/w2v-bert-2.0Wav2Vec2BertForCTC, add_adapter=TrueWav2Vec2BertProcessor — SeamlessM4TFeatureExtractor
for audio features + a Wav2Vec2CTCTokenizer built from scratch on
the combined training + validation transcriptions (character-level
vocabulary, raw/cased text, | as the word delimiter, [PAD]
doubling as the CTC blank token)output_steps < 2 * label_length) are dropped from
both train and validation before trainingvalidation split, greedy decoding vs.
greedy + KenLM (keystats/waxal-kenlm-models-best). Adding the KLM
gives a consistent, meaningful WER/CER improvement over greedy
decoding alone — pair the two for the best results.pyctcdecode +
KenLM, noticeably higher accuracy via beam-search decoding with a
matching language model.1import torch
2import librosa
3from transformers import Wav2Vec2BertForCTC, Wav2Vec2BertProcessor
4
5MODEL_ID = "keystats/w2v-bert-2.0-shona-main-best"
6DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
7
8processor = Wav2Vec2BertProcessor.from_pretrained(MODEL_ID)
9model = Wav2Vec2BertForCTC.from_pretrained(MODEL_ID).to(DEVICE).eval()
10
11audio_array, sr = librosa.load("path/to/audio.wav", sr=16000, mono=True)
12inputs = processor(audio_array, sampling_rate=16000, return_tensors="pt")
13with torch.no_grad():
14 logits = model(input_features=inputs.input_features.to(DEVICE)).logits
15
16predicted_ids = torch.argmax(logits, dim=-1)
17transcription = processor.batch_decode(predicted_ids)[0]
18
19print(transcription) # cased, punctuated Shona textshona/shona_5gram_correct.arpa). Pairing this ASR model with its
matching KLM via beam-search decoding gives a significant accuracy
improvement over greedy decoding alone.-best model pairs with the cased
keystats/waxal-kenlm-models-best repo, while a normalized
(lowercased) sibling checkpoint, if one exists, would pair with the
separate keystats/waxal-kenlm-models repo instead. Mixing a
cased-text ASR model with a normalized-text KLM (or vice versa) will
cause a vocabulary mismatch during decoding.1# pip install pyctcdecode
2# pip install https://github.com/kpu/kenlm/archive/master.zip
3
4import torch
5import librosa
6from huggingface_hub import hf_hub_download
7from transformers import Wav2Vec2BertForCTC, Wav2Vec2BertProcessor
8from pyctcdecode import build_ctcdecoder
9
10MODEL_ID = "keystats/w2v-bert-2.0-shona-main-best"
11KLM_REPO_ID = "keystats/waxal-kenlm-models-best"
12DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
13
14processor = Wav2Vec2BertProcessor.from_pretrained(MODEL_ID)
15model = Wav2Vec2BertForCTC.from_pretrained(MODEL_ID).to(DEVICE).eval()
16
17klm_path = hf_hub_download(repo_id=KLM_REPO_ID, repo_type="dataset",
18 filename="shona/shona_5gram_correct.arpa")
19
20def build_vocab_list(tokenizer, vocab_size):
21 vocab_dict = tokenizer.get_vocab()
22 vocab_list = [None] * vocab_size
23 for tok, idx in sorted(vocab_dict.items(), key=lambda kv: kv[1]):
24 if idx < vocab_size:
25 vocab_list[idx] = tok
26 pad_id = tokenizer.pad_token_id
27 if pad_id is not None and pad_id < len(vocab_list):
28 vocab_list[pad_id] = ""
29 word_delim = getattr(tokenizer, "word_delimiter_token", None)
30 if word_delim:
31 delim_id = vocab_dict.get(word_delim)
32 if delim_id is not None:
33 vocab_list[delim_id] = " "
34 return vocab_list
35
36vocab_list = build_vocab_list(processor.tokenizer, model.config.vocab_size)
37decoder = build_ctcdecoder(
38 vocab_list,
39 kenlm_model_path=klm_path,
40 alpha=0.5, # LM weight -- tune against your own validation set
41 beta=0.7, # word insertion bonus -- tune against your own validation set
42)
43
44audio_array, sr = librosa.load("path/to/audio.wav", sr=16000, mono=True)
45inputs = processor(audio_array, sampling_rate=16000, return_tensors="pt")
46with torch.no_grad():
47 logits = model(input_features=inputs.input_features.to(DEVICE)).logits
48
49transcription = decoder.decode(logits.cpu().numpy()[0], beam_width=100)
50print(transcription)1@misc{keystats_wav2vec2bert_shona,
2 title={w2v-bert-2.0-shona-main-best: A Shona ASR model fine-tuned from facebook/w2v-bert-2.0},
3 author={keystats},
4 year={2026},
5 howpublished={\url{https://huggingface.co/keystats/w2v-bert-2.0-shona-main-best}}
6}
7
8@misc{waxal,
9 title={WAXAL: A Multilingual African Speech Dataset},
10 author={Google},
11 howpublished={\url{https://huggingface.co/datasets/google/WaxalNLP}}
12}
13
14@misc{badrex_shona_speech,
15 title={shona-speech},
16 author={badrex},
17 howpublished={\url{https://huggingface.co/datasets/badrex/shona-speech}}
18}
19
20@misc{beijuka_shona,
21 title={DigitalUmuganda\_AfriVoice\_shona},
22 author={Beijuka},
23 howpublished={\url{https://huggingface.co/datasets/Beijuka/DigitalUmuganda_AfriVoice_shona}}
24}
25
26@misc{shunyalabs_shona,
27 title={shona-speech-dataset},
28 author={shunyalabs},
29 howpublished={\url{https://huggingface.co/datasets/shunyalabs/shona-speech-dataset}}
30}
31
32@misc{realtime_speech_shona,
33 title={shona2},
34 author={realtime-speech},
35 howpublished={\url{https://huggingface.co/datasets/realtime-speech/shona2}}
36}
37
38@inproceedings{w2vbert2,
39 title={Seamless: Multilingual Expressive and Streaming Speech Translation},
40 author={Seamless Communication and others},
41 year={2023},
42 howpublished={\url{https://huggingface.co/facebook/w2v-bert-2.0}}
43}