中文分词模型之最大熵模型

中文分词模型之最大熵

学习自然语言处理的相关模型,一直觉得云里雾里。看了好久的《统计学习方法》,也依然无所进益。看了很多博客,也没有具体的,正确率较高分词的实现细节。于是,决定从实际的例子入手,由具体到抽象。于是选取了中文分词任务作为最大熵模型的一个例子。学习最大熵模型之前,先了解一下统计模型处理分词任务的标准方法——字标注法。

 

基于字标注法的分词思想

字标注法是依据汉字在词中的位置,对每个汉字标注一个符号。最简单的是2-tag标注法,该方法将词的第一个字标注为B,其他的字标注为I。比如“汉字”这个词进行标注即为“汉/B 字/I”。同理,对于已经分好词的文本:

迈向  充满  希望  的  新  世纪  ——  一九九八年  新年  讲话  (  附  图片  1  张  )

使用2-tag标注为:

迈/B  向/I  充/B  满/I  希/B  望/I  的/B  新/B  世/B  纪/I  —/B  —/I  一/B  九/I  九/I  八/I  年/I  新/B  年/I  讲/B  话/I  (/B  附/B  图/B  片/I  1/B  张/B  )/B

 

除了2-tag标注法,还有4-tag标注法、6-tag标注法。最常用的是4-tag标注法。4-tag标注法将单字标注为S,词的第一个字标注为B,词的最后一个字标注为E,词中间的字标注为M。

比如,对已经分好词的文本:

迈向  充满  希望  的  新  世纪  ——  一九九八年  新年  讲话  (  附  图片  1  张  )

使用4-tag标注为为:

迈/B  向/E  充/B  满/E  希/B  望/E  的/S  新/S  世/B  纪/E  —/B  —/E  一/B  九/M  九/M  八/M  年/E  新/B  年/E  讲/B  话/E  (/S  附/S  图/B  片/E  1/S  张/S  )/S

 

对于未分词的文本,我们的任务就是通过已经分好词的文本,也称为训练集来训练一个数学模型。然后基于该模型为文本中每一个字标注一个tag。这实际上就是为每个字符分类。

 

比如有文本“自然语言处理是很高端的技术”,经过模型为每个字符标注tag后,文本变成“自/B然/E语/B言/E处/B理/E是/S很/S高/B端E的/S技/B术E”。通过4-tag中各个标签的意义,很自然地我们得到分词结果“自然  语言  处理 是  很  高端 的  技术”

 

分词的具体步骤

我们参考论文《maximumentropy chinese word segmentation》来完成分词任务。

第一步,下载工具包源码(openNLP)

由于是初学最大熵模型,我们直接使用工具包,而不自己编码。一则减少学习的难度,而则快速对最大熵模型建立感性的认知。当然最主要的原因是论文用它。

第二步,下载分词的语料(SIGHAN提供的backoff 2005语料)

选择该语料是因为众多论文都用它,很权威。

第三步,对训练集语料进行预处理,处理成满足模型需求的格式。

训练集语料原始格式如下(icwb2-data/training/pku_training.utf8):

迈向  充满  希望  的  新  世纪  ——  一九九八年  新年  讲话  (  附  图片  1  张  )

中共中央  总书记  、  国家  主席  江  泽民

(  一九九七年  十二月  三十一日  )

12月  31日  ,  中共中央  总书记  、  国家  主席  江  泽民  发表  1998年  新年  讲话  《  迈向  充满  希望  的  新  世纪  》  。  (  新华社  记者  兰  红光  摄  )

同胞  们  、  朋友  们  、  女士  们  、  先生  们  :

 

像上面训练集的文本用4-tag标注后,如下:

迈/B  向/E  充/B  满/E  希/B  望/E  的/S  新/S  世/B  纪/E  —/B  —/E  一/B  九/M  九/M  八/M  年/E  新/B  年/E  讲/B  话/E  (/S  附/S  图/B  片/E  1/S  张/S  )/S

中/B  共/M  中/M  央/E  总/B  书/M  记/E  、/S  国/B  家/E  主/B  席/E  江/S  泽/B  民/E

(/S  一/B  九/M  九/M  七/M  年/E  十/B  二/M  月/E  三/B  十/M  一/M  日/E  )/S

1/B  2/M  月/E  3/B  1/M  日/E  ,/S  中/B  共/M  中/M  央/E  总/B  书/M  记/E  、/S  国/B  家/E  主/B  席/E  江/S  泽/B  民/E  发/B  表/E  1/B  9/M  9/M  8/M  年/E  新/B  年/E  讲/B  话/E  《/S  迈/B  向/E  充/B  满/E  希/B  望/E  的/S  新/S  世/B  纪/E  》/S  。/S  (/S  新/B  华/M  社/E  记/B  者/E  兰/S  红/B  光/E  摄/S  )/S

同/B  胞/E  们/S  、/S  朋/B  友/E  们/S  、/S  女/B  士/E  们/S  、/S  先/B  生/E  们/S  :/S

 

然而,openNLP支持的格式并非上面的格式,因此,需要对4-tag法标注后的文本进行处理,使之满足openNLP的训练集输入格式要求。可能有人会问,我怎么知道openNLP的训练集格式是怎么样的? 前面下载了openNLP的源码,在源码包中,就有答案。

在apache-opennlp-1.5.3-src\opennlp-maxent\samples\sports目录中,有如下的文件:

 

wKiom1S8VynTSI1DAAHRETQbdnE553.jpg

从上图的样例中就可以看到训练集的格式。

 

接下来就需要提取特征项了。在论文《maximum entropy chinese word segmentation》中,定义了一些特征模板,

wKioL1S8V_vSsqHSAAC3GL05uHk345.jpg

这些特征是什么意思呢?举个简单的例子:假如我们对文本“迈向充满希望的新世纪”的第3个字“充”进行特征提取,其结果如下:

C-2=迈 C-1=向 C0=充 C1=满 C2=希

C-2C-1=迈向 C-1C0=向充  C0C1=充满 C1C2=满希

C-1C1=向满

Pu=NO

TC=4444

关于特征具体的解释说明见论文《maximum entropychinese word segmentation》

这些特征项结合标注标签就形成了一条训练样本:

C-2=迈  C-1=向 C0=充 C1=满 C2=希C-2C-1=迈向 C-1C0=向充 C0C1=充满 C1C2=满希C-1C1=向满Pu=NO  TC=4444  B

对训练集中的每个字进行上述的处理,就形成了符合openNLP格式的最大熵模型训练集。部分数据截图如下:

wKiom1S8Vyqw6_RoAAMYF1mN9SI323.jpg

训练集的处理是用Python写的脚本。相关的脚本可以在

https://github.com/shgy/chinese-segmenter/tree/master/maxent/scripts

中看到。

 

第四步,创建JavaProject,然后用openNLP工具对模型进行训练。

准备好训练集后,就可以训练模型了。训练参考apache-opennlp-1.5.3-src\opennlp-maxent\samples\sports目录中的CreateModel.java源码。相关的Java项目参看:

https://github.com/shgy/chinese-segmenter/tree/master/maxent

需要注意的是,我用的是GIS算法 cutoff=2 ,迭代200次。(没有调优,随机设置的两个值)

1
model = GIS.trainModel(es,200,2,USE_SMOOTHING,true);

第五步,使用训练好的模型对测试集进行分词,将分词结果保存到文件中。最后的分词结果示例如下:

(选自icwb2-data\testing\pku_test.utf8)

共同 创造 美好 的 新 世纪 —— 二○○一 年 新年 贺词

( 二○○○年 十二月 三十一日 ) ( 附 图片 1 张 )

女士 们 , 先生 们 , 同志 们 , 朋友 们 :

 

第六步,使用backoff2005的测试脚本进行测试。

关于backoff2005的测试脚本如何在windows系统中使用,请参考我的另一篇博客:http://sbp810050504.blog.51cto.com/2799422/1600586

测试的结果如下:

开放测试:

=== TOTAL TRUE WORDS RECALL:       0.902

=== TOTAL TEST WORDS PRECISION:   0.908

=== F MEASURE:       0.905

=== OOV Rate:     0.058

=== OOV Recall Rate:   0.705

=== IV Recall Rate:      0.914

###  pku_open_results.utf8    2638       3284       6898       12820     104372    103726    0.902      0.908      0.905      0.058       0.705      0.914

封闭测试

=== TOTAL TRUE WORDS RECALL:       0.973

=== TOTAL TEST WORDS PRECISION:   0.946

=== F MEASURE:       0.959

=== OOV Rate:     0.000

=== OOV Recall Rate:   —

=== IV Recall Rate:      0.973

###  pku_closed_results.utf8  32341     5     29470     61816     1109947  1142283  0.973      0.946      0.959      0.000      —       0.973

可以看到,正确率都在90%以上。当然这与论文中达到的正确率还有很大的差距,但是并没有添加论文中的两个特征。例子也仅供学习参考,并不求达到最好的结果,毕竟中文分词目前最好的模型是CRFs。

总结:用最大熵模型进行分类,其核心点在于依赖当前字符的上下文特征,计算该字符属于每个类别(B/S/E/M)的概率分布,然后选择分布概率最大的那个类别作为当前字符的类别。这从形式上与朴素贝叶斯是一样的。对于最大熵模型而言,个人觉得特征的选择在具体问题中比算法本身更为重要。所谓Garbage In,Garbage Out正是这个道理。

本文并没有探讨最大熵的原理,就像人学习骑自行车一样,首先能骑即可,而不是要了解自行车的机械原理。有了感性的认知后,再了解信息论、概率论、高数等数学基础后,再看《统计学习方法》,就应该比较容易地看懂公式原理了。但是最重要的是能够实现出来,毕竟“Talk is cheap. Show me the code.”

相关代码可以参考https://github.com/shgy/chinese-segmenter/tree/master/maxent

发表评论

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