近日,WeNet 中增加了对语言模型(Language Model, LM)的支持。WeNet中选择基于 n-gram 的统计语言模型,结合WFST(Weighted Finite State Transducer)框架和传统语音识别解码技术,实现对定制语言模型的支持。在 AIShell-1,  AIShell-2 和 LibriSpeech 三个数据集上,WeNet 的 LM 方案均取得相对错误率3%~10%的下降。

下文将从设计思想、系统结构、工程实现和实验结果四个部分介绍 WeNet 中如何支持语言模型。


设计思想

为什么选择n-gram? 这可能是很多人会问的第一个问题。既然现在基于RNN、Transformer的LM如火如荼,WeNet 为什么要倒行逆施?原因很简单,为了生产力,基于 n-gram 的语言模型有成熟完备的训练工具,语料多少均可以训练,训练速度也很快,Hotfix也很直接容易,在实际产品中有着广泛而成熟的应用。

为什么又选择了WFST?可能是很多人会问的第二个问题。既然大家都这么辛苦费了九牛二虎之力拼命的摈弃传统语音识别特别是复杂的解码技术,WeNet 为什么要新牛吃老草走回头路?原因也很简单,为了生产力,WFST是传统语音识别中一个标准而强大的工具,基于该方案我们有成熟完善的 Bug Fix 的方案和产品方案,如基于 WFST 的 replace 功能,实现基于 class 的个性化语音识别功能,如联系人的识别。

所以,和 WeNet 的设计目标 "Production first and Production Ready" 一样,WeNet 中 LM支持也是以生产力为第一要务,因此借鉴了很多传统语音识别中积累的非常有生产力的工具和方案。并且,和传统语音识别不同的是:

  1. WeNet 的训练依然是纯端到端的。
  2. 如下文介绍,解码时,LM是可选的,可以根据自己的实际需求和应用场景选择是否使用LM。


系统结构

如之前的系列文章介绍,如下图所示,WeNet使用U2(Unified Two Pass)方案以实现流式解码。


其中:

  1. First Pass 使用 CTC 的解码结果作为中间结果,并通过 CTC prefix beam search 算法产生 N-best 。
  2. Second Pass 利用 Attention Decoder对 CTC 产生的多个候选结果 N-best 进行重打分。

WeNet中的LM支持方案如下图所示,N-best的生成方式有两种


  1. 无LM,即依靠CTC prefix beam search生成N-best。
  2. 有LM,则依靠CTC WFST search生成N-best,WFST search为依靠传统解码图的传统解码方式。

有LM时的CTC WFST search是本文的核心。主要包含解码图的构建和解码器两大部分。解码图的构建即将建模单元T、词典L、语言模型G各层次信息组合在一张解码图TLG中,其中:

  1. T为端到端训练时的建模单元,一般的,中文建模单元为汉字,英文为英文字母char或者BPE。
  2. L为词典,该词典很简单,直接将一个单词拆分成其建模单元序列即可,如单词“我们”拆分成“我 们”两个字,单词 APPLE 拆分成“A P P L E”五个字母。可以看到,没有传统词典中音素的概念,也就无需人为干预设计发音序列。
  3. G为语言模型,即将n-gram的语言模型转为WFST形式的表示。

解码器则和传统语音识别中解码器一致,使用标准的Viterbi beam search算法解码。


工程实现

WeNet 借鉴 Kaldi 中的解码器和相关工具以实现LM的支持。为了保持易用性和独立性,我们直接将 Kaldi 中解码相关的代码迁移到 https://github.com/mobvoi/wenet/tree/main/runtime/core/kaldi 目录。并按以下原则修改和组织:

  1. 为了最小化改动,迁移后的代码保持和原来相同的目录结构。
  2. 使用 GLOG 代替 Kaldi 中的 Log 系统。
  3. 修改代码格式以满足 WeNet 中代码风格的 lint 要求。

其中,最核心的代码位于 https://github.com/mobvoi/wenet/blob/main/runtime/core/decoder/ctc_wfst_beam_search.cc,其包装了 Kaldi 中的 LatticeFasterDecoder。并且实现了blank frame skipping的算法,以加速解码。

此外,WeNet 也将解码前构建解码图的相关工具,如arpa2fst、fstdeterminizestar、fsttablecompose、fstminimizeencoded等工具一并迁移过来,让LM的支持和使用作为内置独立工具,做到开箱即用。


实验结果

支持LM的解码方法我们使用 "LM + attention rescoring"表示,以下是该方法在各个数据集上的结果。

AIShell-1(Conformer)

decoding mode

CER

attention decoder

5.18

ctc greedy search

4.94

ctc prefix beam search

4.94

attention rescoring

4.61

LM + attention rescoring

4.36

AIShell-2(U2 Conformer)

decoding mode/chunk size

full

16

8

4

attention decoder

6.23

6.42

6.58

7.20

ctc greedy search

6.98

7.75

8.21

9.91

ctc prefix beam search

7.02

7.76

8.21

9.93

attention rescoring

6.08

6.46

6.72

7.79

LM + attention rescoring

5.87

6.37

6.47

6.61


LibriSpeech(Conformer small)


decoding mode

test clean

test other

ctc greedy search

3.51

9.57

ctc prefix beam search

3.51

9.56

attention decoder

3.05

8.36

attention rescoring

3.18

8.72

LM + attention rescoring

3.09

7.40


可以看到,WeNet 中的 LM 实现在各个数据集上、streaming 和非 streaming 的模型上、各种延迟的 streaming 模型上都取得了正向一致性的提高。这里仅列出了部分模型的测试结果,请在 WeNet 主页的 examples 中查看各个数据集中不同模型融合语言模型的结果。