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分词原理的更多相关文章

  1. IK分词器实现原理剖析 —— 一个小问题引发的思考

    前言: 网上很多的文章都建议在使用IK分词器的时候,建立索引的时候使用ik_max_word模式:搜索的时候使用ik_smart模式.理由是max_word模式分词的结果会包含smart分词的结果,这 ...

  2. IK分词器原理与源码分析

    原文:http://3dobe.com/archives/44/ 引言 做搜索技术的不可能不接触分词器.个人认为为什么搜索引擎无法被数据库所替代的原因主要有两点,一个是在数据量比较大的时候,搜索引擎的 ...

  3. IK分词器 原理分析 源码解析

    IK分词器在是一款 基于词典和规则 的中文分词器.本文讲解的IK分词器是独立于elasticsearch.Lucene.solr,可以直接用在java代码中的部分.关于如何开发es分词插件,后续会有文 ...

  4. ElasticSearch已经配置好ik分词和mmseg分词(转)

    ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进行数据索引 ...

  5. Elasticsearch使用系列-ES增删查改基本操作+ik分词

    Elasticsearch使用系列-ES简介和环境搭建 Elasticsearch使用系列-ES增删查改基本操作+ik分词 一.安装可视化工具Kibana ES是一个NoSql数据库应用.和其他数据库 ...

  6. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例一.

    在这里一下讲解着三个的安装和配置, 是因为solr需要使用tomcat和IK分词器, 这里会通过图文教程的形式来详解它们的安装和使用.注: 本文属于原创文章, 如若转载,请注明出处, 谢谢.关于设置I ...

  7. ElasticSearch ik分词安装

    1.下载对应版本的ES ik分词 https://github.com/medcl/elasticsearch-analysis-ik/releases 2.解压elasticsearch-analy ...

  8. IK分词器 整合solr4.7 含同义词、切分词、停止词

    转载请注明出处! IK分词器如果配置成 <fieldType name="text_ik" class="solr.TextField"> < ...

  9. Elasticsearch5.1.1+ik分词器+HEAD插件安装小记

    一.安装elasticsearch 1.首先需要安装好java,并配置好环境变量,详细教程请看 http://tecadmin.net/install-java-8-on-centos-rhel-an ...

随机推荐

  1. KETTLE常见问题和优化

    1.创建MySQL空资源库报错问题:因为boolean类型的问题,Mysql中的boolean类型实际上保存为TINYINT,需要手动的修改生成资源库的sql脚本,将其中的插入用户ENABLED的值由 ...

  2. sshd服务以及基于口令的远程登陆

    ssh用为客户端,主要进行服务器端的连接:sshd用为服务器端 几个常用的命令: systemctl              ##服务控制命令   systemctl start sshd   ## ...

  3. linux 设置固定ip和dns

    目录 1. centos 1.1 ifconfig 查看网卡名称 1.2 设置固定ip和dns 1.3 重启网络 2. ubuntu 2.1 ifconfig 查看网卡名称 2.2 设置固定ip和dn ...

  4. 去重算法,简单粗暴&优化版

    Remove Repeat 一.去重原理 1.进行排序 2.判断是否满足 '两个字符串相同' 的条件,相同则累加重复次数,并使用continue继续下一次循环 3.当条件不满足时,将该字符串和累计数加 ...

  5. libpcap的下载与安装(apt-get安装unable to locate package 的解决方法(Ubantu))

    因为网络安全课的实验课要求,我们得下载libcap我们得做一个类似于tcpdump的一个东西.具体要求就不贴出来了. libpcap只能在官网(www.tcpdump.org)下到,我用的os是Ubu ...

  6. PHP数组与xml互相转换

    1.数组转xml function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key => $va ...

  7. 领扣(LeetCode)第三大的数 个人题解

    给定一个非空数组,返回此数组中第三大的数.如果不存在,则返回数组中最大的数.要求算法时间复杂度必须是O(n). 示例 1: 输入: [3, 2, 1] 输出: 1 解释: 第三大的数是 1. 示例 2 ...

  8. ACE框架 基于共享内存的分配器

    ACE框架提供了一个内存分配器模板,并且提供了(仅且)一个模板实例,基于共存内存的内存分配器.这个共存内存分配器模板实例在ACE框架应用于,基于内存映射的进程通讯,以及进程间同步等. ACE内存分配器 ...

  9. HTML的标签认识

    <!--      html标签     h1~h6 标题标签(只有1~6,依次减小)     p 段落标签     span 无意义的行标签     div 无意义的块标签     b 加粗 ...

  10. vue动态样式设置

    思路: 通过 v-bind:class="true ? style1 : style2 " 配合三元表达式完成样式的切换 具体实现 //return设置控制的参数 //有多个需要样 ...