MMSeg中文分词算法

Java中有一些开源的分词项目,比如:IK、Paoding、MMSEG4J等等。这里主要说的是MMSEG4J中使用的MMSeg算法。它的原文介绍在:http://technology.chtsai.org/mmseg/,是用英文书写的,这是只是它的一个中文笔记。
 
为什么中文要分词
中文和英文的书写方式不一样,英文中单词之间用空格隔开,而且每个单词代表一个含义(当然也有短语,但这占的比例不是主要的);中文的书写是连在一起的,而且单个单词常常与相邻的单词组合成一个词语,代表一个含义。比如:“中学校长”,不能像英文那样一个词一个划分,要划分为“中学”和“校长”两个词。如果我们的书写习惯是每个词语用空格分隔,那就像英文一样不用分了。
 
 
一、划分规则
把查询语句划分为3个word组成的chunk,每个word中存放一个词语,这个词语是字典中出现的一个字或词组(多个字),对于剩下未划分的子语句可以再使用这个规则划分。
为什么chunk由3个word组成,而不是其它数值?
也许是汉语句子基本结构是主谓宾3部分,而不划为更多个的word,却是在程序准确性与性能之间做一个折中。
例如“眼看就要来了”或以分为以下几种chunk
1、眼看    就要 来了
2、眼看 就要 来
3、眼看 就 要
4、眼 看 就要
5、眼 看 就
 
二、过滤规则
从上面的划分可见,有多个chunk,为了选出唯一一个chunk,分别用四个规则过滤它们,当然如果在某个过滤规则中已经让chunk剩存一个,就退出后继的过滤筛选。反之,如果使用了4个规则,仍然剩存1个以上的chunk,就抛出异常。这4个规则分别是:最大匹配、最大平均单词长度、单词长度最小方差和单字单词语素自由度的最大和。
 
2.1、最大匹配
把3个word中的单词个数相加,取总单词长度最长的chunk。
上面第一个chunk单词长度为6,所以取它。
 
2.2、最大平均单词长度
就是chunk中单词总数除以word个数,如:
1、国际化
2、国际 化
3、国 际 化
这三个chunk的平均单词长度都是1.
 
 
 
2.3、最小单词长度方差
先回忆一下什么是方差?
方差就是各数据与样本平均数的差的平方和的平均数,公式:
[1/(n-1)][(x1-s)^2+(x2-s)^2+...+(xn-s)^2],其中的s为标准值。
方差用于衡量x1~xn群体与s之间的偏离程度,方差越小表明x1~xn群体与s越聚集。当x1~xn都等于s时,方差的值为0,表明它们聚焦在一个点。
 
比如有以下两个chunk
1、小女 孩子 们
2、小 女孩子 们
 
x1~xn就是每个word中单词的长度,标准值就是chunk中平均单词长度
第一个chunk的值为:
[(2-5/3)^2+(2-5/3)^2+(1-5/3)^2]/3=[(1/3)^2+(1/3)^2+(-2/3)^2]/3=
(0.1111+0.1111+0.4444)/3=0.2222
第二个chunk的值为:
 
[(1-5/3)^2+(3-5/3)^2+(1-5/3)^2]/3=[(-2/3)^2+(4/3)^2+(-2/3)^2]/3=
(0.4444+1.7777+0.4444)/3=0.8888
所以取第1个chunk,当然这个规则在这个例子中筛选错误了,因为第二个chunks比较接近原意。
为什么取方差值最小的,因为这样选对的概率比较高。
 
 
2.4最大单字单词的语素自由度和
取出chunks中单词个数为1的word,统计它们的单词语素自由度之和。取语素自由度之和最高的chunk。一个高频率的汉字更可能是一个单字单词,也就有更高的语素自由度,而这个单词的频率是事先统计的,它记录在一个预定义字典中。比如:
1、为首 要 考虑
2、为 首要 考虑
在1 chunks中,“要”的语素自由度为13.84,而在2中,“为”的语素自由度为13.64,说明“要”作为单个词使用的概率高一些,所以这里选择第一个chunk。当然这个算法在这里也选错了。
 
MMSeg中计算自由度公式是:
Freq=(int)(Math.log(Integer.parseInt(rate))*100)
这个公式的目的是让频率值相差不大的词拥有相同的自由度
 
从上面可以看到MMSeg算法划分并不是完全准确,官方说:“在一个由1013个单词组成的样本中,这个系统的正确识别率达到98.41%。”目前也没有那个算法能做到100%准确率,因为语言对于计算机来说真是太复杂的。

posted @ 2014-07-02 10:18  飞扬的薰衣草  阅读(316)  评论(0编辑  收藏  举报