1.kenlm在python中的使用过程
import kenlm
model = kenlm.language("tri_gram_language_model.arpa")
score = model.score("银行 放贷 行为")
print(score)
---------------------------------
>>> -7.153961658477783
score = model.score("银行 放待 行为")
print(score)
----------------------------------
>>> -11.517741203308105
上述代码几个要点:
(1)tri_gram_language_model.arpa为训练好的n-gram语言模型,此处是我自己利用一个很小的文本训练出来的3-gram语言模型,模型文件内容如下,因为我这里训练的是3-gram语言模型,所以模型文件中,分别对应1-gram、2-gram及3-gram的模型参数。
图1
(2)模型文件参数说明,以1-gram中的“-4.405105 中广网 -0.07266096”作为说明,数字“-4.405105”可以看成是“中广网”这个词出现的概率,然后取10为底的对数得到,即lg(p(中广网))=-4.405105,数字“ -0.07266096”为回退概率(back probability),在计算2-gram的未登录词会用到它,这里不用太过关注,需要额外了解的,可以参考这篇博文图解N-gram语言模型的原理。值得说明的是,对于3-gram中的参数,没有回退概率这样一项参数,这是因为本模型最多是3-gram,而回退概率是在计算4-gram才会用到,所以3-gram参数中不需要这一列。
(3)model.score("银行 放贷 行为")返回结果表示“银行 放贷 行为”这句话是人话的概率,也就是说返回分数越高,这句话就越像人话,分数越低,这句话就越不像人话,也就是越不符合我们日常的表达;从上面例子可以看到“银行 放贷 行为”比“银行 放待 行为”更符合人话
(4)model.score() 传入句子时,不同词语之间需要用空格隔开(即分词后的句子)
2.kenlm概率的具体计算过程
(1)语言模型概率——链式法则回顾
计算一个句子(w1,w2,w3,w4,w5)的概率可以用下式表示:
通过马尔科夫假设,将上述计算转化为3-gram模型,也就是计算某一个单词概率时,只依赖前面的2个词语,具体公式如下:
(2)kenlm实际上就是通过上述模型进行计算(以计算“银行 放贷 行为”这句话概率为例)
- 首先在句子前后添加<s>和</s>标记,最终需要计算的句子为['<s>', "银行", "放贷", "行为", "</s>"]
- 然后根据模型参数计算句子概率:p(<s> 银行 放贷 行为 </s>)=p(<s>)p(银行|<s>)p(放贷|<s> 银行)p(行为|银行 放贷)p(</s>|放贷 行为)
- 因为对于所有句子p(<s>)相同,上述可以转化为p(<s> 银行 放贷 行为 </s>)=p(银行|<s>)p(放贷|<s> 银行)p(行为|银行 放贷)p(</s>|放贷 行为)
- 然后在模型文件中查找对应的概率参数计算即可,p(<s> 银行 放贷 行为 </s>)=-2.662721-2.953046-0.702558-0.835635=-7.15396
- 读到这里你可能会有疑问,这些参数是怎么来的,如果有未登录词该怎么办?请接着往下看
(3)条件概率计算规则
- 一元组w1,即p(w1)
直接在arpa文件中查找,如果有则直接返回它的pro(图1中第一列参数),否则返回<unk>的pro(图1中第一列参数)。
- 二元组w1w2,即p(w2|w1)
直接在arpa文件中查找,有则直接返回它的pro,否则返回back_pro(w1) + pro(w2)的结果。back_pro为图2中第一列参数
- 三元组w1w2w3,即p(w3|w1,w2)
这个稍微复杂,具体参照下图
(4)具体计算过程
计算可能用到的n-gram参数如下:
pro n-gram back-pro
-4.540702 <unk> 0
0 <s> -0.39536887
-2.7043288 银行 -0.15291257
-4.247026 放贷 -0.07266093
-3.3257697 行为 -0.18192981
-1.4688878 </s> 0
-2.662721 <s> 银行 -0.0610168
-2.8920295 银行 放贷 -0.0610168
-1.1110907 放贷 行为 -0.0610168
-0.77461904 行为 </s> 0
-0.7025586 银行 放贷 行为
p(<s> 银行 放贷 行为 </s>)=p(银行|<s>)p(放贷|<s> 银行)p(行为|银行 放贷)p(</s>|放贷 行为)
p(银行|<s>) = -2.662721
p(放贷|<s> 银行) = -0.0610168-2.8920295 = -2.953046 (因为"<s> 银行 放贷"三元组参数不存在,最终结果等于back_pro("<s> 银行") + pro("银行 放贷"))
p(行为|银行 放贷) = -0.7025558
p(</s>|放贷 行为) = -0.0610168-0.77461904= -0.835635 (因为"放贷 行为 </s>"三元组参数不存在,最终结果等于back_pro("放贷 行为") + pro("行为 </s>"))
最终结果为 -2.662721 - 2.953046 - 0.7025558 - 0.835635 = - 7.15396