自然语言处理系列十六》中文分词》分词工具实战》CRF++工具包实战

29 篇文章 1 订阅
16 篇文章 0 订阅

注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》(人工智能科学与技术丛书)【陈敬雷编著】【清华大学出版社】

自然语言处理系列十六

分词工具实战

分词工具有Java、Python、C++实现的,这里给大家推荐目前最流行的分词工具。CRF++是采用C++语言编写,但可以用Python来调用。HanLP是用Java编写的,也可以用Python调用。IK分词和mmseg4j分词也是用Java编写,经常集成在搜索引擎Solr和Elasticsearch里。下面分别进行讲解这几个开源分词包。

CRF++工具包实战

CRF++是著名的条件随机场的开源工具,也是目前综合性能最佳的CRF工具。
工具包:https://taku910.github.io/crfpp/#tips
语料:http://sighan.cs.uchicago.edu/bakeoff2005/
CRF++安装步骤如下:
#下载linux版本CRF++包-----CRF+±0.58.tar.gz,并解压。
#cd CRF+±0.58

#./configure
#sudo make
#sudo make install

若出现ImportError: libcrfpp.so.0: cannot open shared object file: No such file or directory 。
解决方法: ln -s /usr/local/lib/libcrfpp.so.0 /usr/lib/。

1.第一步:准备训练语料
将backoff2005里的训练数据转化为CRF++所需的训练数据格式,采用4-tag( B(Begin,词首), E(End,词尾), M(Middle,词中), S(Single,单字词))标记集,处理utf-8编码文本。 原始训练集/icwb2-data/training/msr_training.utf8的形式是人工分好词的中文句子形式。如下:

“ 人们 常 说 生活 是 一 部 教科书 , 而 血 与 火 的 战争 > 更 是 不可多得 的 教科书 , 她 确实 是 名副其实 的 ‘ 我 的 > 大学 ’ 。
“ 心 静 渐 知 春 似 海 , 花 深 每 觉 影 生 香 。
“ 吃 屎 的 东西 , 连 一 捆 麦 也 铡 不 动 呀 ?
他 “ 严格要求 自己 , 从 一个 科举 出身 的 进士 成为 一个 伟> 大 的 民主主义 者 , 进而 成为 一 位 杰出 的 党外 共产主义 战 士 , 献身 于 崇高 的 共产主义 事业 。
“ 征 而 未 用 的 耕地 和 有 收益 的 土地 , 不准 荒芜 。
“ 这 首先 是 个 民族 问题 , 民族 的 感情 问题 。
’ 我 扔 了 两颗 手榴弹 , 他 一下子 出 溜 下去 。
“ 废除 先前 存在 的 所有制 关系 , 并不是 共产主义 所 独具 的 特征 。
“ 这个 案子 从 始 至今 我们 都 没有 跟 法官 接触 过 , 也 > 没有 跟 原告 、 被告 接触 过 。
“ 你 只有 把 事情 做好 , 大伙 才 服 你 。

根据如下的脚本 make_crf_train.py,将这个训练语料转换为CRF++训练用的语料格式(2列,4-tag),代码如下所示:

import codecs  
import sys  
  
def character_tagging(input_file, output_file):  
    input_data = codecs.open(input_file, 'r', 'utf-8')  
    output_data = codecs.open(output_file, 'w', 'utf-8')  
    for line in input_data.readlines():  
        word_list = line.strip().split()  
        for word in word_list:  
            if len(word) == 1:  
                output_data.write(word + "\tS\n")  
            else:  
                output_data.write(word[0] + "\tB\n")  
                for w in word[1:len(word)-1]:  
                    output_data.write(w + "\tM\n")  
                output_data.write(word[len(word)-1] + "\tE\n")  
        output_data.write("\n")  
    input_data.close()  
output_data.close()

转化后如下:

“ S
人 B
们 E
常 S
说 S
生 B
活 E
是 S
一 S
部 S
教 B
科 M
书 E

2.第二步:训练模型
准备好训练语料,就可以利用crf的训练工具crf_learn来训练模型了,假设上述准备好的语料文件为:msr_training.tagging4crf.utf8

执行如下命令即可:

crf_learn -f 3 -c 4.0 ./template ./msr_training.tagging4crf.utf8 model   #执行此命令可以在安装文件外面新建一个文件夹进行,template是模板文件,model是训练完成后的model文件,只需要将模板,训练数据放到新建的文件夹里面,执行此命令就在当前文件夹下训练并生成了model文件。

有四个主要的参数可以调整:
-a CRF-L2 or CRF-L1
规范化算法选择。默认是CRF-L2。一般来说L2算法效果要比L1算法稍微好一点,虽然L1算法中非零特征的数值要比L2中大幅度的小。
-c float
这个参数设置CRF的hyper-parameter。c的数值越大,CRF拟合训练数据的程度越高。这个参数可以调整过度拟合和不拟合之间的平衡度。这个参数可以通过交叉验证等方法寻找较优的参数。
-f NUM
这个参数设置特征的cut-off threshold。CRF++使用训练数据中至少NUM次出现的特征。默认值为1。当使用CRF++到大规模数据时,只出现一次的特征可能会有几百万,这个选项就会在这样的情况下起到作用。
-p NUM
如果电脑有多个CPU,那么那么可以通过多线程提升训练速度。NUM是线程数量。
模板文件如下:
#Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-2,0]/%x[-1,0]/%x[0,0]
U06:%x[-1,0]/%x[0,0]/%x[1,0]
U07:%x[0,0]/%x[1,0]/%x[2,0]
U08:%x[-1,0]/%x[0,0]
U09:%x[0,0]/%x[1,0]
#Bigram
B

3.第三步:准备测试语料并进行测试
有了模型,现在我们需要做得还是准备一份CRF++用的测试语料,然后利用CRF++的测试工具crf_test进行字标注。原始的测试语料是icwb2-data/testing/msr_test.utf8 ,样例如下:

扬帆远东做与中国合作的先行
希腊的经济结构较特殊。
海运业雄踞全球之首,按吨位计占世界总数的17%。
另外旅游、侨汇也是经济收入的重要组成部分,制造业规模相对较小。
多年来,中希贸易始终处于较低的水平,希腊几乎没有在中国投资。
十几年来,改革开放的中国经济高速发展,远东在崛起。
瓦西里斯的船只中有40%驶向远东,每个月几乎都有两三条船停靠中国港口。
他感受到了中国经济发展的大潮。
他要与中国人合作。
他来到中国,成为第一个访华的大船主。

这里我们同样提供一个python脚本 make_crf_test.py 对测试语料进行处理,将其转换为CRF++要求的格式(2列,B作为最后一列的占位符)

import codecs  
import sys  
def character_split(input_file, output_file):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        for word in line.strip():
            word = word.strip()
            if word:
                output_data.write(word + "\tB\n")
    input_data.close()
output_data.close()

转化后如下(注意中间不要有空行,否则标注结果全部为S):

扬 B
帆 B
远 B
东 B
做 B
与 B
中 B
国 B

假设上述测试语料为msr_test4crf.utf8,执行crf_test即可得到字标注结果:
crf_test -m ./crf_model ./msr_test4crf.utf8 > msr_test4crf.tag.utf8
标注后样例如下:
扬 B B
帆 B E
远 B B
东 B E
做 B S
与 B S
中 B B
国 B E
合 B B
作 B E

4.第四步:将标注的词位信息转化为分词结果

import codecs
import sys
def character_2_word(input_file, output_file):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        if line == "\n":
            output_data.write("\n")
        else:
            char_tag_pair = line.strip().split('\t')
            char = char_tag_pair[0]
            tag = char_tag_pair[2]
            if tag == 'B':
                output_data.write(' ' + char)
            elif tag == 'M':
                output_data.write(char)
            elif tag == 'E':
                output_data.write(char + ' ')
            else: # tag == 'S'
                output_data.write(' ' + char + ' ')
    input_data.close()
    output_data.close()

转化后如下:

扬帆 远东 做 与 中国 合作 的 先行
希腊 的 经济 结构 较 特殊 。
海运 业 雄踞 全球 之 首 , 按 吨 位 计 占 世界 总数 的 17% 。
另外 旅游 、 侨汇 也是 经济 收入 的 重要 组成部分 , 制造业 规模 相对 较小 。
多年来 , 中 希 贸易 始终 处于 较低 的 水平 , 希腊 几乎 没有 在 中国 投资 。
十几年 来 , 改革开放 的 中国 经济 高速 发展 , 远东 在 崛起 。
瓦西里斯 的 船只 中 有 40% 驶 向 远东 , 每个 月 几乎 都 有 两三条 船 停靠 中国 港口 。
他 感受 到 了 中国 经济 发展 的 大潮 。
他 要 与 中国人 合作 。
他 来到 中国 , 成为 第一个 访 华 的 大船 主

最后:评估一下分词效果

有了这个CRF字标注分词结果,我们就可以利用backoff2005的测试脚本来测一下这次分词的效果了:
./icwb2-data/scripts/score ./icwb2-data/gold/msr_training_words.utf8 ./icwb2-data/gold/msr_test_gold.utf8 msr_test4crf.tag2word.utf8 > msr_crf_segment.score
结果如下:
=== SUMMARY:
=== TOTAL INSERTIONS: 1412
=== TOTAL DELETIONS: 1305
=== TOTAL SUBSTITUTIONS: 2449
=== TOTAL NCHANGE: 5166
=== TOTAL TRUE WORD COUNT: 106873
=== TOTAL TEST WORD COUNT: 106980
=== TOTAL TRUE WORDS RECALL: 0.965
=== TOTAL TEST WORDS PRECISION: 0.964
=== F MEASURE: 0.964
=== OOV Rate: 0.026
=== OOV Recall Rate: 0.647
=== IV Recall Rate: 0.974
###msr_test4crf.tag2word.utf8 1412 1305 2449 5166 106873 106980 0.965 0.964 0.964 0.026 0.647 0.974
这次我们获得了一个准确率,召回率以及F值都在96%以上的结果,相对于前面几节的测试结果,这个CRF字标注分词结果还相对不错。

上面测试阶段略微繁琐一些,下面程序直接输入测试语料然后直接输出分词结果:

import codecs  
import sys  
  
import CRFPP  
  
def crf_segmenter(input_file, output_file, tagger):  
    input_data = codecs.open(input_file, 'r', 'utf-8')  
    output_data = codecs.open(output_file, 'w', 'utf-8')  
    for line in input_data.readlines():  
        tagger.clear()  
        for word in line.strip():  
            word = word.strip()  
            if word:  
                tagger.add((word + "\to\tB").encode('utf-8'))  
        tagger.parse()  
        size = tagger.size()  
        xsize = tagger.xsize()  
        for i in range(0, size):  
            for j in range(0, xsize):  
                char = tagger.x(i, j).decode('utf-8')  
                tag = tagger.y2(i)  
                if tag == 'B':  
                    output_data.write(' ' + char)  
                elif tag == 'M':  
                    output_data.write(char)  
                elif tag == 'E':  
                    output_data.write(char + ' ')  
                else:  
                    output_data.write(' ' + char + ' ')  
        output_data.write('\n')  
    input_data.close()  
    output_data.close()  
  
if __name__ == '__main__':  
    if len(sys.argv) != 4:  
        print "Usage: python " + sys.argv[0] + " model input output"  
        sys.exit(-1)  
    crf_model = sys.argv[1]  
    input_file = sys.argv[2]  
    output_file = sys.argv[3]  
    tagger = CRFPP.Tagger("-m " + crf_model)  
crf_segmenter(input_file, output_file, tagger)

只需执行“python crf_segmenter.py crf_model ./icwb2-data/testing/msr_test.utf8 msr_test.seg.utf8”即可得到与前面几步得到的分词结果完全一致的CRF分词结果:msr_test.seg.utf8 。
接下来的自然语言处理系列十七将讲解Python的Jieba分词

总结

此文章有对应的配套视频,其它更多精彩文章请大家下载充电了么app,可获取千万免费好课和文章,配套新书教材请看陈敬雷新书:《分布式机器学习实战》(人工智能科学与技术丛书)

【新书介绍】
《分布式机器学习实战》(人工智能科学与技术丛书)【陈敬雷编著】【清华大学出版社】
新书特色:深入浅出,逐步讲解分布式机器学习的框架及应用配套个性化推荐算法系统、人脸识别、对话机器人等实战项目

【新书介绍视频】
分布式机器学习实战(人工智能科学与技术丛书)新书【陈敬雷】
视频特色:重点对新书进行介绍,最新前沿技术热点剖析,技术职业规划建议!听完此课你对人工智能领域将有一个崭新的技术视野!职业发展也将有更加清晰的认识!

【精品课程】
《分布式机器学习实战》大数据人工智能AI专家级精品课程

【免费体验视频】:
人工智能百万年薪成长路线/从Python到最新热点技术

从Python编程零基础小白入门到人工智能高级实战系列课

视频特色: 本系列专家级精品课有对应的配套书籍《分布式机器学习实战》,精品课和书籍可以互补式学习,彼此相互补充,大大提高了学习效率。本系列课和书籍是以分布式机器学习为主线,并对其依赖的大数据技术做了详细介绍,之后对目前主流的分布式机器学习框架和算法进行重点讲解,本系列课和书籍侧重实战,最后讲几个工业级的系统实战项目给大家。 课程核心内容有互联网公司大数据和人工智能那些事、大数据算法系统架构、大数据基础、Python编程、Java编程、Scala编程、Docker容器、Mahout分布式机器学习平台、Spark分布式机器学习平台、分布式深度学习框架和神经网络算法、自然语言处理算法、工业级完整系统实战(推荐算法系统实战、人脸识别实战、对话机器人实战)、就业/面试技巧/职业生涯规划/职业晋升指导等内容。

【充电了么公司介绍】

充电了么App是专注上班族职业培训充电学习的在线教育平台。

专注工作职业技能提升和学习,提高工作效率,带来经济效益!今天你充电了么?

充电了么官网
http://www.chongdianleme.com/

充电了么App官网下载地址
https://a.app.qq.com/o/simple.jsp?pkgname=com.charged.app

功能特色如下:

【全行业职位】 - 专注职场上班族职业技能提升

覆盖所有行业和职位,不管你是上班族,高管,还是创业都有你要学习的视频和文章。其中大数据智能AI、区块链、深度学习是互联网一线工业级的实战经验。

除了专业技能学习,还有通用职场技能,比如企业管理、股权激励和设计、职业生涯规划、社交礼仪、沟通技巧、演讲技巧、开会技巧、发邮件技巧、工作压力如何放松、人脉关系等等,全方位提高你的专业水平和整体素质。

【牛人课堂】 - 学习牛人的工作经验

1.智能个性化引擎:

海量视频课程,覆盖所有行业、所有职位,通过不同行业职位的技能词偏好挖掘分析,智能匹配你目前职位最感兴趣的技能学习课程。

2.听课全网搜索

输入关键词搜索海量视频课程,应有尽有,总有适合你的课程。

3.听课播放详情

视频播放详情,除了播放当前视频,更有相关视频课程和文章阅读,对某个技能知识点强化,让你轻松成为某个领域的资深专家。

【精品阅读】 - 技能文章兴趣阅读

1.个性化阅读引擎:

千万级文章阅读,覆盖所有行业、所有职位,通过不同行业职位的技能词偏好挖掘分析,智能匹配你目前职位最感兴趣的技能学习文章。

2.阅读全网搜索

输入关键词搜索海量文章阅读,应有尽有,总有你感兴趣的技能学习文章。

【机器人老师】 - 个人提升趣味学习

基于搜索引擎和智能深度学习训练,为您打造更懂你的机器人老师,用自然语言和机器人老师聊天学习,寓教于乐,高效学习,快乐人生。

【精短课程】 - 高效学习知识

海量精短牛人课程,满足你的时间碎片化学习,快速提高某个技能知识点。

上一篇:自然语言处理系列十五》中文分词》机器学习统计分词》CRF分词
下一篇:自然语言处理系列十七》中文分词》分词工具实战》Python的Jieba分词

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈敬雷-充电了么-CEO兼CTO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值