圖解N-gram語言模型的原理--以kenlm爲例

常用的N-gram訓練工具有SRILM、IRSTLM、BerkeleyLM和KenLM等。這幾種工具所 用的算法思想基本一致,只是在實現細節上有所不同,所以我們只需理解其中一個訓 練工具即可。本文以KenLM(號稱速度最快,佔用內存最少)作爲訓練工具,對基於N-gram的過程進行詳細介紹,所用的平滑技術是Modified Kneser-ney smoothing,因爲它是當 前一個標準的、廣泛採用的、效果最好的平滑算法。

爲了方便說明訓練過程,我們以下列簡單文本爲例進行bigram操作:


你 我


對於KenLM工具,需要執行如下命令:lmplz -o 2 --text [inputfile] --arpa [outputfile]; 然後我們就可以得到如圖1所示的bigram結果:
bigram結果

圖1 bigram語言模型

接下來我們一步步剖析,看該結果是怎麼生成的。

一、增加<s>和</s>標記符,表示句子的開頭和結尾。

<s> 我 </s>
<s> 你 我 </s>
<s> 他 </s>
<s> 我 </s>
<s> 你 <</s>

二、把每個詞映射到唯一的數字id,爲了更直觀地描述下面的關鍵步驟,我們這裏就不把單詞映射爲數字id。
三、Counting(原始計數)。也就是把相同的字合併,然後排序(假設編碼順序爲<s>、我、你、他、<\s>) 。根據步驟一的文本,我們可以得到1-gram和2-gram的原始計數:
表1 1-gram counting
1-gram 原始計數
<s> 5
3
2
1
</s> 5
表2 2-gram counting
2-gram 原始計數
<s> 我 2
<s> 你 2
<s> 他 1
我 </s> 3
你 我 1
你 </s> 1
他 </s> 1
四、Adjusting(調整計數)。其基本思想是對於那些lower-gram,我們不care其出現的次數,而是關心其作爲novel continuation的可能性。比如“York”,其在語料中出現的次數一般會比較多,因爲“New York”是很高頻的詞。但“York”作爲continuation(中文意思:別的詞把“york”作爲接續詞)的可能性就較低,也就是說它前面的詞只有“new”等少數幾類詞,所以應該給它較低的計數。其公式如下:

這裏寫圖片描述(1)
式中:

  • w1nw_{1}^{n}表示某個n-gram,比如n=2時,那麼w12w_{1}^{2}就表示表2中第一列的某個2-gram。
  • c(w1n)c(w_{1}^{n})表示w1nw_{1}^{n}的原始計數;1-gram的原始計數見表1,2-gram的原始計數見表2;
  • a(w1n)a(w_{1}^{n})表示由原始計數調整後的計數;2-gram的調整後計數不變(根據式子(1)中的第一行),還是如表2所示;1-gram的調整後計數見表3(根據式子(1)中的第二行得到的)。

下面詳細介紹1-gram的調整計數的計算過程。特別需要說明的是公式(1)中的υ:c(υw1n)\left | \upsilon :c\left ( \upsilon w_{1}^{n}\right ) \right |表示w1nw_{1}^{n}前面出現的詞的種類,比如=“我”,詞庫中“<s>我”出現2次,“你我”出現1次,那麼“我”的前面出現的詞的種類就爲2,a(我)=2,而不是3,因爲我們care的不是出現次數。根據這一原則,我們可以得到1-gram的調整計數,如下表所示:
這裏寫圖片描述
而對於2-gram的adjusting count,根據式1的條件表達式(n=N)得,2-gram的adjusting count與表2相同。
這裏寫圖片描述

五、Discounting。其基本思想是把經常出現的一些N-Gram的概率分一些出來給沒有出 現的N-gram,也就等同於將經常出現的N-Gram次數減去(discount)一部分,這樣做的道理就在於,對於出現次數比較多的計數我們其實已經得到了一個相對比較好的估計,那麼當我們從這個計數值中減去一個較小的數值d後應該影響不大。那 到底該discount取多少呢?其中比較有代表性的有Church & Gale於1991年通過留存 法實驗從而得到的Absolute Discounting;另一個是Chen and Goodman於1998年提出 的方法,其公式如下:

這裏寫圖片描述(2)
式中:

  • k ε [1,3];對於k爲0的情況,Dn(0)D_{n}\left ( 0 \right )=0;對於k大於3的情況,Dn(k)D_{n}\left ( k \right )=Dn(3)D_{n}\left ( 3 \right )
  • n ε [1,N];比如在本例中我們採用2-gram,那麼N=2,n=[1,2];

在計算Dn(k)D_{n}\left ( k \right )之前,我們需要先計算tn,kt_{n,k}tn,kt_{n,k}表示出現了k次的n-gram的個數(比如根據表3,出現1次的1-gram的次數爲2,分別爲“你”、“他”)。其數學表達式如下:
這裏寫圖片描述(3)
根據公式(3)、表3和表4,我們可以得到tn,kt_{n,k}的取值(t1,1t_{1,1}t1,4t_{1,4}的計算參考表3,t2,1t_{2,1}t2,4t_{2,4}的計算參考表4)
這裏寫圖片描述
根據公式(2)和表5,我們可以得到Dn(k)D_{n}\left ( k \right )的取值:
這裏寫圖片描述

六、Normalization。該步驟其實分爲兩小步:

① 計算n-gram的概率,該概率稱之爲pseudo probability,也就是說它不是最終的概率,但對於計算最終概率是有用的。pseudo probability的計算公式如下:
這裏寫圖片描述(4)
我們可以看到跟傳統的n-gram公式相比,它的分子多減去一項,被減去的這一項也就是
第五步計算得到的discount。
接下來我以**u(我)和u(我∣你)**爲例來詳細介紹下計算過程,其他概率的計算讀者有興趣的話可以自己做下。

  • 對於u(我)的計算,n=1;

a()=a()Dn(a())Σxa(x)=11/21+1a(我)=\frac{a(我)-D_{n}(a(我))}{\Sigma_{x}\, a(x)}\, =\frac{1-1/2}{1+1}

其中Σxa(x)\Sigma_{x}a(x) = a(我) + a(你) + a(他) + a(<\s>) = 2+1+1+3 = 7。需要注意的是我們並沒有加上a(<s>),因爲<s>最爲句子開頭標誌,其前面不可能再有其他詞。

  • 對於u(我|你)的計算,n=2;

a()=a()Dn(a())Σxa(x)    =21/22+1+1+3a(我|你)=\frac{a(我|你)-D_{n}(a(我|你))}{\Sigma_{x}\, a(你\, x)}\, \, \, \, =\frac{2-1/2}{2+1+1+3}

其中Σxa(x)\Sigma_{x}a(你\, x) = a(你 我) + a(你 </s>) = 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()=122+540+302=12b(你)=\frac{\frac{1}{2}*2+\frac{5}{4}*0+3*0}{2} = \frac{1}{2}

b()=120+540+313=1b(我)=\frac{\frac{1}{2}*0+\frac{5}{4}*0+3*1}{3} = 1

b()=121+540+301=12b(他)=\frac{\frac{1}{2}*1+\frac{5}{4}*0+3*0}{1} = \frac{1}{2}

b(<s>)=121+542+305=35b(<s>)=\frac{\frac{1}{2}*1+\frac{5}{4}*2+3*0}{5} = \frac{3}{5}

然後對上述的概率取以10爲底的log,就能得到與圖1中的第三列對應的結果。需要注意的是我們沒有計算b(</s>),這是因爲</s>已經是句子的最後一個單詞,它在後退之後就沒有其他詞了。
ps:arpa中的概率是取log10,而不是ln!

七、Interpolation。在講解Interpolation之前,我們先看一個例子:如果c(多的)和c(多斂) 都爲0,也就是說在某個語料中都沒出現,那麼在傳統的n-gram中,p(的∣多)=p(斂∣ 多)。而這個概率我們直觀上來看是錯誤的,p(的∣多)應該比p(斂∣多)高很多。要實 現這個,我們就希望把 bigram 和 unigram 結合起來,因爲“的”比“斂”常見的多,就能保證p(的∣多)>p(斂∣多)。interpolate 就是這樣一種方法,它的數學表達式如下所示:

這裏寫圖片描述 (6)
該過程不斷遞歸,直到unigram停止。其中unigram的插值用uniform distribution表 示,如下列表達式所示:
這裏寫圖片描述 (7)
其中vocabulary\left | vocabulary \right |表示詞彙量大小,這裏總共有{<s>、我、你、他、<\s>}5個詞,所以 vocabulary\left | vocabulary \right | =5;ε表示空字符串。b(ε)b\left ( \varepsilon \right )的計算需要特別說明下:

b(ε)=122+121+312+1+1+3=914b\left ( \varepsilon \right )=\frac{\frac{1}{2}*2+\frac{1}{2}*1+3*1}{2+1+1+3} = \frac{9}{14}

需要注意的是,上式對於b(ε)b\left ( \varepsilon \right )的計算,n應該取1。
接下來我們選取幾個概率進行計算,來驗證下計算結果是否與實際結果相同

p()=u()+b(ε)1vocabulary=314+91415=2470p(我)=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()p()=14+1224700.4214285p(我|你)=u(我|你)+b(你)*p(我) = \frac{1}{4} +\frac{1}{2}*\frac{24}{70}\approx0.4214285

如果你仔細看圖1,你會發現其中有個<unk>字符,但實際上我們的文本中並沒有這個字符。引入<unk>字符後,我們就可以把未登錄詞當作<unk>對待。
因爲我們這個例子沒有未登錄詞,所以<unk>字符的計數爲0,即a(<unk>)=0。

p(<unk>)=0+b(ε)1vocabulary=91415=970p(<unk>)=0+b\left ( \varepsilon \right )*\frac{1}{\left | vocabulary \right |} = \frac{9}{14}*\frac{1}{5}=\frac{9}{70}

同樣的,對上述的概率取以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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章