2018年04月03日 18:16:20 qjf42 阅读数:646
版权声明:本文为博主原创文章,欢迎交流分享,未经博主允许不得转载。 https://blog.csdn.net/qjf42/article/details/79761786
语言模型(Language Model
,LM
)的一个常见任务,是已知一句话的前面几个词,预测下一个是什么,即对P(wi∣wi−11)P(w_i|w_1^{i−1})P(wi∣w1i−1)建模
N-gram语言模型,是基于Markov假设,假设文本中的每个词只与前面的n-1个词有关,即P(wi∣wi−11)≈P(wi∣wi−1i−n+1)=P(wi∣wi−1,…,wi−n+1)P(w_i|w_{1}^{i-1}) \approx P(w_i|w_{i-n+1}^{i-1}) = P(w_i|w_{i-1}, \dots ,w_{i-n+1})P(wi∣w1i−1)≈P(wi∣wi−n+1i−1)=P(wi∣wi−1,…,wi−n+1)
这可以通过对训练语料做极大似然估计,
P(wi∣wi−1i−n+1)=Count(wi,wi−1,…,wi−n+1)Count(wi−1,…,wi−n+1)P(w_i|w_{i-n+1}^{i-1}) = \frac{Count(w_i, w_{i−1},…,w_{i−n+1})}{Count(w_{i−1},…,w_{i−n+1)}}P(wi∣wi−n+1i−1)=Count(wi−1,…,wi−n+1)Count(wi,wi−1,…,wi−n+1)
由此我们可以求一段文本(句子)sss 的概率
首先在句子的首尾增加两个特殊标记 <s>, </s>\text{<s>, </s>},
再通过链式法则,以bigram(n=2)为例,
P(s)=P(<s>,w1,…,wN,</s>)=P(<s>)P(w1∣<s>)P(w2∣w1,<s>)…P(wN∣wN−11,<s>)P(</s>∣wN1,<s>)=P(w1∣<s>)P(w2∣w1)…P(wN∣wN−1)P(</s>∣wN)\begin{aligned}P(s) &= P(\text{<s>}, w_1, \dots, w_N, \text{</s>}) \\&= P(\text{<s>}) P(w_1 | \text{<s>}) P(w_2 | w_1, \text{<s>}) \dots P(w_N |w^{N−1}_1, \text{<s>})P( \text{</s>} |w^N_1, \text{<s>}) \\&= P(w_1 | \text{<s>}) P(w_2 | w_1) \dots P(w_N |w_{N−1})P( \text{</s>} | w_N)\end{aligned}P(s)=P(,w1,…,wN,)=P()P(w1∣)P(w2∣w1,)…P(wN∣w1N−1,)P(∣w1N,)=P(w1∣)P(w2∣w1)…P(wN∣wN−1)P(∣wN)
通常,为了防止概率(<1)连乘 导致浮点underflow,对其取对数,这样乘法就变成了加法
logP(s)=logP(w1∣<s>)+logP(w2∣w1)+⋯+logP(</s>∣wN)\log P(s) = \log P(w_1 | \text{<s>}) + \log P(w_2 | w_1) + \dots + \log P(\text{</s>}|w_N)logP(s)=logP(w1∣)+logP(w2∣w1)+⋯+logP(∣wN)
刚才我们通过训练集得到了语言模型,而perplexity是一种评价语言模型在测试集上表现的方法
对一句句子来说,
Perplexity(s)=P(s)−1N+1=2−1N+1⋅logP(s)Perplexity(s) = P(s)^{-\frac{1}{N+1}} = 2^{-\frac{1}{N+1} \cdot \log P(s)}Perplexity(s)=P(s)−N+11=2−N+11⋅logP(s)
对于bigram LM来说,就是
1P(w1∣<s>)P(w2∣w1)…P(wN∣wN−1)P(</s>∣wN)‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾√N+1\sqrt[N+1]{\frac{1}{P(w_1 | \text{<s>}) P(w_2 | w_1) \dots P(w_N |w_{N−1})P( \text{</s>} | w_N)}}N+1P(w1∣)P(w2∣w1)…P(wN∣wN−1)P(∣wN)1
对于整个测试集,我们再对所有句子的perplexity,求几何平均,得到整体的结果
这里用N′N'N′表示所有测试集中句子长度之和,即N′=∑(Nk+1)N'=\sum (N_k+1)N′=∑(Nk+1),
Perplexity=P(S)−1N′=2−1N′⋅logP(S)=2−∑logP(sk)∑(Nk+1)Perplexity = P(S)^{-\frac{1}{N'}} = 2^{-\frac{1}{N'} \cdot \log P(S)} = 2^{-\frac{\sum \log P(s_k)}{\sum (N_k+1)}}Perplexity=P(S)−N′1=2−N′1⋅logP(S)=2−∑(Nk+1)∑logP(sk)
解释
注意
PS:以下对"ngram"和"词"不做区分
3.1 问题
OOV
, Out-of-vocabulary
) 的词3.2 常用方法
3.2.1 Laplace平滑 (add-one, add-α)
p=c+αn+αvp = \frac{c + \alpha}{n + \alpha v}p=n+αvc+α
其中 0≤α≤1, v=∣V∣0 \le \alpha \le 1,\ v = |V|0≤α≤1, v=∣V∣
词表内
的词,∑v1p=1\sum_{1}^{v} {p} = 1∑1vp=1,也就是说,在做了平滑之后,表内词概率和为1(也就是说算上OOV所有可能出现的词概率之和>1 !)
OOV
的词,c=0⇒p=αn+αv=1n/α+vc=0 \Rightarrow p=\frac{\alpha}{n + \alpha v} = \frac{1}{n/\alpha + v}c=0⇒p=n+αvα=n/α+v1,α\alphaα的选择可以用cross-validation3.2.2 Good-Turing Smoothing
3.2.3 Backoff (Katz)
上面的两种处理方式,是对原先概率为0的情况作了一刀切地处理,但是有些ngram其实比另一些更有可能出现,所以这么做肯定不那么准确。由此,我们分两种情况:
PBO(wn∣wn−1n−N+1)={P∗(wn∣wn−1n−N+1),α(wn−1n−N+1)PBO(wn∣wn−1n−N+2),if Count(wnn−N+1)>0elseP_{BO}(w_n | w_{n−N+1}^{n-1}) =\begin{cases} P^∗(w_n | w_{n−N+1}^{n-1}), & if\ Count(w_{n−N+1}^{n}) > 0 \\ \alpha(w_{n−N+1}^{n-1}) P_{BO}(w_n | w_{n−N+2}^{n-1}), & else\end{cases}PBO(wn∣wn−N+1n−1)={P∗(wn∣wn−N+1n−1),α(wn−N+1n−1)PBO(wn∣wn−N+2n−1),if Count(wn−N+1n)>0else
3.2.4 Interpolation(Jelinek-Mercer)
除了backoff之外,另一种利用多层context的方法是做插值,两者的不同在于
以trigram为例,
pI(wn∣wn−1,wn−2)=λ1p(wn)+λ2p(wn∣wn−1)+λ3p(wn∣wn−1,wn−2)s.t λ1+λ2+λ3=1p_I(w_n|w_{n-1}, w_{n-2})= \lambda_1 p(w_n) + \lambda_2 p(w_n|w_{n-1}) + \lambda_3 p(w_n|w_{n-1}, w_{n-2}) \\s.t\ \ \ \lambda_1 + \lambda_2 + \lambda_3 = 1pI(wn∣wn−1,wn−2)=λ1p(wn)+λ2p(wn∣wn−1)+λ3p(wn∣wn−1,wn−2)s.t λ1+λ2+λ3=1
3.2.5 Recursive Interpolation
递归地调用插值法
pIn(wi∣wi−1i−n+1)=λ(wi−1i−n+1) pn(wi∣wi−1i−n+1)+(1−λ(wi−1i−n+1)) pIn−1(wi∣wi−1i−n+2)p_n^{I}(w_i | w_{i−n+1}^{i−1}) = \lambda(w_{i−n+1}^{i−1})\ p_n(w_i | w_{i−n+1}^{i−1}) + (1 − \lambda(w_{i−n+1}^{i−1}))\ p_{n−1}^{I}(w_i |w_{i−n+2}^{i−1})pnI(wi∣wi−n+1i−1)=λ(wi−n+1i−1) pn(wi∣wi−n+1i−1)+(1−λ(wi−n+1i−1)) pn−1I(wi∣wi−n+2i−1)
3.2.6 Absolute Discounting
上面的很多做法都需要对训练集中的ngram做discount,把剩下的概率匀给unseen ngram。
Church & Gale (1991) 做了一项实验,他们将语料库分成大小相同的两部分(训练集和验证集分别有2200万),观察那些在训练集中出现了rrr次的bigram 在验证集中平均出现的次数。
下面给出不同的 rrr 的结果,
可以看出,除了r=0或1r =0或1r=0或1的bigram之外,验证集中的平均出现次数,都约等于 r−0.75r - 0.75r−0.75。
和Good-Turing Smoothing不同的是,Absolute discounting 直接对rrr进行某种确定性的操作,不依赖于训练集的NrN_rNr。
照着这个思路,
PAD(wi∣wi−1)=(Count(wi,wi−1)−d)/Count(wi−1)+λ(wi−1)P(wi)P_{AD}(w_i | w_{i-1}) = (Count(w_i, w_{i-1}) - d) / Count(w_{i-1}) + \lambda(w_{i−1})P(w_i)PAD(wi∣wi−1)=(Count(wi,wi−1)−d)/Count(wi−1)+λ(wi−1)P(wi)
3.2.7 Witten-Bell Smoothing
一种确定插值法中λ\lambdaλ的思路
3.2.8 Kneser-Ney discounting
让我们来看一道完形填空: I can’t see without my reading (York/glasses).
所以,与Witten-Bell的思路类似,但我们这里考虑可能的上文,或者说这个词本身作为下文(as continuation)的可能性
从而,我们有
PKN(wi∣wi−1)=max(Count(wi,wi−1)−d,0)Count(wi−1)+λ(wi−1)Pcontinuation(wi)P_{KN}(w_i | w_{i−1}) = \frac{max(Count(w_i, w_{i-1}) - d, 0)}{Count(w_{i-1})}+\lambda(w_{i−1}) P_{continuation}(w_i)PKN(wi∣wi−1)=Count(wi−1)max(Count(wi,wi−1)−d,0)+λ(wi−1)Pcontinuation(wi)
对于更高阶的ngram,我们可以用递归的方式
PKN(wi∣wi−1i−n+1)=max(CKN(wii−n+1)−d,0)CKN(wi−1i−n+1)+λ(wi−1i−n+1)PKN(wi∣wi−1i−n+2)P_{KN}(w_i | w_{i-n+1}^{i-1}) = \frac {max(C_{KN}(w_{i-n+1}^{i}) - d, 0)}{C_{KN}(w_{i-n+1}^{i-1})} + \lambda(w_{i-n+1}^{i-1})P_{KN}(w_i | w_{i-n+2}^{i-1})PKN(wi∣wi−n+1i−1)=CKN(wi−n+1i−1)max(CKN(wi−n+1i)−d,0)+λ(wi−n+1i−1)PKN(wi∣wi−n+2i−1)
如果不限制ddd是固定的,而采用absolute discounting中区分count为0, 1, >1的方法,那就变成了Modified Kneser-Ney discounting,基本是目前效果最好的平滑方法之一了
3.2.9 Stupid Backoff
google提出的一种面向大型语料库的方法,在语料足够多的情况下,效果可以与Kneser-Ney媲美
(有兴趣可以玩一下google ngram)
3.3 小结
- Speech and Language Processing 3rd ed, Chapter 4, Daniel Jurafsky.,
- Statistical Machine Translation, Chapter 7, Koehn