文章目录
- 1 为什么需要Language Model
- 2 N-gram
- 3 Continuous LM
- 3 NN-based LM
- 4 RNN-based LM
- 5 合并LAS和LM
- 5.1 shallow fusion
- 5.2 deep fusion
- 5.3 cold fusion
本文为李弘毅老师【Speech Recognition - Language Modeling】的课程笔记,课程视频youtube地址,点这里👈(需翻墙)。
下文中用到的图片均来自于李宏毅老师的PPT,若有侵权,必定删除。
文章索引:
上篇 - 1-6 RNN-T Training
下篇 - 2-1 Feature Disentangle
总目录
1 为什么需要Language Model
LM是用来估计一串token出现的概率的,简单点说,就是给模型一个单词,模型帮你看看这个单词拼写正确的概率是多大,这样子。也就是,我们平时所说的P(Y)P(Y)P(Y)。
在HMM当中,使用P(Y)P(Y)P(Y)是非常自然的,因为HMM求解的是
HMM:Y∗=argmax⏟YP(X∣Y)P(Y)HMM:\ Y^* = \underbrace{argmax}_Y P(X|Y)P(Y) HMM: Y∗=YargmaxP(X∣Y)P(Y)
但是在类似LAS这样的深度学习模型当中,我们是直接求解P(Y∣X)P(Y|X)P(Y∣X)的。这个时候,还要乘上一个P(Y)P(Y)P(Y)其实有点奇怪,甚至难以解释。但事实是,这样的做法,可以提升模型的performance。
LAS:Y∗=argmax⏟YP(Y∣X)P(Y)LAS:\ Y^* = \underbrace{argmax}_YP(Y|X)P(Y) LAS: Y∗=YargmaxP(Y∣X)P(Y)
如果非要解释一波的话,因为P(Y∣X)P(Y|X)P(Y∣X)的训练是需要大量的成对数据的(语音 - 文字),我们并没有那么多的数据。而P(Y)P(Y)P(Y)这个模型是单独拿出来train好的,它的训练只需要文字就可以了,比如我们可以用超神的BERT。
2 N-gram
一种比较传统的语言模型叫做N-gram。N-gram会去统计一大堆语料当中某一组词出现的概率。但是,我们人类所使用的词汇实在是太复杂多样了,我们说的一串话,可能都从来没有出现在用来训练的语料库当中。那怎么办呢?
我们会在假设词和词之间相互独立的基础上,把P(y1,y2,y3,...,yn)P(y_1,y_2,y_3,...,y_n)P(y1,y2,y3,...,yn)这个概率拆解开来,比如2-gram的时候,就变成了
P(y1,y2,y3,...,yn)=P(y1∣BOS)P(y2∣y1)⋯P(yn∣yn−1)P(y_1,y_2,y_3,...,y_n) = P(y_1|BOS)P(y_2|y_1) \cdots P(y_n|y_{n-1}) P(y1,y2,y3,...,yn)=P(y1∣BOS)P(y2∣y1)⋯P(yn∣yn−1)
用一个实际一点的例子来说就是
P("wreckanicebeach")=P(wreck∣BOS)P(a∣wreck)P(nice∣a)P(beach∣nice)P("wreck\ a\ nice\ beach") = P(wreck|BOS)P(a|wreck)P(nice|a)P(beach|nice) P("wreck a nice beach")=P(wreck∣BOS)P(a∣wreck)P(nice∣a)P(beach∣nice)
那么,我们在训练的时候,就只需要去统计相邻词出现的概率即可,比如
P(beach∣nice)=C(nicebeach)C(nice)P(beach|nice) = \frac{C(nice\ beach)}{C(nice)} P(beach∣nice)=C(nice)C(nice beach)
CCC表示训练数据中的频数。
类似的3-gram就是P(yn∣yn−1,yn−2)P(y_n|y_{n-1},y_{n-2})P(yn∣yn−1,yn−2),4-gram就是P(yn∣yn−1,yn−2,yn−3)P(y_n|y_{n-1},y_{n-2},y_{n-3})P(yn∣yn−1,yn−2,yn−3)。
但即使是这样,我们的训练数据仍旧是远远不够的,有许多的组合从来没有出现在训练数据当中过。但这些没有出现过的,并不代表它们的实际概率为0,只是在训练数据中的概率为0而已。为了解决这个问题,我们会用一个很小的概率去代替0,比如0.0001。这个操作叫做language model smooting。这个smooting的方法也有非常多的变形,这里不展开去讲了。
3 Continuous LM
在进入深度学习之前,有人还想出了另一种方法来解决这个训练集不够的问题,那就是借用推荐算法MF(Matrix Factorization)。
什么是MF呢?比如我们现在有A、B、C、D、E五个用户,分别在某个动漫网站上对四个动漫人物打了分。B对第2个人物还没有打分,但他对第一个人物打分了。那么,其实我们可以根据其他用户的打分行为来推断B会对第2个人物打几分。我们发现喜欢第1个人物的用户,通常也会喜欢第2个人物,故我们觉得B可能对第2个人物会打5分。
当然,这个只是拍拍脑袋想象的,MF就可以用数学的方法,帮我们把下面这张表格的空格给填满。
在把MF应用到LM的的时候,我们的横轴和纵轴都会变成vocabulary中的所有单词,而中间的表格就表示横轴的单词后面接纵轴的单词在训练集中的频数。比如下图中的n11=2n_{11}=2n11=2就表示"dog"后面接"ran"出现了2次。
然后每一个横轴的单词都用一个特征向量hih^ihi来表示,每一个纵轴的单词都用一个不同的特征向量vjv^jvj来表示。我们会试图用vj⋅hiv^j \cdot h^ivj⋅hi来逼近njin_{ji}nji。vjv^jvj和hih^ihi都是可以学习的。
逼近的方法,就是通过最小化下面这个loss来计算出所有的vjv^jvj和hih^ihi。
Minimize:L=∑i,j(vj⋅hi−nj,i)2Minimize:\ L = \sum_{i,j}(v^j \cdot h^i - n_{j,i})^2 Minimize: L=i,j∑(vj⋅hi−nj,i)2
通过这样学习得到的vjv^jvj和hih^ihi就表示了每个单词的一些特征,当我们要去计算在训练集里没有出现过的nj,in_{j,i}nj,i时,就可以直接用vj⋅hiv^j \cdot h^ivj⋅hi的方法。这种通过学习的方法,比直接统计要靠谱很多。
3 NN-based LM
这种矩阵相乘的形式,当然时可以转换成神经网络的形式的,稍稍变形就可以变成几个全连接搞定的神经网络,如下图所示。输入是一个one-hot encoding过的向量,其中的全连接权重就是hih^ihi和vjv^jvj,目标就是我们的nj,in_{j,i}nj,i。
那这样的模型如何训练呢?训练方法其实和n-gram 差不多,就是输入几个单词,让模型去预测下一个单词是什么。
有了这样的模型,就可以去计算P(Y)了。下图是一个示意图。
4 RNN-based LM
NN-based LM用的都是全连接,所以当我们想要看非常长的句子时,也就是n-gram中的n非常大时,网络就会变得异常大,没有钱或者硬件是跑不起来的。为了减少资源的消耗,我们可以引入RNN,用RNN的最后一个hidden state去和vjv^jvj相乘。
这里用到的RNN可以非常复杂,但是一般只需要用LSTM就可以了。
5 合并LAS和LM
我们知道怎么train这个LM了之后,怎么把它结合到LAS里呢?方法也有很多种,下面来一一介绍。
5.1 shallow fusion
shallow fusion就是说,我们已经有了train好的LM和train好的LAS,然后在做decoding的时候,每个time step它们都会输出一个维度和词表大小一样的概率向量,把这两个向量加权求和作为最终的概率向量。然后不断这样循环下去就可以了。
5.2 deep fusion
deep fusion和shallow fusion的不同之处在于,它会把LM和LAS的hidden state塞进一个神经网络里去进行融合。这个额外的神经网络是需要train出来的,也就是说我们有一个train好的LM和train好的LAS之后,还要把这两者接进一个network中,再去train一发。
这样做带来的弊端就是,我们没法随意更换LM模型,一旦更换了就需要重新train一发。如果我们要对每个用户做一个针对性的LM,那这个方法就行不通了。
不过也有办法可以换了LM而不重新train这个network,那就是用LM的输出概率作为network的输入。
5.3 cold fusion
最后再来将一个cold fusion,cold fusion其实结构上和deep fushion长的一模一样,只不过,cold fusion当中,我们的LAS是没有train好的,需要接上之后去end-to-end的训练的。这样的做法,可以让LAS收敛得更快。