按照用MeCab打造自己的分词器(一)操作,已经安装好了MeCab。
接下来安装指定方式组织语料、词典和配置文件,打造自己的分词系统。
利用backoff2005中微软研究院的中文分词语料来训练一个简单的分词系统,逐步深入完成我们的总目标。
当前目录为$WordSeg,下载微软的语料到当前目录下,解压,并创建msr_mecab_test目录。
~/Project/WordSeg$ ls
icwb2-data icwb2-data.zip msr_mecab_test
icwb2-data目录下有如下文件:
~/Project/WordSeg/icwb2-data$ ls
doc gold README scripts testing training
其中training目录中存放了训练语料,gold中存放了词典文件
~/Project/WordSeg/icwb2-data/training$ ls
as_training.b5 cityu_training.txt msr_training.txt pku_training.txt
as_training.utf8 cityu_training.utf8 msr_training.utf8 pku_training.utf8
~/Project/WordSeg/icwb2-data/gold$ ls
as_testing_gold.txt cityu_test_gold.txt msr_test_gold.txt pku_test_gold.txt
as_testing_gold.utf8 cityu_test_gold.utf8 msr_test_gold.utf8 pku_test_gold.utf8
as_training_words.txt cityu_training_words.txt msr_training_words.txt pku_training_words.txt
as_training_words.utf8 cityu_training_words.utf8 msr_training_words.utf8 pku_training_words.utf8
通过这两个语料可以创建MeCab需要的词典和训练语料,构建我们的模型。还需要配置文件,比如指定特征函数模板、未登录的处理方式等等。
在msr_mecab_test目录下,分别建立三个子目录:seed, final, script:
mkdir seed
mkdir final
mkdir script
~/Project/WordSeg/msr_mecab_test$ ls
final script seed
切换进入seed目录。
1、将icwb2-data中提供的词典,转换成MeCab格式。
1123项,0,0,0,0,0,0
义演,0,0,0,0,0,0
佳酿,0,0,0,0,0,0
沿街,0,0,0,0,0,0
老理,0,0,0,0,0,0
三四十岁,0,0,0,0,0,0
解波,0,0,0,0,0,0
统建,0,0,0,0,0,0
蓓蕾,0,0,0,0,0,0
李佑生,0,0,0,0,0,0
它的每一行包括七项特征,详细后表。如果只是分词功能,后面六项都置零就可以了。
2、准备配置文件
在seed目录下准备5个最基础的配置文件,分别是dicrc, char.def, unk.def, rewrite.def, feature.def。
1) dicrc: 该文件中设定词典的各种动作的,以下为最小配置:
cost-factor = 800
bos-feature = BOS/EOS,*,*,*,*,*,*,*,*
eval-size = 6
unk-eval-size = 4
config-charset = UTF-8
2) char.def: 定义未登陆词处理的文件. 通常日语的词法分析是基于字符的种类处理未登陆词, Mecab 中哪个文字属于哪个字符种类, 用户可以进行细致的指定; 对于每个字符类别, 需要采用哪种未登陆词的识别处理,也可以进行详细的定义。
DEFAULT 0 1 0 # DEFAULT is a mandatory category!
SPACE 0 1 0
CJK 0 0 2
# SPACE
0x0020 SPACE # DO NOT REMOVE THIS LINE, 0x0020 is reserved for SPACE
0x00D0 SPACE
0x0009 SPACE
0x000B SPACE
0x000A SPACE
3) unk.def: 用于未登陆词的词典。
DEFAULT,0,0,0,unk,*,*
SPACE,0,0,0,unk,*,*
CJK,0,0,0,unk,*,*
4) rewrite.def: 定义从特征列到内部状态特征列的转换映射。[unigram rewrite]
*,*,* $1,$2,$3
[left rewrite]
*,*,* $1,$2,$3
[right rewrite]
*,*,* $1,$2,$3
5) feature.def: 该文件中定义了从内部状态的素生列中抽取CRF的素生列的模板
UNIGRAM W0:%F[6]
UNIGRAM W1:%F[0]/%F[6]
UNIGRAM W2:%F[0],%F?[1]/%F[6]
UNIGRAM W3:%F[0],%F[1],%F?[2]/%F[6]
UNIGRAM W4:%F[0],%F[1],%F[2],%F?[3]/%F[6]
UNIGRAM T0:%t
UNIGRAM T1:%F[0]/%t
UNIGRAM T2:%F[0],%F?[1]/%t
UNIGRAM T3:%F[0],%F[1],%F?[2]/%t
UNIGRAM T4:%F[0],%F[1],%F[2],%F?[3]/%t
BIGRAM B00:%L[0]/%R[0]
BIGRAM B01:%L[0],%L?[1]/%R[0]
BIGRAM B02:%L[0]/%R[0],%R?[1]
BIGRAM B03:%L[0]/%R[0],%R[1],%R?[2]
BIGRAM B04:%L[0],%L?[1]/%R[0],%R[1],%R?[2]
BIGRAM B05:%L[0]/%R[0],%R[1],%R[2],%R?[3]
BIGRAM B06:%L[0],%L?[1]/%R[0],%R[1],%R[2],%R?[3]
3、准备训练语料
msr提供的语料格式是这样的:
人们 常 说 生活 是 一 部 教科书 , 而 血 与 火 的 战争 更 是 不可多得 的 教科书 , 她 确实 是 名副其实 的 ‘ 我 的 大学 ’ 。
“ 心 静 渐 知 春 似 海 , 花 深 每 觉 影 生 香 。
“ 吃 屎 的 东西 , 连 一 捆 麦 也 铡 不 动 呀 ?
他 “ 严格要求 自己 , 从 一个 科举 出身 的 进士 成为 一个 伟大 的 民主主义 者 , 进而 成为 一 位 杰出 的 党外 共产主义 战士 , 献身 于 崇高 的 共产主义 事业 。
分词用空格隔开,而MeCab的训练语料和它的词典格式非常相似,每行行首是一个词,然后用tab键隔开,后跟词相关的特征比如词性、发音等等。我们只有分词功能,后面都置零就可以。
人们 0,0,0,0,0,0
常 0,0,0,0,0,0
说 0,0,0,0,0,0
生活 0,0,0,0,0,0
是 0,0,0,0,0,0
一 0,0,0,0,0,0
部 0,0,0,0,0,0
教科书 0,0,0,0,0,0
, 0,0,0,0,0,0
而 0,0,0,0,0,0
血 0,0,0,0,0,0
与 0,0,0,0,0,0
火 0,0,0,0,0,0
的 0,0,0,0,0,0
战争 0,0,0,0,0,0
更 0,0,0,0,0,0
是 0,0,0,0,0,0
不可多得 0,0,0,0,0,0
的 0,0,0,0,0,0
教科书 0,0,0,0,0,0
, 0,0,0,0,0,0
她 0,0,0,0,0,0
确实 0,0,0,0,0,0
是 0,0,0,0,0,0
seed目录下多了两个文件分别是corpus、和msr_words.csv
到目前为止,我们需要训练用的词典,配置文件及训练语料已准备就绪:
seed 词典(CSV 格式文件集合)
所有的配置文件 (char.def, unk.def, rewrite.def, feature.def)
训练用的数据 (文件名: corpus)
4、生成训练用的二进制词典
在seed目录下运行以下命令, 生成学习用的二进制词典:
/usr/local/libexec/mecab/mecab-dict-index
也可以通过 -d, -o 选项指定输入输出目录来运行该命令
/usr/local/libexec/mecab/mecab-dict-index -d \$WORK/seed -o \$WORK/seed
-d: 包含seed 词典和配置文件的目录(缺省为当前目录)
-o: 训练用二进制词典的输出目录(缺省为当前目录)
5、CRF模型参数训练
在seed目录下执行如下命令,训练CRF模型:
/usr/local/libexec/mecab/mecab-cost-train -c 1.0 corpus model
可以使用 -d 参数指定使用的词典
/usr/local/libexec/mecab/mecab-cost-train -d \$WORK/seed -c 1.0 \$WORK/seed/corpus \$WORK/seed/model
-d: 包含训练用二进制词典的目录(缺省为当前目录)
-c: CRF的超参数(hyper-parameter)
-f: 特征频率的阈值
-p NUM: 实行NUM个并行训练 (缺省为1)
corpus: 训练数据文件名
model: 输出CRF参数文件名
这个训练过程需要一会儿时间,最终的输出大致如下:
adding virtual node: 0,0,0,0,0,0
adding virtual node: 0,0,0,0,0,0
adding virtual node: 0,0,0,0,0,0
adding virtual node: 0,0,0,0,0,0
...
Number of sentences: 86918
Number of features: 28
eta: 0.00005
freq: 1
eval-size: 6
unk-eval-size: 4
threads: 1
charset: EUC-JP
C(sigma^2): 1.00000
iter=0 err=0.29595 F=0.94870 target=2267078.26396 diff=1.00000
iter=1 err=0.13623 F=0.97665 target=1056367.13470 diff=0.53404
iter=2 err=0.13849 F=0.97610 target=1005496.50043 diff=0.04816
iter=3 err=0.14630 F=0.97388 target=924449.25300 diff=0.08060
iter=4 err=0.13693 F=0.97643 target=891815.15638 diff=0.03530
iter=5 err=0.13537 F=0.97672 target=869032.52748 diff=0.02555
iter=6 err=0.11850 F=0.98127 target=854787.02218 diff=0.01639
iter=7 err=0.10803 F=0.98411 target=845031.70611 diff=0.01141
iter=8 err=0.08712 F=0.98848 target=838863.46990 diff=0.00730
iter=9 err=0.07940 F=0.99001 target=835481.49751 diff=0.00403
iter=10 err=0.07276 F=0.99114 target=833719.13204 diff=0.00211
iter=11 err=0.06556 F=0.99263 target=833462.32905 diff=0.00031
iter=12 err=0.06569 F=0.99258 target=831886.20533 diff=0.00189
iter=13 err=0.06568 F=0.99259 target=831739.11465 diff=0.00018
iter=14 err=0.06559 F=0.99262 target=831643.59710 diff=0.00011
iter=15 err=0.06531 F=0.99266 target=831599.69205 diff=0.00005
iter=16 err=0.06502 F=0.99274 target=831544.40251 diff=0.00007
iter=17 err=0.06480 F=0.99279 target=831518.14668 diff=0.00003
iter=18 err=0.06475 F=0.99280 target=831504.33361 diff=0.00002
iter=19 err=0.06470 F=0.99281 target=831502.92263 diff=0.00000
Done! writing model file ...
6、生成用于发布的词典
在seed目录下执行:
/usr/local/libexec/mecab/mecab-dict-gen -o ../final -m model
model is not a binary model. reopen it as text mode...
reading ./unk.def ... 3
reading ./msr_words.csv ... 88119
emitting ../final/left-id.def/ ../final/right-id.def
emitting ../final/unk.def ... 3
emitting ../final/msr_words.csv ... 88119
emitting matrix : 100% |###########################################|
emitting matrix : 133% |########################################### copying ./char.def to ../final/char.def
copying ./rewrite.def to ../final/rewrite.def
copying ./dicrc to ../final/dicrc
copying ./feature.def to ../final/feature.def
copying model to ../final/model.def
done!
也可以使用 -d -o 选项指定词典
/usr/local/libexec/mecab/mecab-dict-gen -o \$WORK/final -d \$WORK/seed -m \$WORK/seed/model
-d: 包含seed 词典和配置文件的目录(缺省为当前目录)
-o: 用于发布的词典的输出目录
-m: CRF 的参数文件
用于发布的词典, 必须输出到和 seed 词典不同的目录,通常把包含发布词典的 final 目录打包之后用于发布 .
7、生成用于解析器的词典
进入到final目录下
cd ../final
执行
/usr/local/libexec/mecab/mecab-dict-index
reading ./unk.def ... 3
emitting double-array: 100% |###########################################|
./pos-id.def is not found. minimum setting is used
reading ./msr_words.csv ... 88119
emitting double-array: 100% |###########################################|
reading ./matrix.def ... 3x3
emitting matrix : 100% |###########################################|
done!
也可以使用 -d -o 选项指定词典
usr/local/libexec/mecab/mecab-dict-index -d \$WORK/final -o \$WORK/final
-d: 包含seed 词典和配置文件的目录(缺省为当前目录)
-o: 用于解析器的二进制词典的输出目录(缺省为当前目录)
至此,MeCab中文分词所需的词典和模型文件准备就绪,都在final目录下,可以测试一下,回到上一层目录(cd ..),然后执行
/WordSeg/msr_mecab_test$ mecab -d ./final/
请介绍信托基金的情况
请 0,0,0
介绍信 0,0,0
托 0,0,0
基金 0,0,0
的 0,0,0
情况 0,0,0
EOS
输出的结果。看到它把“信托”分开了。信托基金是金融领域的常用词。可见语料和词典中没有覆盖金融领域词。这也是为什么要有自己的分词系统的缘故。