Elasticsearch调优篇 07 - Elasticsearch ik分词最全优化

背景

  这里介绍的优化是基于 ik 分词源码的优化。首先,我们知道,ik 分词默认有两种分词模式,分别为:ik_max_word 和 ik_smart

  这里针对这两种分词方式分别存在的问题有:

  ik_max_word :最细粒度分词方式

    分的太细了,召回率确实很高,但是会导致召回的内容存在语义问题。例如,北京的一天,召回了 南京的游玩,或者任何地方的一天等等。

  ik_smart:最粗颗粒度分词方式

    1. 分的太粗,保证了召回的精准性,但是召回率却很低。

    2. 存在歧义,导致召回了不是想要的结果集,例如:广西北海 --> 广西 | 西北 | 北海,找回去了西北相关的数据。

ik_smart 消歧逻辑

   

 

 

   当前 ik_smart 采用的是:贪心算法,分别为:

    有效文本长度->词元个数->路径跨越->词元位置->词长平均→词元位置权重

  可以在该算法的基础上进行改进

优化三部曲

  不管做什么优化,前提保证不影响原分词效果,故在原有基础之上增加一种新的分词方式,暂定为:ik

 去除语义覆盖的单字

  例:玻璃栈道 

  ik:玻璃栈道 | 玻璃 | 栈道 

  ik_max_word:玻璃栈道 | 玻璃 | 玻 | 璃 | 栈道 |   

  这里需要注意:在去除单字的时候需要考虑当前 token 所在位置与单字所在位置是否可覆盖,不可覆盖的情况下该单字是不能去除的,例如:

   月坨岛华清月府温泉酒店 --> 月坨岛 不能覆盖 华清月府 中的月,故不能因为月坨岛有月,在华清月府中就将单字 月 去掉,这是不对的。

 专有名词优化

  这个优化一般都是基于行业垂直领域来做的优化。先举例来说吧:

  普吉岛、印度尼西亚、香格里拉一日游,分出来的:普吉岛-->吉岛、印度尼西亚-->印度 以及 香格里拉-->里拉,这些都是另外的一个国家地名,都不是这个原词所表达的含义,也就是说想这类专有词就不应该再拆分了,拆分开就会导致语义失真。

  优化的方式就是将这些专有名词,这里指的是对应的 mdd、poi 等词用文件固话到 ik 分词器中,启动的时候通过 Dictionary 类去加载到内存,在分词链条中做对应的过滤处理即可。

  香格里拉一日游  :原始 ik 分词结果 →  香格里拉|香格|格里拉|格里|里拉|一日游|一日| 

                                新版 ik 分词结果 →  香格里拉|一日游|一日|

 去歧处理

  借鉴 jieba 分词方式,修改词库文件格式。因为 ik 分词器词典格式为一行一词,需要进行改进,在词典中加入对应挖掘的词频,以及词性。

  词典结构为: 单词  词频  词性  ,例如: 西安  2000  n

  需要对ik源码中词典结构进行修改。

  这里可以提供点改动思路,详情想了解的可以私信我吧,毕竟属于公司内部的:

  利用 es 提供的接口,将词库中所有的词分别获取一遍对应的词频,这个是可以取到的。

  而且使用 es 获取业务内部的词频更加准确有效,比起从人民日报资源中挖掘出的,直接应用在项目中要好太多了。

  其次可以利用第三方接口来得到对应词的词性,这个也很容易拿到,这样词典格式改造就可以轻松的完成了。剩下的就是 ik 源码的改造:

  一是首先修改 Dictionary 加载词典的方式;

  二是改造去歧逻辑,优化的地方采用的是:

    在ik进行前三步判断后: 有效文本长度->词元个数→路径跨越 ,如果还剩多个候选集,后三步骤结合jieba分词中的动态规划计算组合的成词概率来进行去歧处理。

 

posted @ 2020-06-26 23:50  星火燎原智勇  阅读(2688)  评论(1编辑  收藏  举报