手算KN-based ngram语言模型
什么是ngram語言模型
語言模型是NLP中最最基礎的模塊,從傳統基于統計的ngram語言模型,再到基于深度學習的CNN,RNN語言模型,再到現在基于tranformer的預訓練語言模型,每次語言模型的發展都能給整個NLP領域帶來巨大推動。
由于傳統的ngram語言模型具備原理簡單,推斷速度快等特點,所以至今依然在廣泛應用在眾多NLP任務中,尤其在計算資源受限的移動端。本文將系統介紹ngram語言模型的內部原理,計算方法及相關工具。
ngram語言模型計算方法
給定一句話:
,這里的 為語言描述的最小單元,可以是字,也可以是詞。語言模型是用來評價這一句話成立的概率:對于其中的每一小項
, 可以用頻率來估計概率,即:這里
表示在整個語料中 聯合出現的次數。理論上語料足夠充足,就可以很好的用頻率直接估計出概率,但實際操作中對于較長的序列
可能數量非常少,或者不存在。例如,計算: p(處理| {我, 愛, 自然, 語言}),可能整個語料中都沒有{我, 愛, 自然, 語言, 處理}這個表達。ngram語言模型的核心就在于一個強假設:當前詞的概率分布只與前N-1個詞有關,即:
本質上 N-gram 模型的假設類似于馬爾可夫鏈當中的 N-1 階馬爾可夫性假設。通常情況下n=1,2,3。對于再高階的4-gram,5-gram就很少見,因為需要非常大的語料才能訓練充分高階的語言模型,而且模型本身的體積也會非常大(占內存)。
- 當n=1時為unigram:當前詞的概率分布與歷史信息無關
- 當n=2時為bigram:當前詞的概率分布只和前一個詞有關
- 當n=3時為trigram:當前詞的概率分布只和前兩個詞有關
所以假設n=2,p(處理| {我, 愛, 自然, 語言}) = p(處理| 語言) = #{語言, 處理} / #{語言} ,這樣相對而言就可算了。
基于kenlm的ngram語言模型訓練
運用ngram語言模型目前最便捷的工具就是kenlm,可快速實現語言模型的訓練與應用。
首先準備一份語言模型訓練語料(test_corpus.txt)注意每個詞之前需要空格分割,如果訓練基于字的語言模型,則每個字之前用空格分割。
模型 語言 模型 傳統 模型 語言關于kenlm的安裝網上有很多教程,實際操作的過程中也確實有坑,為了避免踩坑,可直接采用docker來獲得已安裝了kenlm的環境。具體參見:GitHub - nghuyong/kenlm-docker: docker for kenlm 。下面采用kenlm訓練一個bigram語言模型:
# 拉取鏡像 docker pull nghuyong/kenlm # 啟動并進入容器 docker run -it -v $(pwd):/var nghuyong/kenlm bash # 容器內訓練kenlm ./lmplz -o 2 --verbose_header --text /var/test_corpus.txt --arpa /var/arpa.kenlm這樣就完成了語言模型的訓練,并獲得arpa模型文件。
下面是輸出的apra文件
# Input file: /var/test_corpus.txt # Token count: 6 # Smoothing: Modified Kneser-Ney \data\ ngram 1=6 ngram 2=7\1-grams: -0.89085555 <unk> 0 0 <s> -0.22184873 -0.89085555 </s> 0 -0.46488678 模型 0 -0.69896996 語言 -0.30103 -0.69896996 傳統 -0.30103\2-grams: -0.89085555 模型 </s> -0.50267535 語言 </s> -0.24850096 傳統 </s> -0.44889864 <s> 模型 -0.37527603 語言 模型 -0.56863624 <s> 語言 -0.6575773 <s> 傳統\end\可以看到生成的arpa文件包括ngram的統計值以及ngram的概率。基于這份arpa文件就可以計算一句話的概率分布了。
再看一下kenlm訓練過程輸出的日志情況:
=== 1/5 Counting and sorting n-grams === Reading /data/mm64/rightyonghu/code/kenlm/build/bin/test_corpus.txt ----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100 **************************************************************************************************** Unigram tokens 6 types 6 === 2/5 Calculating and sorting adjusted counts === Chain sizes: 1:72 2:33536714342 Statistics: 1 6 D1=0.5 D2=0.5 D3+=3 2 7 D1=0.5 D2=1.25 D3+=3 Memory estimate for binary LM: type B probing 292 assuming -p 1.5 probing 320 assuming -r models -p 1.5 trie 226 without quantization trie 1235 assuming -q 8 -b 8 quantization trie 226 assuming -a 22 array pointer compression trie 1235 assuming -a 22 -q 8 -b 8 array pointer compression and quantization === 3/5 Calculating and sorting initial probabilities === Chain sizes: 1:72 2:112 ----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100 #################################################################################################### === 4/5 Calculating and writing order-interpolated probabilities === Chain sizes: 1:72 2:112 ----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100 #################################################################################################### === 5/5 Writing ARPA model === ----5---10---15---20---25---30---35---40---45---50---55---60---65---70---75---80---85---90---95--100 **************************************************************************************************** Name:lmplz VmPeak:33297604 kB VmRSS:3344 kB RSSMax:8928344 kB user:0.484 sys:3.636 CPU:4.12075 real:4.12281根據日志可以看出,kenlm在訓練語言模型時候分成了5個主要步驟:統計并排序ngram,計算并排序調整就計數,計算并排序初始概率,計算并寫入差值概率以及生成arpa模型文件。
下面我們就將細致拆解這個幾個步驟,給定語料,硬核的手算出arpa模型。
手算基于KN的語言模型
繼續以test_corpus.txt為語料,手算一個bigram的語言模型。
模型 語言 模型 傳統 模型 語言1. ngram初始統計
第一步是進行ngram的統計,因為這里訓練bigram的語言模型,所以需要統計unigram以及bigram的數量。
在進行統計之前需要先給語料中每句話的開始和結束加上特殊的token:<s> 和 </s>。這樣語料進一步處理成:
<s> 模型 </s> <s> 語言 模型 </s> <s> 傳統 </s> <s> 模型 </s> <s> 語言 </s>根據以上語料統計ngram的數量
| unigram | count |
| <s> | 5 |
| 傳統 | 1 |
| 語言 | 2 |
| 模型 | 3 |
| </s> | 5 |
| bigram | count |
| <s> 模型 | 2 |
| <s> 語言 | 2 |
| <s> 傳統 | 1 |
| 語言 模型 | 1 |
| 模型 </s> | 3 |
| 傳統 </s> | 1 |
| 語言 </s> | 1 |
2. ngram計數調整
對于N-gram的語言模型,調整技術主要針對n<N的ngram進行計數調整。核心是將計數從原先的直接數量統計調整為可接詞數量的統計。具體的計算方法如下:
這里的
表明對于 語料中的直接計數,表明調整后的計數。當n=N或者 為<s>時不需要調整計數;對于其他情況,需要將計數調整為 之前可接詞的數量。所以調整后計數的結果為:
| unigram | adjust count | reason |
| <s> | 5 | w1 = <s>, a = c = 5 |
| 傳統 | 1 | | {<s>, 傳統} | = 1 |
| 語言 | 1 | | {<s>, 語言} | = 1 |
| 模型 | 2 | | {<s>, 模型}, {語言, 模型} | = 2 |
| </s> | 3 | | {模型, </s>}, {傳統, </s>}, {語言, </s>} | = 3 |
| bigram | adjust count | reason |
| <s> 模型 | 2 | n = N, a = c =2 |
| <s> 語言 | 2 | n = N, a = c =2 |
| <s> 傳統 | 1 | n = N, a = c =1 |
| 語言 模型 | 1 | n = N, a = c =1 |
| 模型 </s> | 3 | n = N, a = c =3 |
| 傳統 </s> | 1 | n = N, a = c =1 |
| 語言 </s> | 1 | n = N, a = c =1 |
3. 計數打折
計數打折的思想為:對于出現頻率較高的ngram減少一點對最終的概率影響不會很大,可將其加到那些未出現的ngram上;對于出現頻率較低的ngram則不能減少。
具體根據Chen and Goodman提出的打折公式進行計算
這里的
表示出現了k次的ngram個數,這里的| t_{n,k} (n=1,2; k=1,2,3,4) | value | reason |
| t_{1,1} | 2 | n=1, |a(語言) , a(傳統) | = 2 |
| t_{1,2} | 1 | n=1, |a(模型) | = 1 |
| t_{1,3} | 1 | n=1, |a(</s>)| = 1 |
| t_{1,4} | 0 | n=1, 不存在a為4的unigram |
| t_{2,1} | 4 | n = 2, |a({<s>, 傳統}), a({語言, 模型}), a({傳統, </s>}), a({語言, </s>})| = 4 |
| t_{2,2} | 2 | n = 2, |a({<s>, 模型}), a({<s>, 語言})| = 2 |
| t_{2,3} | 1 | n = 2, |a({模型, </s>})| = 1 |
| t_{2,4} | 0 | n=2, 不存在a為4的bigram |
| D_{n,k} | value |
| D_{1}(1) | 1/2 |
| D_{1}(2) | 1/2 |
| D_{1}(3) | 3 |
| D_{1}(4) | 3 |
| D_{2}(1) | 1/2 |
| D_{2}(2) | 5/4 |
| D_{2}(3) | 3 |
| D_{2}(4) | 3 |
4. 計算偽概率
偽概率的計算公式如下:
可以看到,分子如果沒有減去
這項就是最基礎的用概率估計頻率,減去這個折扣項蘊含的思想是”劫富濟貧“,即對那些出現次數較多的 n-gram 減少對應的次數,之后加到未出現的 n-gram 上面。| unigram | u value | reason |
| <s> | 2/7 | a = 5, D_{1}(5) = 3, a(傳統) + a(語言) + a(模型) + a(</s>) = 7(5-3) / 7 = 2/7 |
| 傳統 | 1/14 | a = 1, D_{1}(1) = 1/2 (1-1/2)/7 = 1/14 |
| 語言 | 1/14 | a = 1, D_{1}(1) = 1/2 (1-1/2)/7 = 1/14 |
| 模型 | 3/14 | a = 2, D_{1}(2). = 1/2 (2-1/2)/7 = 3/14 |
| </s> | 0 | a =3, D_{1}(3) = 3 (3-3) / 7 = 0 |
| bigram | u value | reason |
| <s> 模型 | 3/20 | a = 2, D_{2}(2) = 5/4, a({<s> 模型}) + a({<s> 語言}) + a({<s> 傳統}) = 5(2-5/4)/5 = 3/20 |
| <s> 語言 | 3/20 | a = 2, D_{2}(2) = 5/4 (2-5/4)/5 = 3/20 |
| <s> 傳統 | 1/10 | a = 1, D_{2}(1) = 1/2 (1-1/2)/5 = 1/10 |
| 語言 模型 | 1/4 | a = 1, D_{2}(1) = 1/2 a({語言 模型}) + a({語言 </s>}) = 2(1-1/2) / 2 = 1/4 |
| 模型 </s> | 0 | a = 3, D_{2}(3) = 3 a({模型 </s>}) = 3(3-3) / 3 = 0 |
| 傳統 </s> | 1/2 | a = 1, D_{2}(1) = 1/2 a({模型 </s>}) = 1(1-1/2)/1 = 1/2 |
| 語言 </s> | 1/4 | a = 1, D_{2}(1) = 1/2 a({語言 </s> }) + a({語言 模型}) = 2(1-1/2)/2= 1/4 |
注意,當n=1時,計算
不考慮<s>, 因為<s>之前不可能再接入詞5. 回退值計算
定義回退值為接詞的能力,具體回退值的計算公式如下:
| unigram | backoff value | reason |
| <s> | 3/5 | (1/2*1 + 5/4 * 2 + 3 * 0) / 5= 3/5 |
| 傳統 | 1/2 | (1/2*1 + 5/4*0 + 3*0) / 1 = 1/2 |
| 語言 | 1/2 | (1/2*2 + 5/4 *0 + 3*0) / 2 = 1/2 |
| 模型 | 1 | (1/2*0 + 5/4 *0 + 3*1) / 3 = 1 |
| </s> | 0 | 0 |
注意</s>后面不可能接新詞,所以backoff為0
6. 差值計算
差值的計算可根據遞推公式:
根據此遞推公式一定會遞歸到unigram,而unigram可直接由以下公式進行計算
這里的
為空字符串,即可以認為是 ,所以回退值可計算為:首先計算unigram插值后的概率值,注意對于<s>的概率直接置為0
| unigram | p | reason |
| <s> | 0 | 0 |
| 傳統 | 1/5 | 1/14 + 9/14 * (1/5) = 14/70 |
| 語言 | 1/5 | 1/14 + 9/14 * (1/5) = 14/70 |
| 模型 | 12/35 | 3/14 + 9/14 * (1/5) = 24/70 |
| </s> | 9/70 | 0 + 9/14 * (1/5) = 9/70 |
| <unk> | 9/70 | 0 + 9/14 * (1/5) = 9/70 |
再根據遞推公式,進一步計算bigram插值后的概率值
| bigram | p | reason |
| <s> 模型 | 249/700 | 3/20 + 3/5 * 24/70 = 249/700 |
| <s> 語言 | 27/100 | 3/20 + 3/5 * 1/5 = 27/100 |
| <s> 傳統 | 11/50 | 1/10 + 3/5 * 1/5 = 11/50 |
| 語言 模型 | 59/140 | 1/4 + 1/2 * 24/70 = 59/140 |
| 模型 </s> | 9/70 | 0 + 1 * 9/70 = 9/70 |
| 傳統 </s> | 79/140 | 1/2 + 1/2 * 9/70 = 79/140 |
| 語言 </s> | 11/35 | 1/4 + 1/2 * 9/70 = 11/35 |
7. 生成語言模型
整理上文中計算的概率以及backoff,并計算log10
| unigram | p | log10 p | backoff | log10 backoff |
| <s> | 0 | 0 | 3/5 | -0.221849 |
| 傳統 | 1/5 | -0.698970 | 1/2 | -0.301030 |
| 語言 | 1/5 | -0.698970 | 1/2 | -0.301030 |
| 模型 | 12/35 | -0.464887 | 1 | 0 |
| </s> | 9/70 | -0.890856 | 0 | 0 |
| <unk> | 9/70 | -0.890856 | 0 | 0 |
| bigram | p | log10 p | ||
| <s> 模型 | 249/700 | -0.448899 | ||
| <s> 語言 | 27/100 | -0.568636 | ||
| <s> 傳統 | 11/50 | -0.657577 | ||
| 語言 模型 | 59/140 | -0.375276 | ||
| 模型 </s> | 9/70 | -0.890856 | ||
| 傳統 </s> | 79/140 | -0.248501 | ||
| 語言 </s> | 11/35 | -0.502675 |
進一步整理成arpa格式, 可以發現與之前kenlm計算的結果一致
\data\ ngram 1=6 ngram 2=7\1-grams: -0.890856 <unk> 0 0 <s> -0.22184873 -0.69896996 傳統 -0.30103 -0.69896996 語言 -0.30103 -0.46488678 模型 0 -0.89085555 </s> 0 -0.890856 <unk> 0\2-grams: -0.24850096 傳統 </s> -0.44889864 <s> 模型 -0.56863624 <s> 語言 -0.6575773 <s> 傳統 -0.37527603 語言 模型 -0.89085555 模型 </s> -0.50267535 語言 </s>\end\參考文獻
Scalable Modified Kneser-Ney Language Model Estimation: https://aclanthology.org/P13-2121.pdf
AI教室:傳統語言模型+KenLM 實現
總結
以上是生活随笔為你收集整理的手算KN-based ngram语言模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020电脑蓝屏代码大全
- 下一篇: BUGKU-CTF入门笔记