统计中文分词(最大熵)

来源:互联网 发布:coc法师塔升级数据 编辑:程序博客网 时间:2024/05/02 02:47

在机器学习中,序列标注(Sequence labeling)是一种常见的模式识别任务,它用来给一组可观察对象打上状态(类别)标签。它可以解决NLP中的分词(Word Segement)、词性标注(Part-Of-Speech Tagging)、命名实体识别(Named Entity Recognition )等问题。常见的概率统计模型有:HMM、MEMM、CRF。
下面介绍利用最大熵统计算法进行分词的步骤。

第一步:工具包开发环境搭建

下载MEMM工具包,这里利用的是张乐博士最大熵模型工具包,参照里面的INSTALL步骤安装,同时,参照python文件夹的README安装python相关的包(Python extension of the C++ Maximum Entropy Modeling Toolkit)。

第二步:准备语料

这里利用的是SIGHAN提供的backoff 2005语料,将熟语料转换成工具包所需格式,即4-tag(BMES)格式。可参考52NLP网站的python代码。

第三步:训练模型

工具包的example目录自带了一个python训练工具。执行:

 ./postrainer.py tagger.model -f train.data --iters 100

(注意迭代次数iters前面是两个-号)。

第四步:利用模型执行分词

利用上步得到的tagger.model执行分词。首先,准备所需语料,把生语料进行原子切分,如:“扬帆远东做与中国合作的先行”切分成“扬 帆 远 东 做 与 中 国 合 作 的 先 行”。执行最大熵标注脚本即可得到字标注结果,得到的格式如下:“扬/B 帆/M 远/M 东/M 做/E 与/S 中/B 国/E 合/B 作/E 的/S 先/B 行/E “,最后利用python程序合并成分词结果文件,如:“扬帆远东做 与 中国 合作 的 先行”。

第五步:评测

利用backoff2005的测试脚本来测分词的效果:

    === SUMMARY:=== TOTAL INSERTIONS:   5456=== TOTAL DELETIONS:    4439=== TOTAL SUBSTITUTIONS:    12205=== TOTAL NCHANGE:  22100=== TOTAL TRUE WORD COUNT:  106873=== TOTAL TEST WORD COUNT:  107890=== TOTAL TRUE WORDS RECALL:    0.844=== TOTAL TEST WORDS PRECISION: 0.836=== F MEASURE:  0.840=== OOV Rate:   0.026=== OOV Recall Rate:    0.565=== IV Recall Rate: 0.852

可以看到召回率是84.4%,准确率是83.6%,不是很高,这和语料规模有关。

详情可参考52NLP的网站文章,在character_2_word.py第16行增加if(len(line.strip())>0):判断,防止最终分词结果出现空行,否则这样score打分脚本会报错。

    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()        
0 0
原创粉丝点击