收藏 分享(赏)

IK分词处理过程(源码分析).doc

上传人:mcady 文档编号:7230027 上传时间:2019-05-10 格式:DOC 页数:3 大小:43.50KB
下载 相关 举报
IK分词处理过程(源码分析).doc_第1页
第1页 / 共3页
IK分词处理过程(源码分析).doc_第2页
第2页 / 共3页
IK分词处理过程(源码分析).doc_第3页
第3页 / 共3页
亲,该文档总共3页,全部预览完了,如果喜欢就下载吧!
资源描述

1、IK 的整个分词处理过程首先,介绍一下 IK 的整个分词处理过程:1. Lucene 的分词基类是 Analyzer,所以 IK 提供了 Analyzer 的一个实现类 IKAnalyzer。首先,我们要实例化一个 IKAnalyzer,它有一个构造方法接收一个参数 isMaxWordLength,这个参数是标识 IK 是否采用最大词长分词,还是采用最细粒度切分两种分词算法。实际两种算法的实现,最大词长切分是对最细粒度切分的一种后续处理,是对最细粒度切分结果的过滤,选择出最长的分词结果。2. IKAnalyzer 类重写了 Analyzer 的 createComponents 方法,这个方法

2、接收两个参数,fieldName 和输入流 reader,其中 fieldName 是 Lucene 的属性列,是对文本内容进行过分词处理和创建索引之后,索引对应的一个名称,类似数据库的列名。因为 IK 仅仅涉及分词处理,所以对 fieldName 没有进行任何处理,所以此处不做任何讨论。3. createComponents 方法在 Lucene 对文本输入流 reader 进行分词处理时被调用,在IKAnalyzer 的 createComponents 方法里面仅仅实例化了一个 IKTokenizer 类,该类继承了Lucene 的 Tokenizer 类。并重写了 incrementT

3、oken 方法,该方法的作用是处理文本输入流生成 token,也就是 Lucene 的最小词元 term,在 IK 里面叫做 Lexeme。4. 在 IKtokenizer 的构造方法里面实例化了 IK 里面最终要的分词类 IKSegmenter,也称为主分词器。它的构造方法接收两个参数,reader 和 isMaxWordLength。5. IKSegmenter 的构造方法里面,主要做了三个工作,创建上下文对象 AnalyzeContext,加载词典,创建子分词器。6. AnalyzeContext 主要是存储分词结果集和记录分词处理的游标位置。7. 词典是作为一个单例被创建的,主要有量词

4、词典、主词典和停词词典。词典是被存储在字典片段类 DictSegment 这个字典核心类里面的。DictSegment 有一个静态的存储结构charMap,是公共词典表,用来存储所有汉字,key 和 value 都是一个中文汉字,目前 IK 里面的 charMap 大概有 7100 多的键值对。另外,DictSegment 还有两个最重要的数据结构,是用来存储字典树的,一个是 DictSegment 的数组 childrenArray,另一个是 key 为单个汉字(每个词条的第一个汉字) ,value 是 DictSegment 的 HashMap childrenMap。这两个数据结构二者取

5、其一,用来存储字典树。8. 子分词器才是真正的分词类,IK 里面有三个子分词器,量词分词器,CJK 分词器(处理中文) ,停词分词器。主分词器 IKSegmenter 遍历这三个分词器对文本输入流进行分词处理。9. IKTokenizer 的 incrementToken 方法调用了 IKSegmenter 的 next 方法,next 的作用是获得下一个分词结果。next 在第一次被调用的时候,需要加载文本输入流,并将其读入buffer,此时便遍历子分词器,对 buffer 种的文本内容进行分词处理,然后把分词结果添加到 AnalyzeContext 的 results 數組中。下面,以 C

6、JKSegmenter 子分词器为例介绍一下生成分词结果集的流程:1. IKSegmenter 遍历 Segmenter 时,调用 CJKSegmenter 的 analyze 方法,该方法接收两个参数,segmentBuf 和 AnalyzeContext,segmentBuf 是一个 Character 数组,文件输入流分解后得到,AnalyzeContext 即 IK 的 Context 类实例,用来记录 segmentBuf 游标以及存储切分后的词元 lexeme。2. 进入 analyze 方法,首先判断是否中文字符,然后判断是否存在词段队列,举例来说“中华人民共和国” ,这个词条,

7、就会存在一个词段队列,分别存储“中华” 、 “中华人民” 、“中华人民共和” 、 “中华人民共和国” ,前面词段依次是后面词段的前缀。这个词段队列也是在 analyze 方法中填充的。当一个词条和字典中的词匹配成功,并且也是字典中某个词条的前缀,则被加入队列,当一个词条不再是某个词条的前缀,移除出队列。3. 如果词段队列里面不存在词段,把当前的 Character 与字典中的词匹配,创建一个新的hit,如果字典种存在这个 Character,把 hit 添加进词段队列。如果词段队列里面已经存在词段,遍历词段队列,判断当前 Character 是否可以以词段队列中的词为前缀,组成一个字典中存在的

8、词,如果可以,则加入 results 中,如果不能匹配成词,则将这个前缀 hit 从队列种移除,因为以后也不会匹配成词了,故删除。4. 如此循环执行 analyze 方法,最终将文本输入流切分成的词元 lexeme 完全放入AnalyzeContext 的 results 中。这时,再次调用 IKSegmenter 类的 next 方法时,则会直接读取 results 中已经切分好的词元。所以所有的切分工作都在第一次调用 IKSegmenter 的 next的时候完成。5. IK 分词算法理解根据作者官方说法 IK 分词器采用“正向迭代最细粒度切分算法” , 分析它 的源代码, 可以看到分词工

9、具类 IKQueryParser 起至关重要的作用, 它对搜索 关键词采用从最大词到最小词层层迭代检索方式切分,比如搜索词:“中华人 民共和国成立了” , 首先到词库中检索该搜索词中最大分割词, 即分割为: “中 华人民共和国”和“成立了” , 然后对“中华人民共和国”切分为“中华人民”和“人 民共和国” ,以此类推。最后, “中华人民共和国成立了”切分为:“中华人民 | 中华 | 华人 | 人民 | 人民共和国 | 共和国 | 共和 | 成立 | 立了” ,当然, 该切分方式为默认的细粒度切分,若按最大词长切分,结果为:“中华人民共 和国 | 成立 | 立了” 。核心算法代码如下boolea

10、n accept(Lexeme _lexeme)/* * 检查新的 lexeme 对当前的 branch 的可接受类型 * acceptType : REFUSED 不能接受* acceptType : ACCEPTED 接受 * acceptType : TONEXT 由相邻分支接受*/ int acceptType = checkAccept(_lexeme); switch(acceptType) case REFUSED: / REFUSE 情况 return false;case ACCEPTED : if(acceptedBranchs = null) /当前 branch 没有子

11、 branch,则添加到当前branch 下 acceptedBranchs = new ArrayList(2); acceptedBranchs.add(new TokenBranch(_lexeme); else boolean acceptedByChild = false; /当前 branch 拥有子 branch,则优先由子 branch 接纳 for(TokenBranch childBranch : acceptedBranchs) acceptedByChild = childBranch.accept(_lexeme) | acceptedByChild; /如果所有的子

12、 branch 不能接纳,则由当前 branch 接纳 if(!acceptedByChild) acceptedBranchs.add(new TokenBranch(_lexeme); /设置 branch 的最大右边界 if(_lexeme.getEndPosition() this.rightBorder) this.rightBorder = _lexeme.getEndPosition(); break;case TONEXT : /把 lexeme 放入当前 branch 的相邻分支 if(this.nextBranch = null) /如果还没有相邻分支,则建立一个不交叠的分

13、支 this.nextBranch = new TokenBranch(null); this.nextBranch.accept(_lexeme); break; return true; 从代码中可以了解到,作者采用了递归算法(代码中加粗的部分)切分 搜索词。若词存在子词则递归该函数,继续切分。IK 分词弱点、缺点 分词弱点 弱点、总体来说,IK 是一个很不错的中文分词工具,但它自身也存在一些缺点,比如: a. 对歧义分词还需要扩展、改进,比如:”湖北石首” 和 “蒋介石首次访问” ,如果用户搜索”石首”会把”蒋介石首次访问”也显示出来。 b. 对英文单词的搜索还需改进,比如:”IKAnalyzer” 或”UU 音乐” ,如果用户输 入搜索关键词”IKAnaly ”或”U”则无法搜索出结果。 c. IKAnalyzer.cfg.xml 中关于词典的配置,暂不支持通配符方式,这样导致如果 有大批词典配置文件时会很麻烦。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报