Predicts speaker gender (male/female) from short African-language speech clips
(16 kHz). Trained and evaluated on
google/WaxalNLP (ASR + TTS
configs).
How it works
A 3D-Speaker CAM++ model trained
on VoxCeleb at 16 kHz, 512-dim output, as part of its
speaker-diarization/verification pipeline. This repo only ships a tiny MLP
head (onnx/model.onnx, 512 -> 64 -> 2) trained on top of
those embeddings.
Training data
WaxalNLP rows across 25 language configs where the gender field normalized
cleanly to male/female (case-insensitive male/m/female/f). Rows with a
blank or other value (e.g. "unknown") were dropped, as were configs where
every row failed to normalize - aka_asr, dag_asr, dga_asr, ewe_asr,
ful_asr, kpo_asr, mlg_asr, bau_tts, ewe_tts have no usable gender
labels in this dataset and are not represented in this model.
330,027 labeled utterances total (train=275862, validation=25667, test=28498). Splits follow WaxalNLP's own
train/validation/test partition (not re-shuffled). (Note: WaxalNLP's sog
config is Soga/Lusoga - tagged here as xog, its real ISO 639-3 code, since
sog is actually Sogdian.)
Training: 64-unit MLP head, Adam @ lr=0.001, batch size 256,
60 epochs, best checkpoint picked by validation accuracy.
Language coverage
Evaluated on these 22 languages: ach, amh, fat, ful, hau, ibo, kik, lin, lug, luo, mas, nyn, orm, pcm, sid, sna, swa, tir, twi, wal, xog, yor.
Countries where the trained languages are spoken
Sub-Saharan Africa only, shaded by how many of the 22 trained languages are
spoken in each country (darker = more) - North Africa is intentionally left
uncolored since none of the training data comes from there.
Gender shows up in pitch, formants, and voice-quality acoustics that aren't
very language-specific, so this model is a reasonable starting point for
Sub-Saharan African languages beyond the ones above too - it just hasn't
been measured on them. It's specifically scoped to Sub-Saharan Africa because
that's what WaxalNLP (and therefore this model's training data) covers - none
of the languages above are North African, so no claim is made there. The
language tags on this model card cover the wider Sub-Saharan African
language directory (via afriso) for
discoverability, not a claim of measured accuracy on every one of them.
Evaluation
Validation accuracy: 0.9840
Test accuracy: 0.9358
Test macro F1: 0.9347
Speed (CPU only)
Embedding extraction: 392 ms for a 31s clip (2 CPU threads)
Gender head inference: 0.16 ms (negligible next to the embedding step)
Real-time factor: 78x - a 3-second clip classifies in ~38 ms of compute
No GPU required for inference; this is exactly what the model card's Quickstart runs.
Comparison to other gender-ID models
On a stratified sample of 2215 held-out WaxalNLP test clips across 22 languages, against public gender-ID models that never saw African-language speech in training (all out-of-domain for them by construction):
This is an accuracy-only comparison, deliberately - the baselines run as plain PyTorch/transformers models, while ours is ONNX-exported, so a latency comparison would mostly measure that export gap rather than anything about the approach itself. See the Speed section above for this model's own real-world inference latency.
audeering's model natively outputs a 3-way female/male/child softmax, folded here to binary by taking the argmax over just female/male; it's also the only baseline with a non-commercial license (CC-BY-NC-SA-4.0) - everything else here, including ours, is Apache-2.0/MIT/CC-BY-4.0.
1from huggingface_hub import hf_hub_download
2import sherpa_onnx, onnxruntime as ort, soundfile as sf, numpy as np, json
34# 1. sherpa-onnx's pretrained speaker-embedding extractor (unchanged, public)5embed_path = hf_hub_download("csukuangfj/speaker-embedding-models","3dspeaker_speech_campplus_sv_en_voxceleb_16k.onnx")6extractor = sherpa_onnx.SpeakerEmbeddingExtractor(7 sherpa_onnx.SpeakerEmbeddingExtractorConfig(model=embed_path, num_threads=2, provider="cpu")8)910# 2. this repo's tiny gender head + its config (holds the label map)11head_path = hf_hub_download("AfriSpeech/afrispeech-gender-id","onnx/model.onnx")12config = json.load(open(hf_hub_download("AfriSpeech/afrispeech-gender-id","config.json")))13label_map = config["label_map"]14session = ort.InferenceSession(head_path, providers=["CPUExecutionProvider"])1516# 3. run on a 16 kHz mono wav file17audio, sr = sf.read("sample.wav", dtype="float32")18stream = extractor.create_stream()19stream.accept_waveform(sample_rate=sr, waveform=audio)20stream.input_finished()21embedding = np.asarray(extractor.compute(stream), dtype=np.float32).reshape(1,-1)2223logits = session.run(["logits"],{"embedding": embedding})[0][0]24pred = label_map[str(int(logits.argmax()))]25print(pred)
See scripts/ for ready-to-run CLI versions of the above (single file and
whole-directory batch), built on the same gender_id.py helper.
Files
onnx/model.onnx - the trained MLP head (embedding -> logits)
config.json - architecture metadata plus label_map ({"0": "female", "1": "male"}), the output-index mapping needed to interpret the head's output
metrics.json - full validation/test metrics, including the per-language table above
scripts/gender_id.py - reusable GenderClassifier class
scripts/infer_file.py - classify one audio file
scripts/infer_batch.py - classify every .wav in a directory
scripts/requirements.txt - minimal deps for the scripts above
License
Model head weights: CC-BY-4.0, matching WaxalNLP's training data license. The
embedding extractor and its license are hosted separately at
csukuangfj/speaker-embedding-models.