转: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 ...
随机推荐
- 原生JS封装_new函数,实现new关键字的功能
1.前言 众所周知:没有对象怎么办?那就new一个! 那么在JS中,当我们new一个对象的时候,这个new关键字内部都干了什么呢? 现在我们就来剖析一下原生JS中new关键字内部的工作原理. 2.原生 ...
- Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/util/PatternMatchUtils
{ "message": "Handler dispatch failed; nested exception is java.lang.NoClassDefFoundE ...
- 大数据之路day01_1--Java下载、安装等配置
从今天开始,我就正式的走上大数据的道路了,如果说我为啥要去学习大数据,可能我的初衷是以后可以接触到人工智能方面的技术,后来在自学的过程中发现,学习人工智能,需要扎实的算法,以及对大量数据的处理,再者, ...
- jquery each循环遍历完再执行的方法
jquery each循环遍历完再执行的方法 因为each是异步的 所以要加计数器. var eachcount=0; <pre> $(".emptytip").eac ...
- day1-python初识以及变量
一.变量:将输入的内容赋值给变量,即变量=输入的内容 n1=input('请输入用户名:') 二. 变量名可以是 -英文. -数字.数字不能开头 -下划线,但是不可以下划线开头 不能是关键字 'and ...
- java 打包web 项目
1 选择你的web项目 2 右击,选择export 3 选择web下的war file 4 将打包好war包,保存在tomcat的webapps下 5 运行tomcat,tomcat会自动帮你解压这个 ...
- Java传参-基本数据类型和引用数据类型作为参数的区别(值传递)
java中的方法可以传递参数,参数的传递方法就是值传递. 参数有形参和实参,定义方法时写的参数叫形参,真正调用方法时,传递的参数叫实参. 调用方法时,会把实参传递给形参,方法内部其实是在使用形参. 所 ...
- macOS 使用Miniconda配置本地数据运算环境
目前,做数据分析工作,基本人手Numpy,pandas,scikit-learn.而这些计算程序包都是基于python平台的,所以搞数据的都得先装个python环境...(当然,你用R或Julia请忽 ...
- 一个简单的C#爬虫程序
这篇这篇文章主要是展示了一个C#语言如何抓取网站中的图片.实现原理就是基于http请求.C#给我们提供了HttpWebRequest和WebClient两个对象,方便发送请求获取数据,下面看如何实 1 ...
- hdu 3342 Legal or Not (topsort)
Legal or NotTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...