CLD: language detection heads for ASR models (Whisper / MMS)
Project description
CLDConvex Low-resource Accent-Robust Language Detection in Speech Recognition |
|
This repository provides the official implementation of CLD, a lightweight language-detection module for multilingual ASR. This codebase contains our pip-installable Python package (jaxcld/) including our training/benchmark scripts implemented in JAX and optimized via ADMM for high performance in low-resource settings. Simply, the package attaches a small language detection head (Convex NN / small NN / linear SVM) to ASR encoder representations, and use it to select the language token (Whisper) or adapter (MMS) before decoding.
Highlights
- High Accuracy: Excels in binary and multiclass language detection.
- Low-Resource Robustness: Effective with limited data.
- Efficient: 13x training speedup from traditional NNs due to ADMM optimization and JAX.
Requirements
The package is published on PyPI as jaxcld. JAX (CPU) is included by default. For GPU support, install the matching extra:
# CPU
pip install jaxcld
# GPU — CUDA 12 (most modern systems)
pip install "jaxcld[cuda12]"
# GPU — CUDA 11
pip install "jaxcld[cuda11]"
If you've cloned this repo, you can instead install from source:
- Package-only install (inference usage):
pip install -e . # CPU
pip install -e ".[cuda12]" # GPU — CUDA 12
- Full training/benchmark environment (recommended if you run the scripts in this repo):
pip install -e ".[train]" # CPU
pip install -e ".[train,cuda12]" # GPU — CUDA 12
If you prefer installing from the pinned dependency list instead:
pip install -r requirements.txt
Using the package
Minimal inference example (Whisper)
import numpy as np
from jaxcld import ASRModel, CVXNNLangDetectHead, NNLangDetectHead, SVMLangDetectHead
# 1) Load the base ASR model
languages = ["en", "hi", "id", "ms", "zh"]
asr = ASRModel.from_pretrained("openai/whisper-small", config={"languages": languages})
# 2) Load a language detection head artifact (choose ONE)
# head = CVXNNLangDetectHead.load("path/to/whisper-small_trained_cvx_mlp.pkl", asr)
# head = NNLangDetectHead.load("path/to/openai_whisper-small_nn_head.pkl", asr)
# head = SVMLangDetectHead.load("path/to/openai_whisper-small_linear_svm.pkl", asr)
# 3) Attach head and run inference
asr.set_lang_detect_head(head)
audio_16k_mono: np.ndarray = ... # shape (T,), sampling rate 16kHz
pred_langs, pred_texts = asr.predict(audio_16k_mono)
print(pred_langs[0], pred_texts[0])
Pre-trained models
Trained convex heads are published on the Hugging Face Hub:
| Model | Backbone | Languages | Det. Acc | WER ↓ | CER ↓ | HF Hub |
|---|---|---|---|---|---|---|
cld-whisper-small-5lang |
whisper-small | en/hi/id/ms/zh | 0.98 | 48.23 | 27.47 | 🤗 |
cld-whisper-large-v3-5lang |
whisper-large-v3 | en/hi/id/ms/zh | 0.98 | 31.11 | 19.81 | 🤗 |
cld-mms-1b-5lang |
mms-1b-all | en/hi/id/ms/zh | 0.96 | 48.10 | 23.47 | 🤗 |
cld-whisper-small-enzh (100–10000 samples/class) |
whisper-small | en/zh | 0.99–1.00 | — | — | 🤗 |
Loading from the Hub
import numpy as np
from huggingface_hub import hf_hub_download
from jaxcld import ASRModel, CVXNNLangDetectHead
languages = ["en", "hi", "id", "ms", "zh"]
# 1) Load the frozen base ASR model
asr = ASRModel.from_pretrained("openai/whisper-small", config={"languages": languages})
# 2) Download the convex head from the Hub and load it
head_path = hf_hub_download("williamhtan/cld-whisper-small-5lang", "model.pkl")
head = CVXNNLangDetectHead.load(head_path, asr)
# 3) Attach the head
asr.set_lang_detect_head(head)
# 4) Grab one clip from the dataset's test split
from datasets import load_dataset
sample = next(iter(load_dataset("williamhtan/cld-multi-dataset", split="test", streaming=True)))
audio_16k_mono = sample["audio"]["array"] # (T,) float waveform, 16 kHz mono
# 5) Predict
pred_langs, pred_texts = asr.predict(audio_16k_mono)
print("true:", sample["lang"], "| pred:", pred_langs[0], "| text:", pred_texts[0])
For the low-resource binary model, specify the samples-per-class subfolder:
head_path = hf_hub_download("williamhtan/cld-whisper-small-enzh", "1000/model.pkl")
Citation
If you use this code in your work, please cite the paper:
@inproceedings{feng2026cld,
title = {Convex Low-resource Accent-Robust Language Detection in Speech Recognition},
author = {Feng, Miria and Tan, William and Pilanci, Mert},
booktitle = {Proceedings of the 43rd International Conference on Machine Learning},
year = {2026},
series = {Proceedings of Machine Learning Research},
publisher = {PMLR},
url = {https://icml.cc/virtual/2026/poster/64615}
}
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jaxcld-0.2.4.tar.gz.
File metadata
- Download URL: jaxcld-0.2.4.tar.gz
- Upload date:
- Size: 64.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e691e456e28c52e4b67feb32427a2580c1e3cf906965fa25f2b6fd10322f3446
|
|
| MD5 |
38c07af1adb46cb8705b659ee61c6380
|
|
| BLAKE2b-256 |
b93f5889c81650ee3c9569ff679cd7b8d7fb8766629251304f98c3c91a4042e6
|
File details
Details for the file jaxcld-0.2.4-py3-none-any.whl.
File metadata
- Download URL: jaxcld-0.2.4-py3-none-any.whl
- Upload date:
- Size: 64.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2871b5bcd5aa4b3dce4183a24b979979e1e64b01fb5d234647cbda5cb47e9c61
|
|
| MD5 |
7a3829fb6bbfa86a5250a4143667837f
|
|
| BLAKE2b-256 |
e912d575a203b545b9d0339f5a74095bd195f0c08daa7ac43e95b8cad1940206
|