语音识别系统计算词错误率(WER)时的文本归一化方法及工具咨询
嘿,这个问题抓得特别准——ASR计算WER的时候,文本归一化绝对是容易被忽略但影响极大的环节,就像你举的例子,dataset和data set、article's和article is这种差异,完全不该被算成错误。我来给你唠唠具体该怎么做,还有好用的工具推荐:
一、核心归一化操作步骤
这些是针对英文ASR场景的通用规则,你可以根据自己的数据集调整优先级:
- 统一大小写:把所有文本转成小写(或全大写),避免
Without和without被误判为不同词 - 展开缩略词:把口语化的缩略形式还原成完整表达,比如
article's→article is、don't→do not、can't→cannot - 复合词统一格式:这是你例子里的关键!要么把复合词拆成单个词(比如
dataset→data set),要么把拆分的词合并(data set→dataset),保持标准文本和预测文本格式一致 - 移除/标准化标点:去掉所有非字母数字的符号(比如逗号、撇号、引号),或者把特定标点转换成统一形式
- 清理冗余空格:移除连续空格、开头结尾的空格,确保每个词之间只有一个空格
- 数字标准化(可选):如果你的场景涉及数字,可以把阿拉伯数字转成英文单词(比如
123→one hundred twenty three),或者统一保留阿拉伯数字,避免格式差异导致错误
二、好用的工具与代码示例
1. 专用Python库
- jiwer:这是计算WER的黄金工具,不仅能直接算编辑距离,还支持自定义归一化函数,一步到位处理预处理和WER计算
- contractions:专门处理英文缩略词展开的小库,覆盖了绝大多数日常和书面语的缩略形式
- spaCy/NLTK:通用NLP库,可以用来辅助分词、处理文本规则,适合需要更复杂自定义逻辑的场景
2. 实战代码示例
先安装依赖:
pip install jiwer contractions
然后写一个自定义归一化函数,结合jiwer计算WER:
import re from contractions import contractions_dict from jiwer import wer def normalize_asr_text(text): # 1. 统一转小写 text = text.lower() # 2. 展开所有缩略词 for contraction, expansion in contractions_dict.items(): # 用正则匹配完整的缩略词,避免部分匹配 text = re.sub(rf'\b{re.escape(contraction)}\b', expansion, text) # 3. 处理复合词:把dataset拆成data set(可根据需求反向调整) text = re.sub(r'\bdataset\b', 'data set', text) # 4. 移除所有标点符号 text = re.sub(r'[^\w\s]', '', text) # 5. 清理冗余空格 text = re.sub(r'\s+', ' ', text).strip() return text # 测试你的例子 reference_text = "Without the dataset the article is useless" hypothesis_text = "Without the data set the article's useless" # 归一化处理 norm_ref = normalize_asr_text(reference_text) norm_hyp = normalize_asr_text(hypothesis_text) # 计算WER wer_score = wer(norm_ref, norm_hyp) print(f"归一化后的WER: {wer_score}") # 输出0,完全符合预期!
3. 进阶:用jiwer内置的归一化规则
jiwer本身也提供了一些预设的归一化工具,比如jiwer.transforms里的操作,你可以组合使用:
from jiwer import wer, transforms # 组合归一化规则 normalize = transforms.Compose([ transforms.ToLowerCase(), transforms.RemovePunctuation(), transforms.RemoveMultipleSpaces(), transforms.Strip(), transforms.ExpandCommonEnglishContractions(), # 自定义复合词替换 transforms.ReplaceRegex(r'\bdataset\b', 'data set') ]) # 直接用组合好的规则计算WER wer_score = wer( reference_text, hypothesis_text, reference_transform=normalize, hypothesis_transform=normalize ) print(f"归一化后的WER: {wer_score}") # 同样输出0
三、进阶小技巧
- 维护领域词表:如果你的ASR是特定领域(比如医疗、法律),可以自己维护一个复合词/术语映射表,确保专业词汇的格式统一
- 迭代优化规则:针对自己的数据集做错误分析,看看哪些假阳性错误是归一化没覆盖到的,比如特定的缩略词、复合词,不断补充规则
- 多语言适配:如果是其他语言,比如中文,需要额外处理多音字、同音字、分词差异等问题,可以结合jieba等分词工具做归一化
内容的提问来源于stack exchange,提问作者Franck Dernoncourt




