You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

语音识别系统计算词错误率(WER)时的文本归一化方法及工具咨询

嘿,这个问题抓得特别准——ASR计算WER的时候,文本归一化绝对是容易被忽略但影响极大的环节,就像你举的例子,datasetdata setarticle'sarticle is这种差异,完全不该被算成错误。我来给你唠唠具体该怎么做,还有好用的工具推荐:

一、核心归一化操作步骤

这些是针对英文ASR场景的通用规则,你可以根据自己的数据集调整优先级:

  • 统一大小写:把所有文本转成小写(或全大写),避免Withoutwithout被误判为不同词
  • 展开缩略词:把口语化的缩略形式还原成完整表达,比如article'sarticle isdon'tdo notcan'tcannot
  • 复合词统一格式:这是你例子里的关键!要么把复合词拆成单个词(比如datasetdata set),要么把拆分的词合并(data setdataset),保持标准文本和预测文本格式一致
  • 移除/标准化标点:去掉所有非字母数字的符号(比如逗号、撇号、引号),或者把特定标点转换成统一形式
  • 清理冗余空格:移除连续空格、开头结尾的空格,确保每个词之间只有一个空格
  • 数字标准化(可选):如果你的场景涉及数字,可以把阿拉伯数字转成英文单词(比如123one 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

火山引擎 最新活动