10秒開發(fā)一個基于字的3-gram的拼音輸入法:魔改sunpinyin
apt source libsunpinyin3v5 下載到當前目錄下。
src/sunpinyin-dictgen是個有shebang的Makefile:
#!/usr/bin/make -f
W3M = wget -q -O -
DL_LIST = https://sourceforge.net/projects/open-gram/files/
DL_HOST = https://jaist.dl.sourceforge.net
DL_ROOT = ${DL_HOST}/open-gram
DICT_PAT = 'dict\.utf8-[0-9]\+.tar.bz2'
SLM_PAT = 'lm_sc\.3gm\.arpa-[0-9]\+.tar.bz2'
DICT_AR = $(shell ${W3M} ${DL_LIST} | grep -o ${DICT_PAT} | sort -u | tail -n 1)
光腚make為了求變量DICT_AR的值也要聯(lián)網(wǎng),雖然比Android Studio快得多,我還是不喜歡。
此版本下載dict.utf8就夠了。
寫個小爛Python程序可從dict.utf8提取字,得到如下文件:
<unknown> 0 <unknown_cn> 2 <amigu> 9 <stok> 10 <Digit> 20 <Simbol> 21 <NONEWORD_ALLWORD> 69 , 70 。 71 ; 72 ? 73 ! 74 : 75 “ 76 ” 77 、 78 … 79 ? 100 qiu ... 袏 26753 zuo 阼 26754 zuo
注意調(diào)整ID連續(xù)。while 1: input(),用<輸入,split(), ' '.join(fields)...
語料用的《錦醫(yī)衛(wèi)》。
$ mmseg -d dict.utf8 corpus >ids
$ ids2ngram -n 3 -s /dev/shm/swap -o 3gram -p 1024000 ids # 用內(nèi)存盤
$ slmbuild -l -n 3 -o all.slm -w 26700 -c 0,3,2 -d GT,8,0.9995 -d ABS -d ABS -b 10,11,12 -e 9 3gram
照抄光腚slmbuild的Example改了下文件名。
$ slmthread all.slm lm_sc.t3g
這步是必須的,因為它要浮點轉(zhuǎn)整數(shù)等,online部分不接受all.slm,雖然不crash,但候選字的順序都亂了。
Compressing pr values...13530 float values ==> 13530 values
Compressing bow values...17422 float values ==> 16384 values
Threading the new model...slmthread: src/slm/thread/slmthread.cpp:383: int main(int, char**): Assertion `bowit != bow_map.end()' failed.
已放棄
不放棄,改程序。:-)
// assert(bowit != bow_map.end()); if (bowit == bow_map.end()) { cerr << "val=" << val << endl; for (bowit = bow_map.begin(); bowit != bow_map.end(); ++bowit) if (fabs(bowit->first - val) < 1e4) break; assert(bowit != bow_map.end()); }
map<float, int>里查不到。作者預(yù)見了,注釋里有// precision error,但沒預(yù)見到這種情況。cerr...后代碼為新增。沒幾個,一點不慢。
slmprune不是必須的,我們的模型小。
$ genpyt -i dict.utf -o pydict_sc.bin -l log -s all.slm -e le
Opening language model...done! Writing out...done! Printing the lexicon out to log_file...段錯誤
啊啊啊!最后一步啦!!原來是字典文件名輸入錯了。輸入錯LM文件名則:
Opening language model... open al.slm: 沒有那個文件或目錄 error!
然后換數(shù)據(jù)文件。建個符號鏈接 data -> /usr/lib/x86_64-linux-gnu/sunpinyin/data/ 不然敲得太煩了。
先備份原先的,不過就算壞了,可:apt reinstall sunpinyin-data
雖然mmseg.cpp里setlocale(LC_ALL, ""); 含義是用當前l(fā)ocale;但portability.cpp里MBSTOWCS里寫死了iconv_open("UCS-4LE", "UTF-8"); 補充:還有fgetwc, setvbuf下?
語料其實是head -n 10000的1.7MB. 模型:915K lm_sc.t3g 449K pydict_sc.bin
雖然是字,但可是tri-gram啊。張紫萱、葛哨官……都有。
本帖使用上述小模型和用戶辭典輸入。〔鏈接1〕〔鏈接2〕〔鏈接3〕


在Intel N100上,12M語料訓(xùn)練秒級,100M語料(wiki_zh/AA)訓(xùn)練分鐘級。整句輸入效果不太好,“蹦詞”可以。
模型小不了,數(shù)據(jù)太稠密了:16000**3受不了。【改:可增加cutoff,小模型依然可用,token量大時太小的模型無用】【110MB字3-gram模型輸入這些話很爽】
〔語料1〕〔語料2〕語料1刪掉空格后45M,訓(xùn)練不到半分鐘。
用高頻短詞+字應(yīng)該效果更好。蒼蠅拍打蒼蠅比高射炮好。這算不算種更針對領(lǐng)域,效果更好的平滑算法?
google拼音:48,068詞, 41,442 二三字詞,哈哈哈 哦哦哦都是詞。
輸入zhang zi xuan,出來長子縣。漢典:縣 xuan 同 “懸” —— 名人寫別字不算別字?!
mmseg不允許一個詞有多個讀音,正在試驗系統(tǒng)詞典和分詞詞典不同:[成功]
要是公安部把身份證上的人名和住址都dump出來當語料,就好了。分成兩個文件亂下序,好象也沒啥隱私問題。還有工商名錄。
RIME (中州韻)是個開源的輸入法引擎,有多種平臺下的前端(client),Windows下的叫Weasel (小狼毫)。
pydict_sc.bin: lm_sc.t3g genpyt -e le -i sunzi -s $< -l /t/pydict_sc.log -o $@ lm_sc.t3g: all.slm slmthread $^ $@ all.slm: 3gram slmbuild -l -n 3 -o $@ -w 26700 -c 0,3,2 -d GT,8,0.9995 -d ABS -d ABS -b 10,11,12 -e 9 $< 3gram: mmseg -d sunzi jinyiwei >ids ids2ngram -n 3 -s /t/swap -o $@ -p 1024000 ids rm ids install: mv lm_sc.t3g data mv pydict_sc.bin data clean: rm -f ids 3gram all.slm

浙公網(wǎng)安備 33010602011771號