arpa2fst 原理详解

来源:互联网 发布:姜峰手机 淘宝 编辑:程序博客网 时间:2024/06/18 12:43

在基于 wfst 的语音识别中,需要将 HCLG 四个不同层次的模型复合(composition)在一起构成一个超大的解码网络,其中的 G 即是语言模型的 WFST表示。但是我们常见的语言模型并不是以 WFST 形式存在的,而是基于 ngram 实现的,通常以 arpa 文件形式存在。所以复合的第一步就是将 arpa 文件转为 wfst,在 kaldi 中以 arpa2fst 脚本形式存在,我们在此详细分析 arpa2fst 的原理。

1. 语言模型打分

语言模型通常以arpa文件形式存在,下面是一个示例(引自参考1):

\data\
ngram1=9
ngram2=10
ngram3=2

\1-grams:
-0.7533277 </s>
-99 <s> -0.7907404
-0.9294189 今天 -1.059586
-1.230449 北京 -0.6268836
-0.7533277 天气 -0.5177391
-0.7533277 怎么 -0.5177391
-1.230449 明天 -0.5688916
-0.7533277 样 -0.5177391
-1.230449 的 -0.5688916

\2-grams:
-0.39794 <s> 今天
-0.3309932 <s> 明天
-0.3309932 今天 北京
-0.3309932 今天 天气
-0.1091445 北京 的
-0.1249387 天气 怎么 0
-0.1249387 怎么 样 0
-0.1091445 明天 天气
-0.1249387 样 </s>
-0.1091445 的 天气

\3-grams:
-0.1249387天气 怎么 样
-0.1249387怎么 样 </s>
\end\

上面的文件给出的是一个简单的trigram语言模型。arpa文件可以很容易地表示任意n-gram语言模型,不过在实际中n通常等于3、4或者5。arpa文件的每一行表示一个文法项,它通常包含三部分内容:probability word(s) [backoff probability]。probability表示该词或词组发生的概率,word(s)表示具体的词或者词组。backoff probablitiy是可选项,表示回退概率,当下层文法有以当前词或词组为前缀的文法项时回退概率存在,例如在上面的arpa文件中,二元文法项“天气 怎么”是三元文法项“天气 怎么 样”的前缀,所以它存在回退概率(在该简单arpa中为0,通常不为0)。有了上面的arpa文件,我们就可以计算给定一句话的语言模型得分。假设arpa的最高元是3元,则句子ABCDEF发生的概率为:
P(ABCDEF)=P(A)P(B|A)P(C|AB)P(D|BC)P(E|CD)(F|DE)(1)
其中,P(A)通过访问arpa中的1-grams项获得,P(B|A)通过访问2-grams项获得,其他的概率通过访问3-grams项获得。
P(A)的计算直接找对应A的文法项获得概率即可。如果2-grams中存在“A B”项,P(B|A)的概率也很容易获得,但是如果“A B”词组在2-grams中不存在,我们就需要利用回退概率计算P(B|A),计算公式为P(B|A)=α(A)P(B),其中α(A)就表示A的回退概率。类似地,可以获得三元词组的概率计算公式:

P(CAB)=P(C|AB)ABCα(AB)P(CB)BC(2)α(AB)α(B)P(C)

四元五元文法类似,只是计算公式更加复杂一些。只要句子不出现OOV问题,我们总是可以计算句子的语言模型概率。

2. 语言模型的树形表示

在非WFST解码器中,为了加快概率的查找速度,语言模型通常组织成一种树形结构。最常用的树形结构是trie树,文法直接通过前缀形式建立联系,在具体的实现过程中,每一层文法是一个大数组,数组的每一项包含概率、回退概率、当前词组的最后一个词以及以该文法项为前缀的下一层文法的入口位置和结束位置,示例图如下:
这里写图片描述
在上面结构中,每一层文法已经排序,这样可以通过二分查找来寻找下一层文法中start和end之间是否存在要查找的文法。这种结构非常精炼,对语言模型的压缩比较明显,适合于内存有限制的场景下,但是也存在一个比较明显的问题,就是需要动态查询语言模型得分,所以速度要慢于基于WFST的解码器。
图1中的有效信息都在节点内,我们还可以将有效信息放到边上,生成下面的树形结构:
这里写图片描述
在上面的语言模型中,每一层节点表示一层文法,有效信息都放在边上,边上包括文法项的概率、文法项最后一个词、以及可能的回退概率。我们可以在节点上保留到该节点的词历史信息,以表示该条路径到当前节点经过的词历史。这种表示结构已经开始有些类似于基于WFST的语言模型,但是每条边上的信息不符合WFSA标准。标准的WFSA转移包含一个输出字符和一个概率,上面边多了一个回退概率。下面我们将上面的语言模型转换成WFSA形式。

3. arpa2fst原理

理解arpa语言模型转换为wfst的一个难点就是“arpa有限的状态转换变成wfst之后为何可以识别无限长度的语音”。我们从公式(1)作为突破口,给定一个任意长的句子,我们都可以按照公式(1)来计算句子的语言模型得分。一般情况下,在完成部分句子语言模型得分的计算之后,后面来一个新词,我们会利用前面句子的部分历史加上新词计算新的语言模型得分。也即在完成一个文法项的概率计算之后,我们获取该文法的回退位置,将回退位置处的文法和新词组成更高元的文法项进行新的概率计算。所以公式(1)能计算无限长度句子概率的根本原因在于回退位置连接了老概率和新概率的计算,arpa2fst的核心也是利用回退位置。
图2的语言模型有点类似于WFST的语言模型,但是边不符合WFSA的标准,同时也不具备无限识别的可能。我们将图2边中的回退概率拿出来构造一个新的边—ε边,边上的概率为回退概率,词为空ε,指向的节点恰恰就是代表原始边回退位置的节点,这样每条边就符合WFSA标准,同时由于ε的原因它也可以处理无限长度的句子! (当然还有很多细节要处理~)考虑一个只包含三个词A B C的trigram,它包含两个二元文法AB和BC,先不考虑三元文法,我们画出它的部分WFSA来:
这里写图片描述
首先,我们构造一个词历史为ε的状态节点,从该节点开始我们构造所有一元文法项对应的边。每个一元文法项都从ε节点构造出一条边,边上包含一元文法对应的词和概率,并指向一个词历史是一元文法对应词的节点。然后处理回退概率,对每一个新构造的节点创建一个ε边指向最初的ε状态,概率为回退概率。最后处理二元文法,二元文法AB就是从状态A新建一条边,BC就是从状态B新建一条边,它们对应节点的词历史就改为AB和BC,回退概率的处理和一元文法类似,均指向自己的回退节点。
上述流程的伪代码如下:

Q ←{(ε)} //创建初始节点for each w ∈ unigram do    Q ← Q ∪ {(w)}    E ← E ∪ {((ε), w, - log P(w), (w))} //创建一条ε→w的边    E ← E ∪ {((w), ε, - log α(w), (ε))} //创建一条w→ε的边end fori=2while i <= n do    for each w[1,i] ∈ ith-gram do        Q ← Q ∪ {(w[1,i])}        E ← E ∪ {((w[1,i-1]), w[i], - log P(w[i]|w[1,i-1]), (w[1,i]))} //创建一条w[1,i-1]→w[1,i]的边        E ← E ∪ {((w[1,i]), ε, - log α(w[1,i]), (w[2,i]))} //创建一条w[1,i]→w[2,i]的边    end forend while

博客写到这里,我们基本介绍完了arpa2fst的原理,但是还有一些细节需要处理,下面我们进行简单描述。

4. 细节处理

4.1 WFST?WFSA?

在上面的介绍中这两个概念不做区分地使用,它们的区别就在于是否有输出符号。如果不考虑语言模型与发音词典的复合,我们只需要将arpa转换成wfsa即可,上面的描述也是转换成wfsa。但是在语音识别中,语言模型不是单独存在的,它需要和其他模型进行复合,构成实际的WFST解码网络,这时就需要它有输入和输出符号。针对语言模型来说,wfsa转wfst非常容易,只需要将每条边上的w复制一遍即可完成转换。下图是一开始语言模型用kaldi的转换工具生成的wfst(from 参考1):
图4 完整的wfst
需要注意的一点是针对ε边输入符号变成了消歧符号“#0”,这确保了G在删除epsilons之后是可确定的,输出符号为<eps>

4.2 概率转换

如果我们看apra文件中的概率就会发现概率均为负值,但是在图4中却都变成了正值。这是因为arpa文件中的概率都取了log10,但是在语音识别中通常采用自然对数,所以需要乘以ln 10做转换,同时对ln概率取相反数。

4.3 <s></s>处理

从图4可以看到,用kaldi生成的wfst中不包含<s></s>。kaldi会创建一个状态表示<s>,图4中是状态1,然后从该状态构造包含<s>的文法项。此外,我们也可以使wfst显式包含<s>,这样会产生很多包含<s>的边。
针对</s>的处理包含两种方式,kaldi采用的方式是不在wfst中出现</s>,而是将包含</s>的项转成结束状态,图4中的状态10和状态7即是由包含</s>的项生成的。另一种方式是把</s>当作普通字符,在wfst中显式出现,此时wfst中只有一个结束状态。

4.4 处理没有回退概率的文法项

并不是所有的文法项都有回退概率,最明显的就是最高元文法,它没有回退概率,低元文法中也可能存在文法项没有回退概率。没有回退概率的文法项我们就不能借助回退概率使其指向它的回退节点,这时我们无需创建节点w[1,i],而是直接将节点w[1,i-1]指向节点w[2,i],边上的概率和词就是该文法项的概率和词。
图4的wfst包含了本博客涉及的所有问题:每条边的输入和输出符号相同,概率为-ln(P)。初始状态为0,从该状态出去的边对应所有的一元文法,一元文法生成的新节点都有一个ε回边指向初始状态。状态2的词历史是今天,3是北京,4是天气等等。二元文法项都是从一元文法状态往外扩展新的边,2到6表示二元文法“今天 北京”,2到4表示二元文法“今天 天气”等等,没有回退概率的二元文法项直接指向回退节点。4到9表示二元文法“天气 怎么”,它有回退概率,所以它通过ε边指向回退位置。三元文法项类似。当遇到</s>时,就创建终止节点,并将对应文法项的概率付给终止节点。
至此,已经比较全面地介绍了arpa2fst的原理,大家可以通过仔细研究图4来进一步加深了解。

5. 参考

  1. Kaldi WFST 构图 学习
  2. Speech Recognition Algorithms Using Weighted Finite-State Transducers
  3. Investigations on Search Methods for Speech Recognition using Weighted Finite-State Transducers
原创粉丝点击