高性能搜索引擎sphinx源码解析之中文分词和mmseg

来源:互联网 发布:cad2017软件多少钱 编辑:程序博客网 时间:2024/06/05 00:27

注:

此文档基于sphinx及mmseg3代码整理,内容可能有疏漏,以后逐步完善

术语:

待分字符串:中华人民共和国
Chunk:中华,人民,共和国,为一条chunk(词组,item的组合)
Item:中华,为一个item
Sphinx分词器类包括四种:单字节字符集分词类器CSphTokenizer_SBCS,UTF-8字符集分词器类,N-gram,中文分词类CSphTokenizer_UTF8MMSeg,使用哪种分词器可通过配置文件指定。分词器继承关系、成员关系如下图:
这里写图片描述

IsphTokenizer是所有分词器类的基类,通过多态调用实现对不同分词器的支持。对其主要成员说明如下:

属性成员

  • m_tLC:CsphLowercaser
    如果是ASCII码转换为小写方式。如果是汉字把汉字的unicode码转换为utf_8编码。
  • m_tSettings: CsphTokenizerSettings
    分词器设置类,在进行分词前先调用此类进行设置,主要成员如下
  • m_iType:int 设置分词器类型,由配置文件读入,例如:zh_cn.utf-8
  • m_sCaseFolding: CsphString字符表和大小写转换规则,UTF8时值是 0..9, A..Z->a..z, _, a..z,
    U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451
  • m_iMinWordLen:int 最小索引长度,默认为1
  • m_sSynonymsFile: CsphString 特殊短语文件,目前未启用

            **使用方法:**        其输入文件txt格式如下        // test commit         .net => dotnet        c# => csharp        c++ => cplusplus        三星 => 三星4S        其中左侧是待支持的特殊短语,右侧是左侧的特殊短语需要被转换为的短语。        特殊短语词库构造命令:        mmseg -b exceptions.txt        其中, 开关'-b'指示mmseg是要构造特殊短语词库;exceptions.txt是用户编辑的特殊短语转换规  则。        该命令执行后,将在当前目录下产生一个名为"synonyms.dat"的文件,将该文件放在"uni.lib"同一目录下,分词系统将自动启动特殊短语转换功能。
  • m_sBoundary: CsphString 设置Boundary字符,默认为空,可由配置文件指定

  • m_sIgnoreChars:CsphString 设置忽略的字符集,可由配置文件指
  • m_iNgramLen:int n-gram length to index,for CJK indexing,只支持1,默认0,可由配置文件指定
  • m_sNgramChars: CsphString n-gram characters list, for CJK index,可由配置文件指定
  • m_sBlendChars: CsphString 设置Blend字符集,默认为空,可由配置文件指定, Blend字符会当作分隔符和合法字符处理,例如AT&T 会分成三个词 (“at”, “t”, and “at&t”)
    m_sBlendMode: CsphString 设置Blend模试,支持的有trim_none, trim_head, trim_tail, trim_both, skip_pure, 可由配置文件指定
  • m_iDebug:int coreseek加入,用于调试
  • m_sDictPath: CsphString 词典文件,由配置文件读入
  • m_iLastTokenLen:int 记录上一个分词长度,单位为字节
  • m_iLastTokenBufferLen:int 记录上一个分词的字符个数
  • m_bBoundary:bool遇到Boundary字符时变为true
  • m_bWasSpecial:bool 遇到特殊字符时变为true
  • m_iOvershortCount:int 记录跳过的字符个数,需要跳过的字符是\0,空格,\r,\t,\n
  • m_bPhrase:bool 遇到Phrase符号时变为true,遇到第二个变为false

成员函数

ISphTokenizer * ISphTokenizer::Create ( const CSphTokenizerSettings & tSettings, const CSphEmbeddedFiles * pFiles, CSphString & sError )
分词器创建流程如图
这里写图片描述

 SetCaseFolding:bool 设置字符表和大小写转换规则 ,进程启动创建分词器时由Create 调用
 AddPlainChar:void 添加一些字符为合法的分词字符,进程启动创建分词器时由Create 调用,例如*,?,%,=
 AddSpecials:void 添加特殊字符,进程启动创建分词器时由Create 调用,例如()|-!@~\”/^$<
 SetIgnoreChars:bool 设置分词时忽略的字符,由配置文件指定,默认为空
 SetNgramChars:bool 设置NgramChars,CJK使用
 SetNgramLen:void:CJK使用
 LoadSynonyms:bool 特殊符号同义词,未使用
 WriteSynonyms:void 未使用
 SetBoundary:bool 设置Boundary字符,由配置文件指定,默认为空
 SetBlendChars:bool 设置Blend字符,由配置文件指定,默认为空
 SetBlendMode:bool 设置Blend模式,由配置文件指定,默认为空
 Setup:void 使用CSphTokenizerSettings类的相关设置,配置分词器,进程启动创建分词器时由Create 调用
 GetSettings:CSphTokenizerSettings,返回当前所用分词器的相关配置参数
 SetBuffer:void 设置待分的字串、长度、mmseg相关参数
 GetToken:BYTE * 得到一个分词

分词在sphinx内部存储结构

分词结果存储在XQParser_t类的m_dIntTokens:CSphVector和m_tPendingToken:YYSTYPE成员中。数字以字串的形式存储在m_dIntTokens中,中文、英文、特殊字符存储在pNode成中m_dWords:CSphVector中。例如:中国123abc?456人民,存储结构如下
这里写图片描述

mmseg3算法

Mmseg3中有两种算法,正向匹配算法、复杂最大匹配算法。正向匹配算法是查字典所用的算法,复杂匹配算法是chunk所用算法。
复杂匹配算法,匹配出所有的“三个词的词组(chunk),即从某一既定的字为起始位置,得到所有可能的“以三个词为一组”的所有组合
 最大匹配规则,选择词组长度最大的那个词组,规则1
 最大平均词语长度,选择平均词语长度最大的那个(平均词长=词组总字数/词语数量)词组,规则2
 词语长度的最小变化率,计算标准差,规则3
 单个词的词频较为接近,既计算组合中所有单字词词频的自然对数,然后将得到的值相加,取总和最大的词组,规则4

分词流程图如下
这里写图片描述

举例如下:
 词典:中华,中华人,中华人民,民,人民,共和国,研究,研究生,生命,起源
 待切分字符串:中华人民共和国
 应用正向匹配算法,查字典结束后得到的item,字典中没有的单字也会被查出当作一个item
① 中:中华,中华人,中华人民
② 华:华
③ 人:人民
④ 民:民
⑤ 共:共和国
⑥ 和:和
⑦ 国:国
 应用复杂匹配算法得到chunk
① 中华,人民,共和国
② 中华人,民,共和国
③ 中华人民,共和国
④ ………..
 应用规则1,chunk长度最大,得到chunk
⑤ 中华,人民,共和国
⑥ 中华人,民,共和国
① 中华人民,共和国
 应用规则2,chunk词平均长度最大,得到chunk
① 中华人民共和国
 只剩唯一个chunk,分词结束
mmseg3分词算法的说明
 mmseg3只存储token长度,不存储token,以vector存储,这样很大程度节约系统资源
 mmseg3把整个字符串全部完成切分后,再返回结果,而不是得一个token就返回
 mmseg3查字典应用正向匹配算法,查字典结束后应用复杂匹配算法
 mmseg3对每个字均做一次查字典操作,例如中华人民共和国,先用中查字典,就算字典中只有中华,没有中,也会用华查字典,而不是用人去查字典
 mmseg3对每个字查字典,全部完成部,再应用复杂匹配算法,得到所所三个词组合的chunk(如果有三个词)

转载请注明出处!交流QQ群:659201069

原创粉丝点击