在sim_slmbuilder.cpp的CSlmBuilder::AddNGram里:
if (fr > cut[nlevel]) {TLeafLevel& v = *(TLeafLevel*)(level[nlevel]);v.push_back(TLeaf(ngram[nlevel - 1], fr)); } else {nr[nlevel][0] += fr;nr[nlevel][fr] += fr; }
相关代码:
FREQ_TYPE(*nr)[SLM_MAX_R]; //nr[1][SLM_MAX_R] is for 1-gram... typedef unsigned int FREQ_TYPE; typedef CSIMSlm::FREQ_TYPE FREQ_TYPE; static const int SLM_MAX_R = 16; nr = new FREQ_TYPE[n + 1][SLM_MAX_R];还有: typedef unsigned int TWCHAR; typedef TWCHAR TSIMWordId;
先别急着训练。
mmseg用fgetwc()读文件。getwc是fgetwc的宏版,应该更快。setvbuf也能加快读取速度。
字的n-gram,token ID不超过65536,可以输出uint_16而不是uint_32.
mmseg输出到stdout,用管道送给ids2ngram可取消中间文件。文件名为-时代表输出到stdout和从stdin读是标准做法。
所有的程序都没有开-O,-O2总该试一试吧。
比如语料是五个句号。。。。。 。的token id是71 (0x47). mmseg把每行看作一个句子,在最前和最后面插入了<stok>,其id为10 (0x0a)
mmseg再id2ngram后,得到一串uint_32,下面只显示它的最低字节并换了行:
0a 47 47 01
47 47 0a 01
47 47 47 03
01 02 03是频次。
slminfo可以把语言模型以文本文件模式导出。"thread"好像是sunpinyin独有的说法。tslminfo处理被slmthread加工过了的。
省事的方法是重新训练,瞎鼓捣已有的语言模型,动不动触发assert.
1.6GB的百科问答,8G内存的电脑的内存盘,就带不动了(尚未试验mmseg | ids2ngram).
上次的wiki_zh,是分目录处理再merge的,百科问答是一个大文件,wiki_zh是[a..m]×99个文件。
Linux命令行可以很长,wiki_zh/a/* 一句话搞定。