如何提升elasticsearch中文搜索能力(自己动手训练ik中文词典)
选择一个好用的中文分词器
补充:
1.medcl/elasticsearch-analysis-ik github.com/medcl/elast…
优点:
被使用量远超过其它中文分词器几个数量级别,插件更新快能跟上elasticsearch更新
缺点:
但是词典过时比较严重,缺少新词识别的能力
2.jieba/nlp
sing1ee/elasticsearch-jieba-plugin
KennFalcon/elasticsearch-analysis-hanlp
优点:
具有发现新词能力,python版本jieba,能开启PaddlePaddle(百度飞桨)模式,使用深度学习方式进行分词,elasticsearch版本插件是否支持开启Paddle模式未知。
hanlp应该是目前中文自然语言分析能力最强的开源项目
缺点:
插件非官方支持,更新比较慢,被使用次数少.
截止2021-12-24,elasticsearch已经更新到7.16,hanlp elasticsearch 插件目前最高只支持到7.10
jieba需要自己改适配版本重新编译,看了下jieba的词典库也比较老
本人目前使用的elasticsearch 版本为7.15,因此决定继续使用ik分词器,但是要对ik分词能力弱的问题进行提升。 方案:使用python版jieba/hanlp和手上中文内容,手动训练额外中文词典,作为对ik的补充
自定义Ik分词器词典
下载 第三方词典 作为ik 分词补充
《现代汉语词典》(第7版)
CNMan/XDHYCD7th
github.com/pwxcoo/chin…
中华新华字典数据库
pwxcoo/chinese-xinhua
github.com/pwxcoo/chin…
自己训练词典提升ik能力(jieba版本)
1.下载jieba分词,安装百度飞桨模式插件
2.下载IK已有的词库
3.下载最新中文停用词表
4.选择提取新词用的数据源(中文语料库)
网上很多
5.代码
# encoding=utf-8
import jieba
import json
import re
def stopwordslist():
stopwords_file = '../../app/Services/stopwords.txt'
stopwords = [line.strip() for line in open(stopwords_file,encoding='UTF-8').readlines()]
return stopwords
def ikwordslist():
stopwords_file = './ik.txt'
stopwords = [line.strip() for line in open(stopwords_file,encoding='UTF-8').readlines()]
return stopwords
stopwords = stopwordslist()
ikwords = ikwordslist()
total_word = []
filename = 'titles.txt'
current = 0
print("开始进行分词")
count = len(open(filename,'r').readlines())
with open(filename,'r') as f:
for line in f.readlines():
linestr = line.strip()
# data = json.loads(linestr)
seg_list = list(jieba.cut(linestr))
# ret = [ i for i in seg_list if i not in stopwords ]
current+=1
if current%1000 == 0:
print("{}/{}".format(current,count))
seg_list = list(set(seg_list))
for word in seg_list:
match = re.match(u"^[\u4e00-\u9fa5]*$", word )
if match:
total_word.append(word)
total_word = list(set(total_word))
print("过滤停用词")
ret = [ i for i in total_word if i not in stopwords ]
print("过滤IK分词器已有词典")
ret2 = [ i for i in ret if i not in ikwords ]
ret2.sort()
with open ("it_cn_words.txt", "w") as thefile:
thefile.write("\n".join(ret2))
6.设置elastcisearh ik分词额外词典
github.com/medcl/elast… 详见ik插件文档
7.重启/测试
使用原生ik词典ik_smart测试:
GET _analyze
{
"analyzer": "ik_smart",
"text": ["中国科学院计算所如何在html中引入javaScript代码"]
}
分词结果
中国科学院,计算所,如,何在,html,中,引入,javascript,代码
后总结: jieba paddle模式不理想,分词时候对受到空格和特殊符号影响很大,分词结果有点莫名其妙 如:
每日一博 | 一文搞懂SaaS困境、API经济与Serverless WebAssembly
正常模式:
['每日', '一博', ' ', '|', ' ', '一文', '搞懂', 'SaaS', '困境', '、', 'API', '经济', '与', 'Serverless', ' ', 'WebAssembly']
飞桨模式:
['每日', '一博 | 一文搞懂SaaS困境、API经济与Serverless WebAssembly']
jieba 默认模式效果也有点过头 也会发现很多莫名其妙新词,例如
中三大
中不为
中不写
中不出
中不受
中不含
中不太
中不常
中不随
中与子
To be continue
结巴新词发现功能过头的原因,应该和新词发现时候对于词性的判断不ok, 下载尝试,带有词性识别和中文nlp能力的hanlp,看看效果如何