用MeCab打造一套实用的中文分词系统(四):MeCab增量更新

Deep Learning Specialization on Coursera

最近在处理NLPJob的一些数据,发现之前训练的Mecab中文分词工具包还有一些问题,所以想到了为NLPJob定制一个MeCab中文分词器,最简单的方法就是整理一批相关的词条,可以通过词条追加的方法加到原有的Mecab中文分词词典中去,这个可以参考《日文分词器Mecab文档》中介绍的“词条追加”方法,既可以放到系统词典中,也可以放到用户词典中,很方便。不过这个还不是最佳方案,之前有用户在《用MeCab打造一套实用的中文分词系统》中留言:

你好, 我在win7上训练的时候mecab-cost-train的时候会崩溃,请问下我能每次只训练一小部分,然后最后一起发布嘛?

google了一下,发现MeCab的作者Taku Kudo在google plus上给了一个增量更新的方案:

https://plus.google.com/107334123935896432800/posts/3g83gkBoSYE

当然这篇文章是用日文写得,不过如果熟悉Mecab的相关脚本,很容易看懂。增量更新除了可以解决在小内存机器上分批训练模型外,也可以很容易在一个已有的基准分词模型上定制特定领域的分词器,既更新词典,也更新模型,这才是我理想中NLPJob中文分词器的定制之路。

按照这条路子,我预处理了一下NLPJob中的数据,包括提取和校正了公司名,在已有的Mecab-Chinese中文工具包的基础上,手工标记一批NLPJob分词和词性标注数据,用于词条追加和模型训练。然后按照上面Mecab作者的文章指引,进行了一次MeCab-Chinese的定向(NLPJob)更新,效果还不错。以下是相关的中文记录,方便大家查看,文章的例子数据来源于手工标记的一小部分数据,仅供参考。

首先准备两份数据,一份是需要追加的词条,例如 nlpjob.dict:

明略数据/nt
大数据/n
挖掘/vn
工程师/n
美团/nt
招聘/vn
机器/n
学习/vn
技术/n
专家/n
......

另一份手工校正过的分词和词性标注数据,例如 nlpjob.data:

【/w 明略数据/nt 】/w 大数据/n 挖掘/vn 工程师/n
美团/nt 招聘/vn 机器/n 学习/vn 技术/n 专家/n
美团/nt 招聘/vn 数据/n 挖掘/vn 技术/n 专家/n
【/w 微店/nt 北京/ns 社招/v 】/w 搜索/v 研发/j 工程师/n
融360/nt -/unk 互联网/n 金融/n 搜索/vn 服务/vn 平台/n 招聘/v 大数据/n 开发/vn 工程师/n
【/w c轮/n 图片/n 社交/n 】/w nice/nt -/w 数据/n 仓库/n 研发/j 工程师/n
【/w 微店/nt 北京/ns 社招/v 】/w 推荐/v 研发/j 工程师/n
【/w 微店/nt 北京/ns 社招/v 】/w 广告/n 系统/n 算法/n 研发/j 工程师/n
【/w 一点资讯/nt 社招/v 】/w 大数据/n 方向/n :/w 大数据/n 、/w 分布式/b 系统/n 高级/a 研发/j 工程师/n
【/w 一点资讯/nt 社招/v 】/w 后台/n 及/c 搜索/vn 方向/n :/w 后台/n 、/w 推送/v 后台/n 、/w 数据/n 抓取/v 处理/v
......

按照《用MeCab打造一套实用的中文分词系统(三):MeCab-Chinese》文中的介绍,我们在MeCab-Chinese-V0.2-Script目录下分别执行:

python make_mecab_seed_data.py nlpjob.dict nlpjob.csv
python make_mecab_train_data.py nlpjob.data nlpjob.train

分别得到两个用于Mecab训练用格式的词典(nlpjob.csv) 和训练句子文件(nlpjob.train),例如 nlpjob.csv:

明略数据,0,0,0,n,nt,BMME,4,明略数据,ming_lve_shu_ju,明略數據
大数据,0,0,0,n,n,BME,3,大数据,da_shu_ju,大數據
挖掘,0,0,0,v,vn,BE,2,挖掘,wa_jue,挖掘
工程师,0,0,0,n,n,BME,3,工程师,gong_cheng_shi,工程師
美团,0,0,0,n,nt,BE,2,美团,mei_tuan,美團
招聘,0,0,0,v,vn,BE,2,招聘,zhao_pin,招聘
机器,0,0,0,n,n,BE,2,机器,ji_qi,機器
学习,0,0,0,v,vn,BE,2,学习,xue_xi,學習
技术,0,0,0,n,n,BE,2,技术,ji_zhu,技術
专家,0,0,0,n,n,BE,2,专家,zhuan_jia,專家
......

例如nlpjob.train:

【 w,w,S,1,【,【,【
明略数据 n,nt,BMME,4,明略数据,ming_lve_shu_ju,明略數據
】 w,w,S,1,】,】,】
大数据 n,n,BME,3,大数据,da_shu_ju,大數據
挖掘 v,vn,BE,2,挖掘,wa_jue,挖掘
工程师 n,n,BME,3,工程师,gong_cheng_shi,工程師
EOS
美团 n,nt,BE,2,美团,mei_tuan,美團
招聘 v,vn,BE,2,招聘,zhao_pin,招聘
机器 n,n,BE,2,机器,ji_qi,機器
学习 v,vn,BE,2,学习,xue_xi,學習
技术 n,n,BE,2,技术,ji_zhu,技術
专家 n,n,BE,2,专家,zhuan_jia,專家
EOS
......

这里我们将上一期训练的Mecab中文处理工具包命名为mecab_chinese_data_v0.2,将nlpjob.csv和nlpjob.train拷贝进入这个目录,然后在上层目录执行如下命令,进行二进制词典的更新:

/usr/local/libexec/mecab/mecab-dict-index -f utf8 -t utf8 -d mecab_chinese_data_v0.2 -o mecab_chinese_data_v0.2

执行过程如下:

mecab_chinese_data_v0.2/pos-id.def is not found. minimum setting is used
reading mecab_chinese_data_v0.2/unk.def ... 11
emitting double-array: 100% |###########################################|
mecab_chinese_data_v0.2/pos-id.def is not found. minimum setting is used
reading mecab_chinese_data_v0.2/add.csv ... 9
reading mecab_chinese_data_v0.2/company_name.csv ... 678
reading mecab_chinese_data_v0.2/nlpjob.csv ... 203
reading mecab_chinese_data_v0.2/words.csv ... 1101507
emitting double-array: 100% |###########################################|
reading mecab_chinese_data_v0.2/matrix.def ... 272x272
emitting matrix : 100% |###########################################|

done!

然后执行如下命令在原有CRF模型的基础上基于新的训练数据训练新的模型参数:

/usr/local/libexec/mecab/mecab-cost-train -M mecab_chinese_data_v0.2/model.def -d mecab_chinese_data_v0.2 mecab_chinese_data_v0.2/nlpjob.train new_model

执行过程如下:

Using previous model: mecab_chinese_data_v0.2/model.def
--cost --freq and --eta options are overwritten.
reading corpus ...adding virtual node: u,unk,S,1,-,-,-
adding virtual node: u,unk,S,1,(,(,(
......
adding virtual node: u,unk,BE,2,】-,_,】-
100... 100...
Number of sentences: 100
Number of features: 5703547
eta: 0.00005
freq: 1
eval-size: 7
unk-eval-size: 4
threads: 1
charset: utf-8
C(sigma^2): 1.00000

iter=0 err=0.25000 F=0.97210 target=511.75767 diff=1.00000
iter=1 err=0.24000 F=0.96818 target=520.81646 diff=0.01770
iter=2 err=0.17000 F=0.97504 target=500.66250 diff=0.03870
iter=3 err=0.17000 F=0.97993 target=493.89725 diff=0.01351
iter=4 err=0.17000 F=0.98091 target=490.33833 diff=0.00721
iter=5 err=0.16000 F=0.98287 target=480.14951 diff=0.02078
iter=6 err=0.08000 F=0.99070 target=473.11797 diff=0.01464
iter=7 err=0.07000 F=0.99168 target=468.60587 diff=0.00954
iter=8 err=0.08000 F=0.99070 target=466.45814 diff=0.00458
iter=9 err=0.07000 F=0.99266 target=465.97983 diff=0.00103
iter=10 err=0.07000 F=0.99266 target=465.55008 diff=0.00092
iter=11 err=0.06000 F=0.99364 target=465.29456 diff=0.00055
iter=12 err=0.06000 F=0.99364 target=465.03189 diff=0.00056
iter=13 err=0.06000 F=0.99364 target=464.84768 diff=0.00040
iter=14 err=0.06000 F=0.99364 target=464.71818 diff=0.00028
iter=15 err=0.06000 F=0.99364 target=464.59071 diff=0.00027
iter=16 err=0.06000 F=0.99364 target=464.53703 diff=0.00012
iter=17 err=0.06000 F=0.99364 target=464.50074 diff=0.00008
iter=18 err=0.06000 F=0.99364 target=464.48284 diff=0.00004
iter=19 err=0.06000 F=0.99364 target=464.45312 diff=0.00006
iter=20 err=0.06000 F=0.99364 target=464.43718 diff=0.00003
iter=21 err=0.06000 F=0.99364 target=464.43268 diff=0.00001
iter=22 err=0.06000 F=0.99364 target=464.41177 diff=0.00005

Done! writing model file ...

接下来我们新建一个目录用于新的模型和词典数据发布:

mkdir mecab_chinese_data_v0.3

然后执行如下命令生成用于发布的词典:

/usr/local/libexec/mecab/mecab-dict-gen -d mecab_chinese_data_v0.2 -o mecab_chinese_data_v0.3 -m new_model

执行过程如下:

new_model is not a binary model. reopen it as text mode...
reading mecab_chinese_data_v0.2/unk.def ... 11
reading mecab_chinese_data_v0.2/add.csv ... 9
reading mecab_chinese_data_v0.2/company_name.csv ... 678
reading mecab_chinese_data_v0.2/nlpjob.csv ... 203
reading mecab_chinese_data_v0.2/words.csv ... 1101507
emitting mecab_chinese_data_v0.3/left-id.def/ mecab_chinese_data_v0.3/right-id.def
emitting mecab_chinese_data_v0.3/unk.def ... 11
emitting mecab_chinese_data_v0.3/add.csv ... 9
emitting mecab_chinese_data_v0.3/company_name.csv ... 678
emitting mecab_chinese_data_v0.3/nlpjob.csv ... 203
emitting mecab_chinese_data_v0.3/words.csv ... 1101507
emitting matrix : 100% |###########################################|
copying mecab_chinese_data_v0.2/char.def to mecab_chinese_data_v0.3/char.def
copying mecab_chinese_data_v0.2/rewrite.def to mecab_chinese_data_v0.3/rewrite.def
copying mecab_chinese_data_v0.2/dicrc to mecab_chinese_data_v0.3/dicrc
copying mecab_chinese_data_v0.2/feature.def to mecab_chinese_data_v0.3/feature.def
copying new_model to mecab_chinese_data_v0.3/model.def

done!

最后我们建一个最终用于发布的二进制词典和模型的目录;
mkdir mecab_chinese_data_binary_v0.3

执行如下命令生成相关的二进制文件:

/usr/local/libexec/mecab/mecab-dict-index -f utf8 -t utf8 -d mecab_chinese_data_v0.3 -o mecab_chinese_data_binary_v0.3
执行过程如下:

mecab_chinese_data_v0.3/pos-id.def is not found. minimum setting is used
reading mecab_chinese_data_v0.3/unk.def ... 11
emitting double-array: 100% |###########################################|
mecab_chinese_data_v0.3/pos-id.def is not found. minimum setting is used
reading mecab_chinese_data_v0.3/add.csv ... 9
reading mecab_chinese_data_v0.3/company_name.csv ... 678
reading mecab_chinese_data_v0.3/nlpjob.csv ... 203
reading mecab_chinese_data_v0.3/words.csv ... 1101507
emitting double-array: 100% |###########################################|
reading mecab_chinese_data_v0.3/matrix.def ... 275x275
emitting matrix : 100% |###########################################|

done!

注意在mecab_chinese_data_binary_v0.3目录下生成了5个二进制文件char.bin,matrix.bin,model.bin,sys.dic, unk.dic,但是还缺少一个dicrc方能使用,从mecab_chinese_data_v0.3下拷贝一个即可。这个时候,可以测试一下:

mecab -d mecab_chinese_data_binary_v0.3/
NLPJob关注“自然语言处理|机器学习|数据挖掘|搜索引擎|计算广告|推荐算法”等相关互联网领域的工作机会。
NLPJob n,nt,BMMMME,6,NLPJob,_____,NLPJob
关注 v,v,BE,2,关注,guan_zhu,關註
“ w,w,S,1,“,“,“
自然 a,a,BE,2,自然,zi_ran,自然
语言 n,n,BE,2,语言,yu_yan,語言
处理 v,v,BE,2,处理,chu_li,處理
| unk,unk,*,*,*,*,*
机器 n,n,BE,2,机器,ji_qi,機器
学习 v,v,BE,2,学习,xue_xi,學習
| unk,unk,*,*,*,*,*
数据 n,n,BE,2,数据,shu_ju,數據
挖掘 v,v,BE,2,挖掘,wa_jue,挖掘
| unk,unk,*,*,*,*,*
搜索引擎 n,n,BMME,4,搜索引擎,sou_suo_yin_qing,搜索引擎
| unk,unk,*,*,*,*,*
计算 v,v,BE,2,计算,ji_suan,計算
广告 n,n,BE,2,广告,guang_gao,廣告
| unk,unk,*,*,*,*,*
推荐 v,v,BE,2,推荐,tui_jian,推薦
算法 n,n,BE,2,算法,suan_fa,算法
” w,w,S,1,”,”,”
等 u,u,S,1,等,deng,等
相关 v,vn,BE,2,相关,xiang_guan,相關
互联网 n,n,BME,3,互联网,hu_lian_wang,互聯網
领域 n,n,BE,2,领域,ling_yu,領域
的 u,u,S,1,的,de,的
工作 v,vn,BE,2,工作,gong_zuo,工作
机会 n,n,BE,2,机会,ji_hui,機會
。 w,w,S,1,。,。,。
EOS

感兴趣的同学也可以在我们的demo上试用一下这个版本的效果:MeCab中文分词Demo

mecab_chinese_data_binary_v0.3 的压缩包已上传到了百度网盘,感兴趣的同学可以下载直接使用: 链接: http://pan.baidu.com/s/1sjFXflF 密码: 62dk

最后也更新了MeCab-Chinese的相关说明,感兴趣的同学可以关注。

注:原创文章,转载请注明出处“我爱自然语言处理”:www.52nlp.cn

本文链接地址:http://www.52nlp.cn/?p=8660

Deep Learning Specialization on Coursera

用MeCab打造一套实用的中文分词系统(四):MeCab增量更新》上有27条评论

  1. youxi.xie

    你好!看的文章真是让人受益匪浅。请教下有没有推荐的开源的语音分析的工具?

    [回复]

    52nlp 回复:

    抱歉,这个不太清楚

    [回复]

  2. jason

    nlpjob.data 文件是纯手工标注么?是否有生成规则可自动化?

    [回复]

    52nlp 回复:

    再上一个版本的分词和标注基础上进行校正,事实上工作量不大

    [回复]

  3. Jarvis

    求问博主,你的model.bin能直接拿来用吗,我在训练那步报错


    Using previous model: mecab_chinese_data_v0.2/model.bin
    --cost --freq and --eta options are overwritten.
    feature_index.cpp(635) [tokenize2(buf.get(), ":", column, 2) == 2] format error: {W

    feature.def什么的都是git上seed里面的

    [回复]

    52nlp 回复:

    binary的model貌似不行,是发布用的版本

    [回复]

  4. frqc

    你好!谢谢你的文章
    我想咨询的是 带词性标注的语料库 和 新加入的词汇数之间的比例该多少合适呢?
    当然语料库越多训练越准确,但考虑到需要手动分词(需要分析特定领域的文章,也就需要特定领域的词汇,也就需要特定领域的训练语料库),一般取多少合适呢?

    [回复]

    52nlp 回复:

    这个没有定量

    [回复]

    frqc 回复:

    那下线1:1?

    [回复]

    frqc 回复:

    如果要强行加100%确定的词,该怎么加呢?

    52nlp 回复:

    100%确定的词就加入词典吧

  5. abbychau

    你好, 看到把mecab 轉為中文使用還有更新, 實在十分高興。
    很感謝博主的貢獻。

    請問mecab-chinese 對比起friso 的優劣可以對比一下嗎?

    [回复]

    52nlp 回复:

    抱歉,不清楚friso,貌似google也没有相关信息,或许你可以给个链接

    [回复]

    abbychau 回复:

    是這個: https://code.google.com/archive/p/friso/

    (m/groonga port: https://github.com/kenhys/groonga-tokenizer-friso

    [回复]

  6. derek

    训练的预料,含有/号。这个mecab如何区分?

    [回复]

    52nlp 回复:

    区分的话是由你来指定的吧?mecab都一视同仁。你再预处理的时候可以用类似“|”来做区分标记,不用"/"这个就可以了,然后以”|“为分割标记来准备mecab的训练文件格式。

    [回复]

    derek 回复:

    谢谢。
    如语料中,出现类似29,964/m金额的词组。生成的训练格式是这个:
    29,964,0,0,0,m,m,BMMMME,6,29,964,_____,29,964
    这样训练是会出错的。

    可以这样来拆分:
    1. 29/m ,/x 964/m
    2. 29964/m

    这个要如何标注呢?

    [回复]

    52nlp 回复:

    你需要修改一下脚本,把这个看做一个整体即可,或者预处理的时候把反斜杠替换掉,或者生成训练格式的时候不要以反斜杠作为分隔符

  7. Kevin

    非常感谢博主提供的这个平台可以交流学习NLP。对mecab很有兴趣,打算读一下它的代码。但是不太会C++,很痛苦。

    有个疑问请教一下,model.bin在分词的时候是不是用不上? 因为粗略的看了一下在code里面在分词的时候好像都没有导入model.bin,只导入了matrix.bin。我尝试把model.bin删除之后完全没有影响。

    [回复]

    52nlp 回复:

    model才是核心文件,你确定删除model.bin能运行成功?

    [回复]

    Kevin Chen 回复:

    是的,model.bin删掉了还是能运行。

    [回复]

    52nlp 回复:

    抱歉,最近重新review了一下相关文档,确实在分词的时候不需要model相关文件

  8. ylnlp

    您好,再次打扰。我在增量更新二进制字典时,出现了这个问题
    feature_index.cpp(563) [decode_charset(model_charset.c_str()) == decode_charset(from.c_str())] dictionary charset and model charset are different. dictionary_charset=utf8 model_charset=EUC-JP
    似乎是mecab自带的model编码与字典编码不匹配?但是model不应该是我们之前训练好的中文model吗?

    [回复]

    ylnlp 回复:

    更改了model.def里面的model_charset好像是可以了。但是训练的时候疯狂出现
    feature_index.cpp(281) [rewrite_.rewrite2(path->rnode->feature, &ufeature2, &lfeature2, &rfeature2)] cannot rewrite pattern: 0,0,0

    learner_tagger.cpp(84) [size == 2] format error:
    这两个报错,是我的新增train数据有问题吗?还是太大了?

    [回复]

发表评论

电子邮件地址不会被公开。 必填项已用*标注