为啥slmbuild的cutoff不能设得很大

在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;

先别急着训练。

setvbuf应能加快读取速度。The getwc() function or macro functions identically to fgetwc(). 我这里gcc -E表明 getwc() 也是函数。

这一堆编码转换函数速度不快啊,大部分时间转换编码有点岂有此理。

字的n-gram,token ID不超过65536,可以输出uint_16而不是uint_32.

mmseg输出到stdout,用管道送给ids2ngram可取消中间文件。文件名为-时代表输出到stdout和从stdin读是标准做法。mmseg原本就输出到stdout,ids2ngram则不肯从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/* 一句话搞定。


哦,可见当时语料小,舍不得cut off. 如今我计划bigram 1000以下,trigram 10万以下都扔掉 (名为3元实则2元)。

整完了报告下:freq.dat 480M chmod a-w; chattr +i 可不敢再覆盖了。

  我记得设了noclobber的啊。如今得set -o noclobber了,不带-o不报错没效果, set noclobberxx也不报错。

slmbuild -w 16563 -c 100,100,100 -d ABS -d ABS -d ABS

lm_sc.t3g 5.8M; Total 3 level ngram: 5,682 226,342 360,548  using -log(pr)

lm_sc.t3g.7z 最大压缩 3.1M

依然好用,最最起码鄙人的名字还在(确认不在系统和用户词典里)。

都cutoff 1万,10x KB的模型,cutoff 1000, 8xx KB.


我认为这样的词没必要放在系统词典里:二十世纪、欧美国家、欧洲国家、欧洲市场,因为它们是二字词+二字词。

国家质量监督检验检疫总局 和 喜羊羊与灰太狼之兔年顶呱呱 也没必要。

事实上,我有点飘了,计划系统词典里只放二字词和三字词,如果效果可以,过会上传。

https://chuna2.787528.xyz/funwithwords/p/19185425

posted @ 2025-11-02 18:14  华容道专家  阅读(6)  评论(0)    收藏  举报