从今天开始,重新开始看Micheal Collins的NLP公开课。预计7天时间。
1. 概率模型- Markov Process
毕竟是机器学习嘛,所以第一步,先要把实际问题转化成数学模型。在NLP中,一般使用的都是概率模型,即把语言模型变成概率论范畴。
比如说,现在有一段语音,说的很含糊,没有听清楚,好像是“like your”,又好像是“lie cured”。那么到底是哪一种呢?我们就看在现有的语料库中,到底是“like your”出现的概率大,还是“lie cured”的概率大。
于是就把语音识别问题转变成了一个概率问题:输入一串字符,输出这串字符组合在一起的概率,如果概率大,就是正确的句子。下面构建这个模型:
假设有一个句子S={x1,x2,x3,...,xn},则这个句子出现的概率理所当然如下:
根据贝叶斯公式(条件概率公式),可知:
为方便起见,补充x−1=x0=∗ (星号字符,无实际意义),则:
对于,其中的P(xi|x1,...,xi−1)这一项,根据大数定律可以约等于:
然而大数定律满足的条件是,#(x1,...,xi−1,xi)和#(x1,...,xi−1)要足够大,但是实际情况下,这样组合的数据并不会特别多,甚至会有很多等于0,所以无法这样去约等于。
正确的计算方式是用“Markov process”来假设:
第一种假设:
Unigram:
P(xi|x1,...,xi−1)≈P(xi)则我们的概率模型变成:
P(S)=∏i=1nP(xi|x1,...,xi−1)≈∏i=1nP(xi)
第二种假设:
Bigram (First-order Markov):
P(xi|x1,...,xi−1)≈P(xi|xi−1)则我们的概率模型变成:
P(S)=∏i=1nP(xi|x1,...,xi−1)≈∏i=1nP(xi|xi−1)
第三种假设:
Trigram (Second-order Markov):
P(xi|x1,...,xi−1)≈P(xi|xi−1,xi−2)则我们的概率模型变成:
P(S)=∏i=1nP(xi|x1,...,xi−1)≈∏i=1nP(xi|xi−1,xi−2)
至此,我们模型框架已经搭建完毕,接下来只要把P(xi)或者P(xi|xi−1)或者P(xi|xi−1,xi−2)计算出来即可,这些概率就是概率模型的参数,需要从训练集中学习出来。
2. 模型参数计算
假设训练集中共有V个单词,根据大数定律有:
Unigram -
P(xi)=#(xi)V Bigram - P(xi|xi−1)=#(xi−1,xi)#(xi−1)
Trigram - P(xi|xi−1,xi−2)=#(xi−2,xi−1,xi)#(xi−1,xi)
这里大数定律基本可以成立,因为这样的小型组合还是不难找到的。
如此,就可以把模型中的每一个参数计算出来了。
3. 参数计算的问题
3.1 Unknown words pair
虽然可以找到比较大数据集,但是在训练集中依旧可能出现#(xi−2,xi−1,xi)=0,或者#(xi−1,xi)=0的情况。但是训练集中不出现,并不代表这种情况不可能发生,所以需要模型具有泛化和推演能力。
3.1.1 Linear Interpolation
第一种解决方法称为 Linear Interpolation。
先再看一下三种参数计算方式:
Unigram - q(xi)=#(xi)V
Bigram - q(xi|xi−1)=#(xi−1,xi)#(xi−1)
Trigram - q(xi|xi−1,xi−2)=#(xi−2,xi−1,xi)#(xi−1,xi)
单纯使用式子1是最有可能造成underfitting的,因为没有一点儿上下文关联信息在里面;使用式子3是最有可能造成overfitting的,因为对上下文的关联性太强,对于训练集中的context记忆太深。
因此,解决Unknown words pair问题,提升模型泛化能力的其中一个方法,就是结合上面式子1-3,不单纯地使用一个假设,令:
P(xi|xi−1,xi−2)=λ1q(xi)+λ2q(xi|xi−1)+λ3q(xi|xi−1,xi−2)其中,要求λ1+λ2+λ3=1,证明过程如下:
考虑到这是一个概率问题,即训练集中,所有的三元组P(xi|xi−1,xi−2)之和应等于1:
∑P(xi|xi−1,xi−2)=∑λ1q(xi)+∑λ2q(xi|xi−1)+∑λ3q(xi|xi−1,xi−2)=λ1∑q(xi)+λ2∑q(xi|xi−1)+λ3∑q(xi|xi−1,xi−2)其中,因为概率计算,所以有∑q(xi)=1, ∑q(xi|xi−1)=1, ∑q(xi|xi−1,xi−2)=1,
因此,
∑P(xi|xi−1,xi−2)=λ1+λ2+λ3=1这里的三个系数用下面的方法进行选择:
挑选λ1,λ2,λ3的过程类似于BP神经网络中的反向传播过程,即优化过程,定义一个优化目标函数,然后从训练集中,分出一部分作为验证集,在验证集上确定系数:
L(λ1,λ2,λ3)=∑x1,x2,x3#(x1,x2,x3)logq(x3|x1,x2)当L(λ1,λ2,λ3)越大的时候,模型越好,所以:
λ1,λ2,λ3=argminλ1,λ2,λ3L(λ1,λ2,λ3)上面只是最简单的线性组合的形式,λ1,λ2,λ3之间是没有实质性关联的,还可以让它们有关系。
如,Bucketing方法:对出现不同次的词组,使用不同的系数:
又如,将三个系数写成同一个参数的线性组合:
λ1=c(xi−1,xi−2)c(xi−1,xi−2)+γλ2=(1−λ1)×c(xi−2)c(xi−2)+γλ3=1−λ1−λ23.1.2 Discounting
就是从概率不为0的词组中预留一部分的概率给未出现过词组。
4. 模型评估
模型想要达到的目的是,generate出来的句子是正确的!而这个“正确性”是由概率来表示的,概率P(S)越大表示越正确。也就是说,我们的目标就是:要使P(S)尽可能地大!!!
下面假设从测试集中生成了句子S={∗,∗,x1,x2,...,xn},则这个句子的正确性(概率)是:(以Bigram为例)
P(S)=P(x1,x2,...,xn)=∏i=1nP(xi|xi−1)注意到一个问题,在实际编程中,使用∏容易造成underflow,因为如果句子很长,P很小但位数很多,可能会溢出。所以在实际编程中,会对这个概率取对数
log ,把乘法变成加法,可以一定程度缓解这种情况:logP(S)=logP(x1,x2,...,xn)=log∏i=1nP(xi|xi−1)=∑i=1nlogP(xi|xi−1)然后从测试集中,我们生成了好多的句子{S1,S2,...,SM},则整体平均正确性(概率)为:其中M为测试集中单词的总数
l=1M∑j=1mlogP(Sj) 一般在机器学习中,评估标准是cost function,越小越好,在这里也是一样,为了满足越小越好,将上式变成下面的形式:
Perplexity=2−lwherel=1M∑j=1mlogP(Sj)可以看到,Perplexity越小,正确性越高(概率越大)。