本文爲轉載https://blog.csdn.net/asrgreek/article/details/81979194的基礎上,做了一些推演與推演過程的修正,如有錯誤歡迎指正。
本文以KenlM介紹常用的N-gram語言模型原理。KenlM採用的平滑技術是Modified Kneser-ney smoothing
以以下代碼段爲例介紹,以N=2爲例,即2-gram,bigram介紹N-gram模型:
我
你 我
他
我
你
接下來我們一步步剖析該模型的實現過程
一、增加<s>和</s>標記符,表示句子的開頭和結尾
<s> 我 </s>
<s> 你 我 </s>
<s> 他 </s>
<s> 我 </s>
<s> 你 </s>
二、把每個詞映射到唯一的數字id,爲了更直觀地描述下面的關鍵步驟,我們這裏就不把單詞映射爲數字id
三、Counting(原始計數)。也就是把相同的字合併,然後排序(假設編碼順序爲<s>、我、你、他、<\s>) 。根據步驟一的文本,我們可以得到1-gram和2-gram的原始計數counting一列:
表1 1-gram counting
1-gram | 原始計數counting | 中間計算過程 | Adjust count |
<s> | 5 | 由公式第一行,=<s>,a(<s>)=c(<s>)=5 | 5 |
我 | 3 | “我”前面出現了“你”和“<s>”,a(我)=2 | 2 |
你 | 2 | “你”前面出現了“<s>”,a(你)=1 | 1 |
他 | 1 | “他”前面出現了“<s>”,a(他)=1 | 1 |
</s> | 5 | “</s>”前面出現了“我”,“你”,“他”a(<\s>)=3 | 3 |
2-gram | 原始計數 | 中間計算過程 |
Adjust count |
---|---|---|---|
<s> 我 | 2 | 根據式1的條件表達式(n=N),故與原始計數相同 | 2 |
<s> 你 | 2 | 同上 | 2 |
<s> 他 | 1 | 同上 | 1 |
我 </s> | 3 | 同上 | 3 |
你 我 | 1 | 同上 | 1 |
你 </s> | 1 | 同上 | 1 |
他 </s> | 1 | 同上 | 1 |
四、Adjusting(調整計數)。其基本思想是對於那些lower-gram,我們不care其出現的次數,而是關心其作爲novel continuation的可能性。比如“York”,其在語料中出現的次數一般會比較多,因爲“New York”是很高頻的詞。但“York”作爲continuation(中文意思:別的詞把“york”作爲接續詞)的可能性就較低,也就是說它前面的詞只有“new”等少數幾類詞,所以應該給它較低的計數。其公式如右:
其中:
- 表示某個n-gram,比如n=2時,那麼表示表2中第一列的某個2-gram
- c()表示的原始計數;1-gram的原始計數見表1,2-gram的原始計數見表
- a()表示由原始計數調整後的計數;2-gram的調整後計數不變(根據式子(1)中的第一行),還是如表2所示;1-gram的調整後計數見表1(根據式子(1)中的第二行得到的)第三和第四列
特別需要說明的是公式(1)中的|v:c(v)∣,表示前面出現的詞的種類,比如=“我”,詞庫中“<s>我”出現2次,“你我”出現1次,那麼“我”的前面出現的詞的種類就爲2,a(我)=2,而不是3,因爲我們care的不是出現次數。根據這一原則,我們可以得到1-gram的調整計數,如表1的第三/四列所示
而對於2-gram的adjusting count,根據式1的條件表達式(n=N)得,2-gram的adjusting count與表2相同,如表2的第三/四列所示
五、Discounting。其基本思想是把經常出現的一些N-Gram的概率分一些出來給沒有出 現的N-gram,也就等同於將經常出現的N-Gram次數減去(discount)一部分,這樣做的道理就在於,對於出現次數比較多的計數我們其實已經得到了一個相對比較好的估計,那麼當我們從這個計數值中減去一個較小的數值d後應該影響不大。那 到底該discount取多少呢?其中比較有代表性的有Church & Gale於1991年通過留存 法實驗從而得到的Absolute Discounting;另一個是Chen and Goodman於1998年提出 的方法,其公式如下:
- k範圍爲[1,3],k=0時,=0, k>3時,=
- n範圍爲[1,N],本文中N=2,所以n的範圍爲[1,2]
n ε [1,N];比如在本例中我們採用2-gram,那麼N=2,n=[1,2];
在計算Dn(k)之前,我們需要先計算tn,k。tn,k表示出現了k次的n-gram的個數(比如根據表3,出現1次的1-gram的次數爲2,分別爲“你”、“他”)。其數學表達式如下:
(3)根據公式(3)、表3和表4,我們可以得到的取值到,到
中間計算過程 | 結果 | |
a()=1:“你”,“我” | 2 | |
a()=2:“我” | 1 | |
a()=3:“</s>” | 1 | |
a()=4:無 | 0 | |
a()=1:“<s>他”,“你我”,“你</s>”,“他</s>” | 4 | |
a()=2:“<s>我”,“<s>你” | 2 | |
a()=3:“我</s>” | 1 | |
a()=4:無 | 0 |
根據公式(2)和表5,我們可以得到Dn(k)的取值:
Discount | 中間計算過程 | 結果 |
D1(1) | a()=1:“你”,“我” | 1/2 |
D1(2) | a()=2:“我” | 1/2 |
D1(3) | a()=3:“</s>” | 3 |
D2(1) | a()=4:無 | 1/2 |
D2(2) | a()=1:“<s>他”,“你我”,“你</s>”,“他</s>” | 4/5 |
D2(3) | a()=2:“<s>我”,“<s>你” | 3 |
六、Normalization。該步驟其實分爲兩小步:
① 計算n-gram的概率,該概率稱之爲pseudo probability,也就是說它不是最終的概率,但對於計算最終概率是有用的。pseudo probability的計算公式(4)如下:
我們可以看到跟傳統的n-gram公式相比,它的分子多減去一項,被減去的這一項也就是第五步計算得到的discount。
接下來我以u(我)和u(我∣你)爲例來詳細介紹下計算過程,其他概率的計算讀者有興趣的話可以自己做下。
對於u(我)的計算,n=1;
Unexpected text node: ' '
a(我)= (a(我)-Dn(a(我)))/(Σxa(x))=(2-1/2)/(2+1+1+3)
其中Σxa(x) = a(我) + a(你) + a(他) + a(<\s>) = 2+1+1+3 = 7。需要注意的是我們並沒有加上a(<s>),因爲<s>最爲句子開頭標誌,其前面不可能再有其他詞
對於u(我|你)的計算,n=2;
a(我∣你)= Σxa(你x)a(我∣你)−Dn(a(我∣你))=(1-1/2)/(1+1)
其中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,我們可以計算每個字的回退權重,如下:
然後對上述的概率取以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∣表示詞彙量大小,這裏總共有{<s>、我、你、他、<\s>}5個詞,所以 ∣vocabulary∣=5;ε表示空字符串。b(ε)
b(ε)的計算需要特別說明下:
b(ε)=12∗2+12∗1+3∗12+1+1+3=914
需要注意的是,上式對於b(ε)b(ε)的計算,n應該取1。
接下來我們選取幾個概率進行計算,來驗證下計算結果是否與實際結果相同。
p(我)=u(我)+b(ε)∗1∣vocabulary∣=3/14+9/14∗1/5=24/70
p(我∣你)=u(我∣你)+b(你)∗p(我)= 1/4+1/2*(24/70)=59/140
如果你仔細看圖1,你會發現其中有個<unk>字符,但實際上我們的文本中並沒有這個字符。引入<unk>字符後,我們就可以把未登錄詞當作<unk>對待。
因爲我們這個例子沒有未登錄詞,所以<unk>字符的計數爲0,即a(<unk>)=0。p(<unk>)=0+b(ε)∗1∣vocabulary∣=9/14∗(1/5)=9/70
同樣的,對上述的概率取以10爲底的log,就能得到與圖1中的第一列對應的結果。 因爲篇幅有限(實際上也沒這個必要),我就不把全部的概率計算過程列出來了。讀者 有興趣可以按照上面的方法把全部概率都計算一遍,再跟實際結果如下圖對比