常用的N-gram训练工具有SRILM、IRSTLM、BerkeleyLM和KenLM等。这几种工具所 用的算法思想基本一致,只是在实现细节上有所不同,所以我们只需理解其中一个训 练工具即可。本文以KenLM(号称速度最快,占用内存最少)作为训练工具,对基于N-gram的过程进行详细介绍,所用的平滑技术是Modified Kneser-ney smoothing,因为它是当 前一个标准的、广泛采用的、效果最好的平滑算法。
为了方便说明训练过程,我们以下列简单文本为例进行bigram操作:
我
你 我
他
我
你
对于KenLM工具,需要执行如下命令:lmplz -o 2 --text [inputfile] --arpa [outputfile]; 然后我们就可以得到如图1所示的bigram结果:
接下来我们一步步剖析,看该结果是怎么生成的。
我
你 我
他
我
你 <
1-gram | 原始计数 |
---|---|
5 | |
我 | 3 |
你 | 2 |
他 | 1 |
5 |
2-gram | 原始计数 |
---|---|
2 | |
2 | |
1 | |
我 | 3 |
你 我 | 1 |
你 | 1 |
他 | 1 |
下面详细介绍1-gram的调整计数的计算过程。特别需要说明的是公式(1)中的 ∣ υ : c ( υ w 1 n ) ∣ \left | \upsilon :c\left ( \upsilon w_{1}^{n}\right ) \right | ∣υ:c(υw1n)∣表示 w 1 n w_{1}^{n} w1n前面出现的词的种类,比如=“我”,词库中“我”出现2次,“你我”出现1次,那么“我”的前面出现的词的种类就为2,a(我)=2,而不是3,因为我们care的不是出现次数。根据这一原则,我们可以得到1-gram的调整计数,如下表所示:
而对于2-gram的adjusting count,根据式1的条件表达式(n=N)得,2-gram的adjusting count与表2相同。
在计算 D n ( k ) D_{n}\left ( k \right ) Dn(k)之前,我们需要先计算 t n , k t_{n,k} tn,k。 t n , k t_{n,k} tn,k表示出现了k次的n-gram的个数(比如根据表3,出现1次的1-gram的次数为2,分别为“你”、“他”)。其数学表达式如下:
(3)
根据公式(3)、表3和表4,我们可以得到 t n , k t_{n,k} tn,k的取值( t 1 , 1 t_{1,1} t1,1至 t 1 , 4 t_{1,4} t1,4的计算参考表3, t 2 , 1 t_{2,1} t2,1至 t 2 , 4 t_{2,4} t2,4的计算参考表4)
根据公式(2)和表5,我们可以得到 D n ( k ) D_{n}\left ( k \right ) Dn(k)的取值:
① 计算n-gram的概率,该概率称之为pseudo probability,也就是说它不是最终的概率,但对于计算最终概率是有用的。pseudo probability的计算公式如下:
(4)
我们可以看到跟传统的n-gram公式相比,它的分子多减去一项,被减去的这一项也就是
第五步计算得到的discount。
接下来我以**u(我)和u(我∣你)**为例来详细介绍下计算过程,其他概率的计算读者有兴趣的话可以自己做下。
a ( 我 ) = a ( 我 ) − D n ( a ( 我 ) ) Σ x a ( x ) = 1 − 1 / 2 1 + 1 a(我)=\frac{a(我)-D_{n}(a(我))}{\Sigma_{x}\, a(x)}\, =\frac{1-1/2}{1+1} a(我)=Σxa(x)a(我)−Dn(a(我))=1+11−1/2
其中 Σ x a ( x ) \Sigma_{x}a(x) Σxa(x) = a(我) + a(你) + a(他) + a(<\s>) = 2+1+1+3 = 7。需要注意的是我们并没有加上a(),因为最为句子开头标志,其前面不可能再有其他词。
a ( 我 ∣ 你 ) = a ( 我 ∣ 你 ) − D n ( a ( 我 ∣ 你 ) ) Σ x a ( 你 x ) = 2 − 1 / 2 2 + 1 + 1 + 3 a(我|你)=\frac{a(我|你)-D_{n}(a(我|你))}{\Sigma_{x}\, a(你\, x)}\, \, \, \, =\frac{2-1/2}{2+1+1+3} a(我∣你)=Σxa(你x)a(我∣你)−Dn(a(我∣你))=2+1+1+32−1/2
其中 Σ x a ( 你 x ) \Sigma_{x}a(你\, x) Σxa(你x) = a(你 我) + a(你 ) = 1+1 = 2。
② 计算回退权重,也称为back-off weight, 它衡量的是某个词后面能接不同词的能力。举个例子,考虑 spite 和 constant 的 bigram,在 Europarl corpus 中,两个 bigram 都出现了 993 次,以 spite 开始的 bigram 只有 9 种,大多数情况下 spite 后面跟着 of(979 次),因为 in spite of 是常见的表达,而跟在 constant 后的单词有 415 种,所以我们更有可能见到一个跟在 constant 后面的bigram,因此back-off(constant)>back-off(spite)。 基于上述思想,定义其表达式为:
(5)
根据该公式,再结合表3和表6,我们可以计算每个字的回退权重,如下:
b ( 你 ) = 1 2 ∗ 2 + 5 4 ∗ 0 + 3 ∗ 0 2 = 1 2 b(你)=\frac{\frac{1}{2}*2+\frac{5}{4}*0+3*0}{2} = \frac{1}{2} b(你)=221∗2+45∗0+3∗0=21
b ( 我 ) = 1 2 ∗ 0 + 5 4 ∗ 0 + 3 ∗ 1 3 = 1 b(我)=\frac{\frac{1}{2}*0+\frac{5}{4}*0+3*1}{3} = 1 b(我)=321∗0+45∗0+3∗1=1
b ( 他 ) = 1 2 ∗ 1 + 5 4 ∗ 0 + 3 ∗ 0 1 = 1 2 b(他)=\frac{\frac{1}{2}*1+\frac{5}{4}*0+3*0}{1} = \frac{1}{2} b(他)=121∗1+45∗0+3∗0=21
b ( < s > ) = 1 2 ∗ 1 + 5 4 ∗ 2 + 3 ∗ 0 5 = 3 5 b()=\frac{\frac{1}{2}*1+\frac{5}{4}*2+3*0}{5} = \frac{3}{5} b(<s>)=521∗1+45∗2+3∗0=53
然后对上述的概率取以10为底的log,就能得到与图1中的第三列对应的结果。需要注意的是我们没有计算b(),这是因为已经是句子的最后一个单词,它在后退之后就没有其他词了。
ps:arpa中的概率是取log10,而不是ln!
(6)
该过程不断递归,直到unigram停止。其中unigram的插值用uniform distribution表 示,如下列表达式所示:
(7)
其中 ∣ v o c a b u l a r y ∣ \left | vocabulary \right | ∣vocabulary∣表示词汇量大小,这里总共有{、我、你、他、<\s>}5个词,所以 ∣ v o c a b u l a r y ∣ \left | vocabulary \right | ∣vocabulary∣ =5;ε表示空字符串。 b ( ε ) b\left ( \varepsilon \right ) b(ε)的计算需要特别说明下:
b ( ε ) = 1 2 ∗ 2 + 1 2 ∗ 1 + 3 ∗ 1 2 + 1 + 1 + 3 = 9 14 b\left ( \varepsilon \right )=\frac{\frac{1}{2}*2+\frac{1}{2}*1+3*1}{2+1+1+3} = \frac{9}{14} b(ε)=2+1+1+321∗2+21∗1+3∗1=149
需要注意的是,上式对于 b ( ε ) b\left ( \varepsilon \right ) b(ε)的计算,n应该取1。
接下来我们选取几个概率进行计算,来验证下计算结果是否与实际结果相同。
p ( 我 ) = u ( 我 ) + b ( ε ) ∗ 1 ∣ v o c a b u l a r y ∣ = 3 14 + 9 14 ∗ 1 5 = 24 70 p(我)=u(我)+b\left ( \varepsilon \right )*\frac{1}{\left | vocabulary \right |} = \frac{3}{14} +\frac{9}{14}*\frac{1}{5}=\frac{24}{70} p(我)=u(我)+b(ε)∗∣vocabulary∣1=143+149∗51=7024
p ( 我 ∣ 你 ) = u ( 我 ∣ 你 ) + b ( 你 ) ∗ p ( 我 ) = 1 4 + 1 2 ∗ 24 70 ≈ 0.4214285 p(我|你)=u(我|你)+b(你)*p(我) = \frac{1}{4} +\frac{1}{2}*\frac{24}{70}\approx0.4214285 p(我∣你)=u(我∣你)+b(你)∗p(我)=41+21∗7024≈0.4214285
如果你仔细看图1,你会发现其中有个
因为我们这个例子没有未登录词,所以
p ( < u n k > ) = 0 + b ( ε ) ∗ 1 ∣ v o c a b u l a r y ∣ = 9 14 ∗ 1 5 = 9 70 p(
同样的,对上述的概率取以10为底的log,就能得到与图1中的第一列对应的结果。 因为篇幅有限(实际上也没这个必要),我就不把全部的概率计算过程列出来了。读者 有兴趣可以按照上面的方法把全部概率都计算一遍,再跟实际结果对比。
希望这个简单的例子对大家理解n-gram和Modified Kneser-ney smoothing有所帮助,谢谢!
[1]: Heafield K, Pouzyrevsky I, Clark J H, et al. Scalable Modified Kneser-Ney Language Model Estimation[C]// Meeting of the Association for Computational Linguistics. 2013:690-696.