WER vs CER : bien mesurer l'ASR
Deux métriques d'évaluation pour la reconnaissance vocale — comment les choisir, les calculer et éviter les pièges.
Définitions
WER — Word Error Rate
$$\text{WER} = \frac{S + D + I}{N}$$
- S : substitutions (mot remplacé)
- D : suppressions (mot manquant)
- I : insertions (mot en trop)
- N : nombre de mots dans la référence
Interprétation : proportion de mots incorrects. 0 % = parfait, 100 % = inutilisable (en pratique).
CER — Character Error Rate
Même formule, mais à l’échelle du caractère au lieu du mot.
Quand utiliser quoi ?
| Situation | Métrique recommandée | Raison |
|---|---|---|
| Langues agglutinantes (Wolof, Swahili, turc…) | CER | Un mot = morphème + affixes ; WER pénalise trop les formes conjuguées |
| Langues à espaces ambigus (Mandarin, japonais) | CER | Pas de délimiteur de mot naturel |
| Anglais, français, espagnol | WER | Standard du domaine, facilite les comparaisons |
| Noms propres, codes, termes techniques | Les deux | WER sur les entités nommées séparément |
| Transcription médicale / légale | WER strict | L’insertion d’un seul mot peut changer le sens |
Calcul avec jiwer (Python)
from jiwer import wer, cer, process_words, process_characters
ref = "le modèle reconnaît la parole"
hyp = "le modèle reconnaît la parole correctement"
print(f"WER : {wer(ref, hyp):.1%}") # 16.7%
print(f"CER : {cer(ref, hyp):.1%}") # 9.5%
# Détail des erreurs
out = process_words(ref, hyp)
print(out.insertions, out.deletions, out.substitutions)
Normalisation : le vrai enjeu
Le WER brut est sensible à la casse, la ponctuation, les chiffres.
Normaliser avant de comparer :
import re
def normalize(text: str) -> str:
text = text.lower()
text = re.sub(r"[^\w\s]", "", text) # supprime ponctuation
text = re.sub(r"\d+", lambda m: num2words(m.group(), lang="fr"), text) # chiffres → lettres
text = " ".join(text.split()) # espaces multiples
return text
Toujours appliquer la même normalisation à la référence et à l’hypothèse.
Pièges fréquents
1. Comparer des WER non normalisés
Un modèle qui prédit "vingt-et-un" contre une référence "21" obtient WER = 100 % sans normalisation des chiffres.
2. Ignorer les langues tonales
En Yoruba ou Éwé, un ton mal transcrit change le sens. Le WER compte l’erreur une seule fois même si le sens est radicalement différent. Combiner avec une évaluation sémantique humaine.
3. Corpus de test non représentatif
Un WER de 8 % sur LibriSpeech ne prédit pas les performances sur des enregistrements téléphoniques bruités en Haoussa. Évaluer sur le domaine cible.
4. Longueur des segments
Le WER augmente mécaniquement sur les courts segments (1-2 mots) car une seule erreur représente 50-100 % du total. Filtrer ou reporter séparément.
Calcul avec HuggingFace evaluate
import evaluate
wer_metric = evaluate.load("wer")
cer_metric = evaluate.load("cer")
references = ["le modèle reconnaît la parole"]
predictions = ["le modèle reconnais la parole"]
print(wer_metric.compute(references=references, predictions=predictions))
print(cer_metric.compute(references=references, predictions=predictions))
Métriques complémentaires
| Métrique | Usage |
|---|---|
| MER (Match Error Rate) | Prend en compte les erreurs dans le contexte global |
| WIL (Word Information Lost) | Pondère les mots par leur fréquence d’information |
| BLEU | Pour les tâches de traduction post-ASR |
| DISFLUENCY rate | Pour les transcriptions conversationnelles |