上周五看了下语言模型相关的工具,之前也打算自己造轮子,发现还是不行,别人开源了就用别人的,其中c++版本比较典型的就是kenlm,这个工具号称单机版训练超级快,经过测试确实很快,支持大规模的语料训练,文件的输入格式一行行以空格隔开的文本,跟word2vev模型训练输入的格式一样,当然c++接口踩过的坑真的是特别多,网上的资料少的可伶,一路摸索,不过python的接口相对来说超级简单。下面看下怎么安装以及使用吧:
1.去boost官网下载最新版的boost:http://www.boost.org/
./bootstrap.sh
./b2 install
2.wget http://tukaani.org/xz/xz-5.2.2.tar.gz
tar xzvf xz-5.2.2.tar.gz
cd xz-5.2.2
./configure
make
make install
3.wget http://zlib.net/zlib-1.2.8.tar.gz
tar xzf zlib-1.2.8.tar.gz
cd zlib-1.2.8
./configure
make
make install
4.wget http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar xzvf bzip2-1.0.6.tar.gz
cd bzip2-1.0.6/
make
make install
5.下载 http://kheafield.com/code/kenlm.tar.gz
cd kenlm
mkdir build
cd build
cmake ..
make
装上面 2 、3、4步骤主要是为了得到 下面三个动态文件,liblzma.dylib libbz2.dylib libz.dylib,我是在mac下面安装,linux对用是so文件,Windows对应的是dll文件,周末花了两天的时间就搞这个东西,这玩意最核心,最后在target_link_libraries下做链接使用,如果没有这几个动态文件,你程序根本编译不过,一路报错,最后kenlm模型生成了四个静态的文件分别是 libkelm.a等四个文件里面,在build/lib下面,安装就说到这里。
模型训练模型,执行文件在build/bin下面:
./lmplz -o 4 --verbose_header --text /Users/zhoumeixu/Downloads/text.txt --arpa model/log.arpa
./build_binary -s model/log.arpa model/log.bin
第一行生成一个.arpa文件,第二行把模型文件格式转换成bin的形式,用于在c++中加载概率模型
c++接口:
#include<iostream>
#include <set>
#include "lm/model.hh"
#include "lm/config.hh"
#include "util/tokenize_piece.hh"
#include "util/string_piece.hh"
#include "util/string_stream.hh"
using namespace std;
using namespace lm::ngram;
int main(int argc, char *argv[]) {
char *path = "/Users/zhoumeixu/Downloads/kenlm/build/bin/model/chinese.bin";
if (argc > 1) {
path = argv[1];
}
Config config;
config.load_method = util::READ;
Model model(path,config);
State state, out_state;
lm::FullScoreReturn ret;
float score;
const Vocabulary &vocab = model.GetVocabulary();
string line;
while (getline(cin, line)) {
state = model.BeginSentenceState();
score = 0;
for (util::TokenIter<util::SingleCharacter, true> it(line, ' '); it; ++it) {
lm::WordIndex vocab = model.GetVocabulary().Index(*it);
ret = model.FullScore(state, vocab, out_state);
score += ret.prob;
state = out_state;
}
ret = model.FullScore(state, model.GetVocabulary().EndSentence(), out_state);
score += ret.prob;
cout<<line.c_str()<<":"<<score<<"\n";
}
return 0;
}
运行之后看下效果,输出的分数是log10之后的结果,要返回概率直接用math.pow(10,xx)就可以得到:
一起 吃饭
一起 吃饭:-6.35668
哈哈
哈哈:-5.84506
python接口,安装按照githup中read.md提供的python安装方法既可以:
In [12]: import kenlm
In [13]: model=kenlm.Model("/Users/zhoumeixu/Downloads/kenlm/build/bin/model/chinese.bin")
In [14]: model.score('一起 吃饭',bos = True,eos = True)
Out[14]: -6.3566813468933105
c++和python结果一模一样,实际过程中碰到各种各样的坑,只是在这里没有把错误贴上来,尤其是c++的,记录一下.