转: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 ...
随机推荐
- tarjan学习(复习)笔记(持续更新)(各类找环模板)
题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...
- 简述JMM
一.很多初学者分不清JMM和JVM的内存模型,本篇只是简要的谈一谈什么是JMM,并不深入探讨. 示意图A: 在多线程操纵共享资源时,并不是对资源本身进行的操作,而是将共享资源的副本复制了一份到自己的私 ...
- egret开发方法(最笨的方法)
egret开发方法(最笨的方法)1 1个精灵1个对象名字 获取精灵设置属性也是直接获取对象设置属性 (不用想的少些代码 因为没有jquery好用) ps:如果要设置很多个精灵属性 那可以添加到数组 然 ...
- java中的线程安全
在Java中,线程的安全实际上指的是内存的安全,这是由操作系统决定的. 目前主流的操作系统都是多任务的,即多个进程同时运行.为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的.分配给别 ...
- Golang stackError 补充go错误定位能力
用过go的都知道,go的error实现很简单,errors.New实现的error类并不存储堆栈数据,这导致一个问题,就是多次error return后,或panic后recover了,找不到触发异常 ...
- Chrome Extension 小试牛刀
自从有了Chrome以后,就喜欢上了这个浏览器,从此IE 886了. 以前作爬虫,做登录,做数据采集,做数据处理等各种功能,后来H5出来后,出现了,除了Session/Cookie 出了Local S ...
- pat 1054 The Dominant Color(20 分)
1054 The Dominant Color(20 分) Behind the scenes in the computer's memory, color is always talked abo ...
- RHEL7.2 安装Hadoop-2.8.2
创建三台虚拟机,IP地址为:192.168.169.101,192.168.169.102,192.168.169.103 将192.168.169.102为namenode,192.168.169. ...
- python_day03
今日所学内容 1.函数部分: #函数的三种定义方式#1.无参函数:不需要外部传入的参数#2.有参函数:需要接受外部传入的参数#3.空函数:def func(): pass#pass代表说明都不用做# ...
- 【翻译】Orleans 3.0 发布
aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUF ...