说说MMSeg分词
记得06年的时候,我就学习过Lucene.Net一段时间,也写过一个分词。那个比较简单,就是一个最大逆向匹配加一个词库。不过,今年早些时候,硬盘坏了。所有数据都丢了。
上上周公司一个项目要用到搜索,我自然又想到了Lucene。并发现一个叫MMSeg的中文分词。据官方说法,正确率高达98%点多。
本人嘴拙,请大家看原文:http://www.solol.org/projects/mmseg/
不废话了:
其实MMSeg分词理解起来很容易,主要是chunk和四个规则。
chunk:
一个chunk就是一句话的一种分词方式。包括一个词条数组和四个属性。
打个比方:
“研究生命”用匹配的话,至少有两种:
研究/生命 VS 研究生/命
这就是两个chunk。
一个chunk有四个重要的属性:
长度:chunk中个词的长度之和,这里两个chunk的长度都是4.
代码如下:
public int getLength() {
if (length == -1) {
length = 0;
for (int i = 0; i < words.length; i++) {
length += words[i].getLength();
}
}
return length;
}
平均长度:长度/词数.4/2=2
代码如下:
public double getAverageLength() {
if (averageLength == -1D) {
averageLength = (double) getLength() / (double) words.length;
}
return averageLength;
}
标准差平方:chunk中各个词条的长度减去平均长度的差的平方的和,再除以词条数目。唉,这句话说的真难懂啊。哈哈哈看代码:
public double getVariance() {
if (variance == -1D) {
double tempVariance = 0D;
for (int i = 0; i < words.length; i++) {
double temp = (double)words[i].getLength()-getAverageLength();
tempVariance += temp * temp;
}
variance = Math.sqrt(tempVariance / (double) words.length);
}
return variance;
}
自由语素度:各单词条词频的对数之和。
看代码:
public double getDegreeOfMorphemicFreedom() {
if (degreeMorphemicFreedom == -1D) {
degreeMorphemicFreedom = 0D;
for (int i = 0; i < words.length; i++) {
if (words[i].getLength() == 1) {
degreeMorphemicFreedom += Math.log((double) words[i].getFrequency());
}
}
}
return degreeMorphemicFreedom;
}
最重要的chunk的概念理解了之后,就要理解四个规则了。
规则1:取最大匹配的chunk (Rule 1: Maximum matching)
这个规则好理解,就是取chunk长度最长的几个。注意是几个噢。
规则2:取平均词长最大的chunk (Rule 2: Largest average word length)
这个规则也好理解,就是取chunk平均长度最大的几个。
规则3:取词长标准差最小的chunk (Rule 3: Smallest variance of word lengths)
这个不说了,对应的属性是getVariance,取最小。
规则4:取单字词自由语素度之和最大的chunk (Rule 4: Largest sum of degree of morphemic freedom of one-character words)
这个一样,对应属性是getDegreeOfMorphemicFreedom,取最大。
如果经过这个四个规则的过滤,剩下的chunk数大于1,就这个分词就无能为力了。需要我们自己扩展了,其实扩展挺容易,再想出一个规则来就行了,哈哈哈。当然,自己扩展的规则,调用方法略微不一样点。
废话不多说: