Speech Valley是原先的github项目Automatic Speech Recognition的正式库名称,之所以取名为Speech Valley,是希望这个项目不仅可以包括语音识别,也能处理Speaker Verification、Text-to-Speech等问题,近期公众号将围绕语言模型、中文语音识别、说话人身份识别、语音合成等诸多前沿领域撰写系列文章与代码实践。
构建好一个强大的语言模型以后,可以应用到非常多的领域,最基本也最常用的毫无疑问就是输入法了,中文中最常用输入法是拼音输入法,它其实是做了一个映射,将汉语拼音通过英文字母来表示,然后用户通过键盘输入英文字母再经过输入法解码后得到汉字或者汉字序列,这样可以大大提高我们打字的效率,拼音输入法诞生的历史已经很久了,今天我们着重讲讲拼音输入法背后的统计语言模型以及借助神经网络可以改进的地方。
不考虑声调的话,汉语一共有大约410个音节,而汉语常用字有大约6000个,所以在音节与庞大的汉字之间作准确的映射是相当有难度的。在介绍将神经语言模型应用到拼音输入法之前,我们回顾一下传统拼音输入法中的语言模型。由于早期设备上的内存和运行速度的限制(当然现在也不见得所有手机都可以高效地运行神经网络算法),大多拼音输入法都是基于统计模型来将拼音序列解码成汉字序列的,最广泛使用的语言模型是n-gram,因为它具有公式简洁、运行较快的优点。
一般用户输入的是一个拼音序列,例如
woshiyigedaxuesheng
其对应的正确的汉字序列就是
我是一个大学生
如果记拼音序列为P,汉字序列为H,Pr为概率,那么拼音输入法要做的事情就是计算满足使得Pr(H|P)达到最大值的H,直接计算Pr(H|P)有点困难,通过贝叶斯公式可以交换事件之间的关系,即通过求Pr(P|H)来求Pr(H|P),根据贝叶斯公式,我们可以将其写成如下形式
H* = argmax Pr(H|P) = argmax [Pr(P|H)*Pr(H)/Pr(P)]
问题就转化成了求Pr(P|H)、Pr(H)、Pr(P)这三个量,Pr(P)在这里可以认为是一个常量,而Pr(H)可以通过n-gram语言模型计算得到,最后一个Pr(P|H)代表的是给定一个汉字,它的拼音被写成P的概率是多大,通常情况下,H不仅仅是一个汉字,而是一个汉字序列,即w1, w2, ..., wn,那么,我们可以认为Pr(P|H)≈Pr(p1|w1)*Pr(p2|w2)*...*Pr(pn|wn),其中pn为第n个字对应的拼音,只要我们抓取到一些干净的语料,训练好一个Perplexity值较低的语言模型,以上的问题就可以迎刃而解。
然而,上面这种计算方法可以实现的前提是用户输入的拼音序列是没有错误的,只有这样才可以准确计算Pr(pn|wn),万一用户输错了怎么办呢?例如对于“你洗脸了吗”这个句子的拼音,有的用户由于地方方言的缘故,加上中国人平时输入拼音的次数不像美国人输入英文那么普遍,他输入的拼音序列可能是这样的
nixinianlema
除此之外,可能有的地方的方言前后鼻音不分,'ng'与'n'混用,还有的是'zh'与'z'混用,'sh'与's'混用,诸如此类的错误有很多很多,这个时候如果还是按照上面的Pr(pi|wi)来计算,就会出现较大的识别误差。
我们可以采用基于大数据的方法来训练概率分布Pr(pi|wi),理论上我们可以训练所有可能的Pr(pi|wi),但是这种做法会带来参数多的缺点,一个更加优化的方案就是把所有具有相同发音的字母对应到同一个音节上,这样实际上就是相当于训练Pr(p|syllable),然后把每个字母映射到对应的音节上面。
上面提到的这种方法是基于统计来做的拼音输入法,统计方法的缺陷在于无法构建字与字内在的含义或者关联性,因而泛化能力非常弱,如果想构建非常全面的统计语言模型,则又面临着curse of dimensionality的问题,即如果你想构建一个6000个字的trigram模型,理论上需要大约6000^3个参数,即2160亿个参数,这是十分困难的,而基于非线性的方法则可以使用较少的参数来捕捉更深层次的特征,即使面对一个从未见过的句子序列,它也可以根据近义词之间的关联从而给出合理的概率,例如,对于句子“一只猫在厨房里”,基于神经网络的语言模型也可以认为句子“一只狗在厨房里”是可以存在的,因为,“狗”和“猫”在字义上是相近的。
提到基于神经网络的语言模型,我们不得不说一下这个语言模型最初是由Bengio在2000年发表的论文《A Neural Probabilistic Language Model》中提出的,即通过构建词的特征向量来对句子的上下文建模,并且当时的实验结果表明基于神经网络的语言模型相比于传统的trigram语言模型提高了20%-35%左右。既然如此,那么如何将这个神经语言模型(以下简称NNLM)应用到输入法中呢?然而,由于NNLM具有较高的计算复杂度,因此要想把其集成到输入法引擎中且可以即时相应用户的拼音输入是相当困难的,难以想象用户输完一段拼音序列以后要等五秒钟才能看到汉字序列,这种人机交互的体验是不现实的,而一种有效的解决方案就是使用NNLM来增强n-gram model,即使用NNLM来计算n-gram中的概率。
在传统的n-gram语言模型中,存在由于数据稀疏性而带来的某些词组出现的概率为0的问题,因此一般都会采取一些平滑的方法来使得不会出现概率为0的情况,最常见的是基于Kneser-Ney平滑算法。而在非线性神经网络模型中,我们可以将输入单词的one-hot vector通过特征矩阵映射到低维空间,然后再进过一个带有非线性激活函数的隐含层得到特征表达,最终通过softmax分类层得到候选单词的概率分布,这种做法不会出现零概率的问题,但是简单地将n-gram模型替换成NNLM会导致计算量比较大,为了减少计算量,可以对n-gram模型进行重构,具体过程如下:
分别训练n-gram模型和NNLM模型;
基于NNLM计算所有可能的n-gram的概率;
将n-gram模型中的所有n-gram的概率替换成由NNLM计算的概率;
对所有n-gram的概率坐归一化,并保存;
在使用时,仍然是以n-gram模型的形式来计算;
经过上面5个步骤,就完成了NNLM增强的n-gram语言模型,并可以高效地应用于拼音输入法中。
本文中只是阐述了基于多层分类器的神经网络语言模型,其实既然是预先计算好n-gram的概率再运用到输入法,我们完全可以使用更加复杂的RNN或CNN来代替MLP从而得到更加精准的语言模型,后面将分享基于TensorFlow的拼音输入法的实践效果。
你可能会感兴趣的文章有:
动态层归一化(Dynamic Layer Normalization)
详述DeepMind wavenet原理及其TensorFlow实现
Layer Normalization原理及其TensorFlow实现
Batch Normalization原理及其TensorFlow实现
Maxout Network原理及其TensorFlow实现
Network-in-Network原理及其TensorFlow实现
如何基于TensorFlow实现ResNet和HighwayNet
TensorFlow seq2seq中的Attention机制(续)
深度学习每日摘要|坚持技术,追求原创