如何自定义ES中文分词词库?调研了一周无果后,同事告诉我只需这样点两下……
背景
作为当下最流行的全文搜索引擎,ES具备丰富的文本分析能力,其中它自带的中文分词插件 Ik分词器 在日常项目中也受到了广泛应用。
IK分词器虽然解决了很多需要中文分词的场景需求,但是它终归是基于自己的一套 默认词库 做的分词,在特定行业领域或者定制化需求中,IK的分词效果往往不能尽如人意。
例如使用 ik_smart 对 蓝牙耳机 进行分词后,结果为两个词元 蓝牙 和 耳机 。
这是因为在IK默认的分词词库中,存在有对应两个词元的数据信息:
如果业务需求上我们不想将 蓝牙耳机 这个词拆分,这就需要去补充和 自定义IK分词词库。
分词介绍
分词器
常见中文分词器
分词器 |
优势 |
劣势 |
|
IK Analyzer |
简单易用,支持自定义词典和远程词典 |
词库需要自行维护,不支持词性识别 |
https://github.com/medcl/elasticsearch-analysis-ik |
Ansj |
分词精准度不错,支持词性识别 |
对标hanlp词库略少,学习成本高 |
https://github.com/NLPchina/elasticsearch-analysis-ansj |
jieba |
新词发现功能 |
不支持词性识别 |
https://github.com/sing1ee/elasticsearch-jieba-plugin |
Smart Chinese Analyzer |
官方插件 |
中文分词效果惨不忍睹 |
https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-smartcn/analysis-smartcn-7.16.1.zip |
Hanlp |
目前词库最完善,支持的特性非常多 |
需要更优的分词效果,学习成本高 |
https://github.com/hankcs/HanLP/releases |
ElasticSearch的分词器作用是从文本中提取若干词元(token)来支持索引的存储和搜索。
分词器(Analyzer)由字符过滤器(Character Filters)、分解器(Tokenizer)和过滤器(Token Filters)组成。
字符过滤器(Character Filters)
字符过滤器以字符流的形式接收原始文本,并可以通过添加、删除或更改字符来转换,比如去除html的特殊标记符。一个 Analyzer 可能有0个或多个字符过滤器。
分解器(Tokenizer)
将字符串分解成一系列词元(Token)。比如使用 whitespace 分词器,当遇到空格时会将文本拆分成token。“eating an apple” 被分词为 [eating, an, apple]。一个 Analyzer 有且仅有一个分解器。
词元过滤器(Token Filters)
针对分词后的 token 进行再一步的处理,例如转小写和增加同义词等,处理后的结果成为索引词(Term),引擎会建立索引词(Term)和源文档的倒排索引(Inverted Index),这样就能根据Term很快查到源文档了。一个 Analyzer 可能有0个或多个token过滤器。
ES自带分词器
分词器 |
分词策略 |
Standard Analyzer |
默认分词器,按词切分,支持多语言小写处理。 |
Simple Analyzer |
按照非字母切分,小写处理。 |
Whitespace Analyzer |
空白字符作为分隔符 |
Stop Analyzer |
相比Simple Analyzer,去除停用词处理,停用词指语气助词等修饰性词语,如the, an, 的 等 |
Keyword Analyzer |
不分词,直接将输入作为一个单词输出 |
Pattern Analyzer |
通过正则表达式自定义分隔符,默认是\W+,即非字词的符号作为分隔符 |
除了本身含有的分词器,ES还提供了很多分词器插件。
其中IK分词器是处理中文最常见、最普遍的分词器插件。它根据本地自己维护的词典进行分词,支持两种分词形式:
ik_smart:将一个中文字符进行最少次数的切分。
ik_max_word:将一个中文字符进行最细粒度的切分。
最佳实践:索引建立时使用ik_max_smart,查询时使用ik_smart
IK 词库目录
该目录下带有许多文件,含义如下
main.dic ik原生内置的中文词库,里面有275909 条现成的词语
quantifier.dic 量词和单位名称,如个,斤,克,米之类的
suffix.dic 常见后缀词,如江,村,省,市,局等
surname.dic 中国姓氏
stopword.dic 停用词,目前默认的是写的几个英文单词,如and,a,the等
preposition.dic 副词、语气助词,连接词等无实际含义的词语,如却,也,是,否则之类的
6.3.1版本的IK分词器还提供了额外的词库补充文件,extra 开头的那几个就是,默认没有使用,有需要可以在配置文件IKAnalyzer.cfg.xml上添加。
最重要的是 main.dic 和 stopword.dic。stopword(停用词)在分词时会直接被干掉,不会建立在倒排索引中。
ES提供了很多类型的分词器,但是它们的分词策略都是 插件自定义 的。
很多时候我们在业务上想要使用 自定义的词典规则 进行分词查询,这样一方面会提高查询效率,另一方面可以更加精准匹配数据。
自定义词库
1. 词库准备
算法团队产出
互联网开源词库
爬虫获取特定领域词库
2. 词库清洗
借助第三方工具或者通过程序脚本,将文本词汇 去重(每个分词占一行),并生成 .dic 文件
3. 配置
进入 ES 安装目录 /config/analysis-ik/,新建 ext.dic 文件‘
打开并编辑 IKAnalyzer.cfg.xml 文件
${es_home}/config/analysis-ik/IKAnalyzer.cfg.xml
将 ext.dic 词库添加到 IK 配置文件中
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">words_location</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<entry key="remote_ext_stopwords">words_location</entry>
</properties>
4. 重启ES集群
重新启动 ElasticSearch节点,验证分词效果。
由于 ES分段不可修改,新拓展的词库只对拓展后写入的数据生效。
可以通过 全量重刷数据 或者 reindex 使新词库数据全部生效。
转折???
以上是基于自建的ElasticSearch服务器,如果你买的是阿里云ES服务,只需要ES后台插件配置中新增词库就好了。
阿里云首次添加词库同样需要 重启集群
另外词库添加完成之后记得重建倒排索引更新数据哈