LibMMSeg 是Coreseek.com为 Sphinx 全文搜索引擎设计的中文分词软件包,其在GPL协议下发行的中文分词法,采用Chih-Hao Tsai的MMSEG算法。
MMSEG: A Word Identification System for Mandarin Chinese Text Based on Two Variants of the Maximum Matching Algorithm
Published: 1996-04-29
Updated: 1998-03-06
Document updated: 2000-03-12
License: Free for noncommercial use
Copyright 1996-2006 Chih-Hao Tsai (Email: hao520 at yahoo.com )
您可以在Chih-Hao Tsai's Technology Page找到算法的原文。
LibMMSeg 采用C++开发,同时支持Linux平台和Windows平台,切分速度大约在500K/s(酷睿 2.4G);截至目前版本LibMMSeg没有为速度做过特殊优化,进一步的提升切分速度仍有空间。
下载 Coreseek-3.2.14+MMSeg 3.2.14,mmseg-3.2.14.tar.gz
MMSeg 的 Node.js 插件,由 zzdhidden 开发。
https://github.com/zzdhidden/mmseg-node
3.2.14
- 2011.01.12 随coreseek3.2.14提供
- 修正同义词库锁定问题
3.2.13
- 2010.07.01 随coreseek3.2.13提供
- 修正chunks问题- 完善多操作系统支持
3.2.12
- 2010.05.03 随coreseek3.2提供
- 增加了英文和数字的处理部分- 优化了相关处理部分
0.7.3
- 2008.05.27 修正 Makefile 无法安装csr_typedefs.h的问题
- 2008.05.27 修正 x64系统上编译无法作为动态库的一部分编译的问题
0.7.2
- 2008.05.19 修正 指定的目录中无词典不提示错误的问题
- 2008.05.19 新增 Ruby 的调用API
0.7.1
- 2008.04.23 修正了在类似 “english 中文 english" 的句子,切分不正确的问题
0.7
- 第一次发行
Window平台
打开源码包中src\win32 子目录下的对应的工程文件,目前LibMMSeg内置了VS2003和VS2005的工程文件。
Linux平台
在源码包根目录下执行:
./configure && make && make install
词典的构造
mmseg -u unigram.txt
该命令执行后,将会在unigram.txt所在目录中产生一个名为unigram.txt.uni的文件,将该文件改名为uni.lib,完成词典的构造。需要注意的是,unigram.txt需要预先准备,并且编码格式必须为UTF-8编码。
特别提醒:Windows下面编辑词典文件,请使用Notepad2,绝对不要使用记事本(Notepad)。
词典文件格式:
....
河 187
x:187
造假者 1
x:1
台北队 1
x:1
湖边 1
......
其中,每条记录分两行。其中,第一行为词项,其格式为:[词条]\t[词频率]。特别提醒,有的编辑器会使用4到8个空格代表\t,这将导致该词条无法解析。需要注意的是,对于单个字后面跟这个字作单字成词的频率,这个频率需要在大量的预先切分好的语料库中进行统计,用户增加或删除词时,一般不需要修改这个数值;对于非单字词,词频率处必须为1。第二行为占位项,是由于LibMMSeg库的代码是从Coreseek其他的分词算法库(N-gram模型)中改造而来的,在原来的应用中,第二行为该词在各种词性下的分布频率。LibMMSeg的用户只需要简单的在第二行处填"x:1"即可。
用户可以通过修改词典文件增加自己的自定义词,以提高分词法在某一具体领域的切分精度,系统默认的词典文件在源代码目录的data/unigram.txt中。
mmseg -d <dict_dir> tobe_segment.txt
其中,命令使用‘-d’开关指定词库文件所在的位置,参数dict_dir为词库文件(uni.lib )所在的目录;tobe_segment.txt 为待切分的文本文件,必须为UTF-8编码。如果一切正确,mmseg会将切分结果以及所花费的时间显示到标准输出上。
对特殊短语的支持
由于LibMMSeg是为Sphinx全文搜索引擎设计的,因此其内置了部分搜索引擎切分算法的特性,主要表现在对特殊短语的支持上。
在搜索引擎中,需要处理C++时,如果分词器中没有词组C++,则将被切分为C/x +/x +/x,在进一步的检索中,可能每个词会由于出现的过于频繁而被过滤掉,导致搜索的结果与C++相关度不高不说,也严重影响的全文搜索的速度。在LibMMSeg中,内置对特殊短语的支持。
其输入文件格式如下
// test commit
.net => dotnet
c# => csharp
c++ => cplusplus
其中左侧是待支持的特殊短语,右侧是左侧的特殊短语需要被转换为的短语。这一转换在分词前进行。
可以在行的开头加入'//'作为注释符号,发现符号'//'后,整行将被忽略。
特殊短语词库构造命令:
mmseg -b exceptions.txt
其中, 开关'-b'指示mmseg是要构造特殊短语词库;exceptions.txt是用户编辑的特殊短语转换规则。
该命令执行后,将在当前目录下产生一个名为"synonyms.dat"的文件,将该文件放在"uni.lib"同一目录下,分词系统将自动启动特殊短语转换功能。
注意:
1、在启用了该功能后,如果分词系统发现了一个特殊短语,将直接输出其在右侧对应的替换的值;
2、右侧被替换的值,请保证不会被分词器进行切分。(eg. C++ => C# 这个转换的意义不大,并且可能导致C++这个短语永远无法被检索到!)
附录:
首先来理解一下chunk,它是MMSeg分词算法中一个关键的概念。Chunk中包含依据上下文分出的一组词和相关的属性,包括长度(Length)、平均长度(Average Length)、标准差的平方(Variance)和自由语素度(Degree Of Morphemic Freedom)。下面列出了这4个属性:
属性 | 含义 |
长度(Length) | chuck中各个词的长度之和 |
平均长度(Average Length) | 长度(Length)/词数 |
标准差的平方(Variance) | 同数学中的定义 |
自由语素度(Degree Of Morphemic Freedom) | 各单字词词频的对数之和 |
Chunk中的4个属性只有在需要该属性的值时才进行计算,而且只计算一次。
其次来理解一下规则(Rule),它是MMSeg分词算法中的又一个关键的概念。实际上我们可以将规则理解为一个过滤器(Filter),过滤掉不符合要求的chunk。MMSeg分词算法中涉及了4个规则:
这4个规则符合汉语成词的基本习惯。
再来理解一下匹配方式复杂最大匹配(Complex maximum matching):
复杂最大匹配先使用规则1来过滤chunks,如果过滤后的结果多于或等于2,则使用规则2继续过滤,否则终止过滤过程。如果使用规则2得到的过滤结果多于或等于2,则使用规则3继续过滤,否则终止过滤过程。如果使用规则3得到的过滤结果多于或等于2,则使用规则4继续过滤,否则终止过滤过程。如果使用规则 4得到的过滤结果多于或等于2,则抛出一个表示歧义的异常,否则终止过滤过程。
最后通过一个例句--“研究生命起源"来简述一下复杂最大匹配的分词过程。MMSeg分词算法会得到7个chunk,分别为:
编号 | chunk | 长度 |
0 | 研_究_生 | 3 |
1 | 研_究_生命 | 4 |
2 | 研究_生_命 | 4 |
3 | 研究_生命_起 | 5 |
4 | 研究_生命_起源 | 6 |
5 | 研究生_命_起 | 5 |
6 | 研究生_命_起源 | 6 |
使用规则1过滤后得到2个chunk,如下:
编号 | chunk | 长度 |
4 | 研究_生命_起源 | 6 |
6 | 研究生_命_起源 | 6 |
计算平均长度后为:
编号 | chunk | 长度 | 平均长度 |
4 | 研究_生命_起源 | 6 | 2 |
6 | 研究生_命_起源 | 6 | 2 |
使用规则2过滤后得到2个chunk,如下:
编号 | chunk | 长度 | 平均长度 |
4 | 研究_生命_起源 | 6 | 2 |
6 | 研究生_命_起源 | 6 | 2 |
计算标准差的平方后为:
编号 | chunk | 长度 | 平均长度 | 标准差的平方 |
4 | 研究_生命_起源 | 6 | 2 | 0 |
6 | 研究生_命_起源 | 6 | 2 | 4/9 |
使用规则3过滤后得到1个chunk,如下:
编号 | chunk | 长度 | 平均长度 | 标准差的平方 |
4 | 研究_生命_起源 | 6 | 2 | 0 |
匹配过程终止。最终取“研究”成词,以相同的方法继续处理“生命起源”。
分词效果:
研究_生命_起源_
研究生_教育_
词汇长度:
默认为5个UTF-8汉字,如果需要修改,可以如下操作: 1. 打开:mmseg源代码/css/segmenter.cpp 2. 修改:#define MAX_TOKEN_LENGTH 15 //3*5 3. 重新编译mmseg和coreseekcoreseek 中文分词核心配置:
请参考:中文分词核心配置mmseg.ini配置:(请将其放置到词典文件uni.lib所在的目录,并在文件结尾空两行)
[mmseg] merge_number_and_ascii=0 number_and_ascii_joint= compress_space=1 seperate_number_ascii=0
配置说明:【因为Sphinx-0.9.9发生变化,导致mmseg.ini的字母和数字切分规则部分无法正常应用,故暂停使用;下一版本将彻底解决该问题】 merge_number_and_ascii : ;合并英文和数字 abc123/x;如果0,则abc123切分为abc、123;如果1,则abc123为一个整体;【暂停使用】 number_and_ascii_joint : 定义可以连接英文和数字的字符;该字符将把英文和数字作为一个整体处理;如果设置为-,则abc-123将被切分为abc123;【继续有效】 compress_space : 预留暂不支持 seperate_number_ascii : 将数字打散;如果0,则123为一个整体;如果1,则123切分为1、2、3;【暂停使用】mmseg 同义词/复合分词处理:
mmseg 3.2.13版本开始,提供了类似复合分词的处理方式,供coreseek进行调用。 其基本使用状况为: 词库包含: 南京西路、南京、西路 索引时: 文本中的“南京西路”会被同时索引为以上三者 查询时: 输入南京西路,可以直接匹配南京西路,而不匹配南京或者西路; 输入南京或者西路,也可以搜索到南京西路 用法: 1. 处理unigram.txt生成同义词库文件 mmseg-3.2.13源代码/script/build_thesaurus.py unigram.txt > thesaurus.txt thesaurus.txt文件的格式如下:南京西路 -南京,西路, 张三丰 -太极宗师,武当祖师,2. 生成同义词词典 mmseg -t thesaurus.txt3. 将thesaurus.lib放到uni.lib同一目录4. coreseek索引和搜索时,会自动进行复合分词处理。如果使用默认的词库,没有做过自定义,则可以直接下载thesaurus.lib,放到uni.lib所在目录!