转:IK分词原理
IKAnalyzer是一个开源的,基于Java语言开发的轻量级的中文分词语言包,它是以Lucene为应用主体,结合词典分词和文法分析算法的中文词组组件。从3.0版本开始,IK发展为面向java的公用分词组件,独立Lucene项目,同时提供了对Lucene的默认优化实现。
以下这篇博客是我在通读IK分词代码后对IK分词的理解,如果有什么地方出现纰漏请大家指正。
回到最初
如果让我自己在看IK分词之前自己写一个分词器,那我会怎么做? 如果我会想到的是:比如对"周末有欧冠决赛"做分词处理,人为的分词是:“周末|有|欧冠|决赛”,那为什么会出现这样的分词效果,首先必须有一个词典,词典中可以标记出“周末”、“欧冠”、“决赛”这些词,因为分词器并不具备人工智能的能力,所以它所做的就是把文本和词典中的词进行比较,按照词典中已有的词进行匹配,匹配完成之后即达到了分词的效果。
现在虽然找不到第一个写分词的人是如何设计分词的算法的,但是我想是差不多的。
K分词其实也是这么来做的。将一段文字进行IK分词处理一般经过:词典加载、预处理、分词器分词、歧义处理、善后结尾 五个部分。
词典加载:
主程序需要加载词典。IK分词的词典主要包括 main2012.dic(主词典)、quantifier.dic(量词)、stopword.dic(停用词)、ext.dic(扩展词,可选)四个字典。字典的结构使用字典树进行存储。关于字典树的具体介绍可以参考: http://www.cnblogs.com/rush/archive/2012/12/30/2839996.html
预处理:
预处理是在加载文档的时候做的,其实预处理部分只是做两件事情:
- 识别出每个字符的字符类型
- 字符转化:全角转半角,大写转小写
字符类型是在分词的时候需要,不同的分词器会根据不同的字符类型做特别处理。而字符转化则是要求文本字符与词典中的字符想匹配,比如对于12288、32这两个字符,分别是汉字和英文的空格,如果一篇文本中包含了汉字包含了这两个字符,那么分词器在分词的时候需要判断两个都是空格。同理在英文大小写上也存在类似的问题。预处理主要在org.wltea.analyzer.core.CharacterUtil.java类中实现。
分词器分词:
IK分词包括三个分词器:LetterSegmenter(字符分词器),CN_QuantifierSegmenter(中文数量词分词器),CJKSegmenter(中日韩文分词器)。分词器分词有两种模式,即:smart模式和非smart模式,非smart模式可以认为是最小力度的分词,smart模式则反之。
具体的实例:
张三说的确实在理
smart模式的下分词结果为:
张三 | 说的 | 确实 | 在理
而非smart模式下的分词结果为:
张三 | 三 | 说的 | 的确 | 的 | 确实 | 实在 | 在理
IK分词使用了”正向迭代最细粒度切分算法“,简单说来就是: Segmenter会逐字识别词元,设输入”中华人民共和国“并且”中“单个字也是字典里的一个词,那么过程是这样的:”中“是词元也是前缀(因为有各种中开头的词),加入词元”中“;继续下一个词”华“,由于中是前缀,那么可以识别出”中华“,同时”中华“也是前缀因此加入”中华“词元,并把其作为前缀继续;接下来继续发现“华人”是词元,“中华人”是前缀,以此类推……
关于IK分词的三个分词器,基本上逻辑是一样的,如果有兴趣了解的话,重点看一下CJKSegmenter就好了。
歧义处理:
非smart模式所做的就是将能够分出来的词全部输出;smart模式下,IK分词器则会根据内在方法输出一个认为最合理的分词结果,这就涉及到了歧义判断。
以“张三说的确实在理”为依据,分词的结果为:
张三 | 三 | 说的 | 的确 | 的 | 确实 | 实在 | 在理
在判断歧义的时候首先要看词与词之间是否用冲突,“张三”与“三”相冲突,“说的”,“的确”,“的”,“确实”,“实在”,“在理”相冲突,所以分成两部分进行歧义判断。我们以后一种为例:“说的”,“的确”,“的”,“确实”,“实在”, 按照默认的生成的一组结果为“说的|确实|在理”,与这个结果相冲突的词是“的确”、“的”、“实在”。回滚生成的结果,将这三个词倒叙逐一放入到生成的结果中,生成可选分词方案是:
"实在"放入后,分词方案为:"说的|实在|";
"的"放入后,生成的分词方案为:"的|确实|在理";
"的确"放入后,生成的分词方案为:"的确|实在";
这样加上原有的一共四种可选的分词方案,从中选取最优的方案。选取的原则顺序如下:
1、比较有效文本长度
2、比较词元个数,越少越好
3、路径跨度越大越好
4、最后一个词元的位置越靠后约好(根据统计学结论,逆向切分概率高于正向切分,因此位置越靠后的优先)
5、词长越平均越好
6、词元位置权重比较
总体说来就是: 主要使用的就是贪心算法获取局部最优解,然后继续处理来获取最终的结果。
善后结尾:
- 处理遗漏中文字符,遍历输入文本,把词之间每个中文字符也作为词输出,虽然词典中没有这样的词。
- 处理数量词,如果中文量词刚好出现在中文数词的后面,或者中文量词刚好出现在阿拉伯数字的后面,则把数词和量词合并。比如"九寸""十二亩"。
其它
Ik的排序方法特别粗略,如果比较发现path1的词个数,比path2的个数少,就直接判定path1更优。其实这样的规则,并未完整的参考各个分出来的词的实际情况,我们可能想加入每个词经统计出现的频率等信息,做更全面的打分,这样IK原有的比较方法就是不可行的。
转:IK分词原理的更多相关文章
- IK分词器实现原理剖析 —— 一个小问题引发的思考
前言: 网上很多的文章都建议在使用IK分词器的时候,建立索引的时候使用ik_max_word模式:搜索的时候使用ik_smart模式.理由是max_word模式分词的结果会包含smart分词的结果,这 ...
- IK分词器原理与源码分析
原文:http://3dobe.com/archives/44/ 引言 做搜索技术的不可能不接触分词器.个人认为为什么搜索引擎无法被数据库所替代的原因主要有两点,一个是在数据量比较大的时候,搜索引擎的 ...
- IK分词器 原理分析 源码解析
IK分词器在是一款 基于词典和规则 的中文分词器.本文讲解的IK分词器是独立于elasticsearch.Lucene.solr,可以直接用在java代码中的部分.关于如何开发es分词插件,后续会有文 ...
- ElasticSearch已经配置好ik分词和mmseg分词(转)
ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进行数据索引 ...
- Elasticsearch使用系列-ES增删查改基本操作+ik分词
Elasticsearch使用系列-ES简介和环境搭建 Elasticsearch使用系列-ES增删查改基本操作+ik分词 一.安装可视化工具Kibana ES是一个NoSql数据库应用.和其他数据库 ...
- [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例一.
在这里一下讲解着三个的安装和配置, 是因为solr需要使用tomcat和IK分词器, 这里会通过图文教程的形式来详解它们的安装和使用.注: 本文属于原创文章, 如若转载,请注明出处, 谢谢.关于设置I ...
- ElasticSearch ik分词安装
1.下载对应版本的ES ik分词 https://github.com/medcl/elasticsearch-analysis-ik/releases 2.解压elasticsearch-analy ...
- IK分词器 整合solr4.7 含同义词、切分词、停止词
转载请注明出处! IK分词器如果配置成 <fieldType name="text_ik" class="solr.TextField"> < ...
- Elasticsearch5.1.1+ik分词器+HEAD插件安装小记
一.安装elasticsearch 1.首先需要安装好java,并配置好环境变量,详细教程请看 http://tecadmin.net/install-java-8-on-centos-rhel-an ...
随机推荐
- 学习笔记之vim的使用
很多刚学习linux编程的人总是对vim有一种恐惧,我自己就是这么回事的. 可是当你努力的去尝试学习使用后,才发现它的精髓所在. 在我看来,让vim变得好用的前提是要安装两个插件,ctags和tagl ...
- Project Euler 59: XOR decryption
计算机上的每个字母都对应一个独特的编号,普遍接受的标准是ASCII(美国信息交换标准代码).例如,大写字母的A的ASCII码是65,星号(*)的ASCII码是42,而小写字母k的代码是107. 一种现 ...
- PyCharm使用正则替换python中的静态资源
python每次开发前台页面时,最无法避免的就是前台静态资源地址的替换了,手动替换成{% static 'web/.......' %}可想而知的痛苦,把正则替换的方式分享给朋友们,希望可以帮助到需要 ...
- 2019年10月13日 linux习题 wangqingchao
1. GUN的含义是: GNU's Not UNIX . 2. Linux一般有3个主要部分:内核.命令解释层.实用工具. 3.POSIX是可携式操作系统接口的缩写,重点在规范核心与应用程序之间的接口 ...
- mysql用find_in_set代替like搜索提高性能
mysql用find_in_set代替like搜索提高性能 <pre>SELECT * from mobantestinfo1 where find_in_set('33',info2); ...
- 简单看看@RequestBody注解原理
又到了很无聊的时候了,于是随便看看源码假装自己很努力的样子,哈哈哈: 记得上一篇博客随便说了一下RequestBody的用法以及注意的问题,这个注解作为非常常用的注解,也是时候了解一波其中的原理了. ...
- PHP 面试官问:你说说Redis的几个过期策略?
在使用redis时,一般会设置一个过期时间,当然也有不设置过期时间的,也就是永久不过期.当设置了过期时间,redis是如何判断是否过期,以及根据什么策略来进行删除的. 设置过期时间 expire ke ...
- (C#)WPF:LinearGradientBrush 线性渐变画刷和RadialGradientBrush 圆形渐变画刷
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/200 ...
- 分组取topN
假设有这样一个文件,文件内容如下 class1 class2 class1 class1 class2 class2 class1 class2 class1 class2 要求按照班级分组取出每个班 ...
- java编程思想第四版第八章习题
第一题 package net.mindview.polymorphism; //基类-自行车 class Cycle{ } //子类-单轮车 class Unicycle extends Cycle ...