在语音识别的实际应用中,对于常用的词汇识别效果比较好,但是对于一些特有的人名、歌名、地名或者某个领域的专有词汇,例如人名宋星辰、歌名国际歌、地名丽泽商务区以及语音识别专业词汇解码器,可能存在识别准确率不高的情况。对于这些专有词汇,通过在 WeNet 中使用热词增强方案,添加热词可以显著提升识别的准确率。
近期,WeNet 的更新支持了两种解码器上热词增强,包括 CTC Prefix Beam Search 和 WFST Beam Search。
热词增强
热词增强在论文中也叫 Context Biasing 或者 Contextual Biasing,相当于是把一些先验的知识加入到了语音识别系统中。WeNet 在解码过程中维护一个 Context Graph 中的状态。通过子图中的状态计算热词的得分,然后通过浅融合 (Shallow Fusion) 的形式在束搜索的过程中进行加分。

Context Graph
指定热词中每个字的得分为 3,则 Context Graph 的构图如下图所示: 
在解码过程中,当匹配到对应前缀时,就会得到相应的分数奖励。为了防止前缀相同,但不是完全匹配的现象。我们加了一条回退弧,通过这条弧移除之前奖励的分数。例如“欧阳修”不能完全匹配任意热词,回退弧则移除“欧阳”两个字得到的 6 分奖励。为了易于确定匹配到的热词的起始点,对于每个前缀,WeNet 只记录一个状态。即在同一时刻,只能进行一个热词的匹配,只有该热词匹配成功或者失败后才能开始匹配其他热词。使用该策略,“欧阳唯品会”则无法成功匹配“唯品会”。因为“欧阳唯品”的“品”字导致“欧阳唯一”匹配失败,回到 0 状态,而“会”字无法匹配任意热词(此处还可以做一些优化的工作,例如回到 0 状态后,“品”字继续匹配等等)。WeNet不考虑这种情况。
CTC Prefix Beam Search
在前缀束搜索的过程中,每个前缀需要记录热词匹配的信息。加上当前时刻的输出后,若前缀发生变化则直接调用上述 GetNextState 函数更新热词匹配的状态和分数。如果是热词的开始或者结束,还需要记录开始的位置和结束的位置,用于在识别结果中插入开始标签和结束标签,如:“前往吴迪在幸福里的家”。
CTC WFST Beam Search
由于 WFST 束搜索采用的是 Kaldi 中的 Lattice Faster Online Decoder,所以为了支持热词增强,我们需要对lattice-faster-decoder.cc做一些修改。
WFST 束搜索根据 CTC 的输出在 TLG 上进行解码,我们一开始的想法是在 TLG 的输入标签 (ilabel) 上做热词增强,也就是经过语言模型之前做热词增强。这样的话 Context Graph 的输入标签和输出标签都是字级别,而且我们只需要修改ProcessEmitting函数。但是由于 TLG 的输入是 CTC 的输出,如果我们要维护热词的匹配状态,那么 Context Graph 还需要和 T (Token Graph) 进行 compose 操作。我们最终决定在 TLG 的输出标签 (olabel) 上做热词增强,也就是在经过语言模型之后做热词增强。同时修改ProcessEmitting和ProcessNonemitting函数,加入相同的热词增强逻辑。Context Graph 构图时,只需要根据语言模型的字典对所有热词进行分词即可:

剪枝
Context Graph 的回退弧会一次性将前面累计的奖励分数回退到一条弧 (ForwardLink) 上,导致该弧的 cost 特别大而被剪枝,它不该一条弧承受这么多。因此在剪枝之前,我们需要移除回退弧产生的 cost,此处感谢爱奇艺@陈海涛同学提出的解决方案。模型使用的是 aishell2 的20210602_unified_transformer_server.zip。每一列对应不同的 context_score。由于 with-context 中包含较多的数字,而解码结果没有做 text-normalization,故 WER 较高。
从实验结果可以看出,随着 context_score 的增加,with-context 数据集上的 WER 越低。当 context_score 超过 5 时,会导致通用数据集上的 WER 升高。WFST Beam Search 有了语言模型的加持, context_score 可以设置大一些。限制
WeNet 提供了一种端到端热词定制化的方案,但是该方案在工程化的时候没有对下述问题做详细的探索。- context_score 设置为多少比较合适?对于不同模型和不同数据集,如何能快速确定该值?
- 某些情况下,热词奖励(但不是正确识别结果)得分过高,导致正确路径被裁剪掉,又该如何避免?
等等。对于上述限制,希望感兴趣的同学可以多多提供方案,多多到 github 上提交 pull request。