一、背景
近期研究了一下语言模型,同事推荐了一个比较好用的工具包kenlm,记录下使用过程。
二、使用kenlm训练 n-gram
1.工具介绍:http://kheafield.com/code/kenlm/
2.工具包的下载地址:http://kheafield.com/code/kenlm.tar.gz
3.解压后运行,./bjam 进行编译
4.使用如下命令进行训练:bin/lmplz -o 5 --verbose_header --text data/chat_log.txt --arpa result/log.arpa --vocab_file result/log.vocab
备注:4.1 文件必须是分词以后的文件。
4.2 -o后面的5表示的是5-gram,一般取到3即可,但可以结合自己实际情况判断。
三、使用kenlm判断一句话概率
使用kenlm主要就是对arpa文件内容的运行,下面解析下该文件的内容。
1.arpa文件
1-grams: -6.5514092 <unk> 0 0 <s> -2.9842114 -1.8586434 </s> 0 -2.88382 ! -2.38764 -2.94351 world -0.514311 -2.94351 hello -0.514311 -6.09691 guys -0.15553 2-grams: -3.91009 world ! -0.351469 -3.91257 hello world -0.24 -3.87582 hello guys -0.0312 3-grams: -0.00108858 hello world ! -0.000271867 , hi hello ! end
1.1 介绍该文件需要引入一个新的概念,back_pro. 超详细的介绍见 --> http://blog.csdn.net/visionfans/article/details/50131397
三个字段分别是:Pro word back_pro (注:arpa文件中给出的数值都是以10为底取对数后的结果)
1.2 需要特别介绍三个特殊字符。<s>、</s>和<unk>
一看便知,<s>和</s>结对使用,模型在计算概率时对每句话都进行了处理,将该对标记加在一句话的起始和结尾。这样就把开头和结尾的位置信息也考虑进来。
如“我 喜欢 吃 苹果” --> "<s> 我 喜欢 吃 苹果 </s>"。
<unk>表示unknown的词语,对于oov的单词可以用它的值进行替换。
2.n-gram概率计算
2.1 一元组w1
直接在arpa文件中查找,如果有则直接返回它的pro,否则返回<unk>的pro。
2.2 二元组w1w2
直接在arpa文件中查找,有则直接返回它的pro,否则返回back_pro(w1)*pro(w2)的结果。当然此处都去过log,直接加减即可。
2.3 三元组w1w2w3
这个说起来比较麻烦,画个图。
其中有一点大家可能会比较疑惑。为什么文件中存在二元组w1w2,要输出 back_pro(w1w2)*pro(w2w3),而没有w1w2,则可以直接输出pro(w2w3)。因为直观理解,有w1w2出现,概率pro(w1w2w3)的数值应该更大些。其实此处是用pro(w2w3)来近似代替pro(w1w2w3)的值。
我在arpa文件中选了前2000个一元组的pro和back_pro画出下图,由图我们可知,一个单词或者词组的pro和back_pro是负相关的。所以当二元组w1w2没有出现时,我们认为pro(w1w2)的特别小,相应地back_pro的值就会变大,而取完log以后的结果就为0,在加法中可以直接忽略该项。
3. sentence pro计算
句子的计算就不需我多说了,一般情况下都只用到三元组。
4.衡量指标
4.1 衡量的指标暂时只考虑了困惑度(perplexity),定义如下:
取完对数后计算超级方便,对数运算真乃利器也!!!