分词器(es分词器)

http://www.itjxue.com  2023-01-27 12:35  来源:未知  点击次数: 

ES自定义分词器

es的分词器往往包括3个低级构建块包:

Standard Analyzer

标准分析仪按照Unicode文本分段算法的定义,将文本分割成单词边界的分词。它删除了大多数标点符号,小写显示分词,并支持删除stop words。

Simple Analyzer

当遇到不是字母的字符时,简单的分析器会将文本分成条目。小写显示分词。

Whitespace Analyzer

空格分析器遇到任何空格字符时都会将文本分为多个项目。不会把分词转换为小写字母。

Stop Analyzer

停止分析仪和Simple Analyzer类似,但也支持stop words的删除。

Keyword Analyzer

一个“noop”分析器,它可以接受任何给定的文本,并输出完全相同的文本作为一个单词。

Pattern Analyzer

使用正则表达式拆分分词,支持lower-casing和stop words。

Language Analyzers

Elasticsearch提供许多语言特定的分析器,如英语或法语。

Fingerprint Analyzer

一个专门的分析仪,它可以创建一个可用于重复检测的指纹。

对中文文本以英文逗号作为分隔符分词:

将分析器设置到索引上

获取分词结果

es 节点层面的默认分词设置已经废弃,不支持了。就是说在 elasticsearch.yml 配置诸如:

无效,会导致es启动失败:

推荐在索引层面动态设置。

ICTCLAS中文分词器(现在叫nlpir)

ICTCLAS(现在叫nlpir)是中科院张华平博士开发中文分词器。NLPIR分词系统前身为2000年发布的ICTCLAS词法分析系统,从2009年开始,为了和以前工作进行大的区隔,并推广NLPIR自然语言处理与信息检索共享平台,调整命名为NLPIR分词系统。

ICTCLAS by sennchi

ElasticSearch 分词器,了解一下

这篇文章主要来介绍下什么是 Analysis ,什么是分词器,以及 ElasticSearch 自带的分词器是怎么工作的,最后会介绍下中文分词是怎么做的。

首先来说下什么是 Analysis:

顾名思义,文本分析就是 把全文本转换成一系列单词(term/token)的过程 ,也叫 分词 。在 ES 中,Analysis 是通过 分词器(Analyzer) 来实现的,可使用 ES 内置的分析器或者按需定制化分析器。

举一个分词简单的例子:比如你输入 Mastering Elasticsearch ,会自动帮你分成两个单词,一个是 mastering ,另一个是 elasticsearch ,可以看出单词也被转化成了小写的。

再简单了解了 Analysis 与 Analyzer 之后,让我们来看下分词器的组成:

分词器是专门处理分词的组件,分词器由以下三部分组成:

同时 Analyzer 三个部分也是有顺序的,从图中可以看出,从上到下依次经过 Character Filters , Tokenizer 以及 Token Filters ,这个顺序比较好理解,一个文本进来肯定要先对文本数据进行处理,再去分词,最后对分词的结果进行过滤。

其中,ES 内置了许多分词器:

接下来会对以上分词器进行讲解,在讲解之前先来看下很有用的 API: _analyzer API :

它可以通过以下三种方式来查看分词器是怎么样工作的:

再了解了 Analyzer API 后,让我们一起看下 ES 内置的分词器:

首先来介绍下 Stamdard Analyzer 分词器:

它是 ES 默认的分词器 ,它会对输入的文本 按词的方式进行切分 ,切分好以后会进行 转小写 处理, 默认的 stopwords 是关闭的 。

下面使用 Kibana 看一下它是怎么样进行工作的,在 Kibana 的开发工具(Dev Tools)中指定 Analyzer 为 standard ,并输入文本 In 2020, Java is the best language in the world. ,然后我们运行一下:

运行结果如下:

可以看出是按照空格、非字母的方式对输入的文本进行了转换,比如对 Java 做了转小写,对一些停用词也没有去掉,比如 in 。

其中 token 为分词结果; start_offset 为起始偏移; end_offset 为结束偏移; position 为分词位置。

下面来看下 Simple Analyzer 分词器:

它只包括了 Lower Case 的 Tokenizer ,它会按照 非字母切分 , 非字母的会被去除 ,最后对切分好的做 转小写 处理,然后接着用刚才的输入文本,分词器换成 simple 来进行分词,运行结果如下:

从结果中可以看出,数字 2020 被去除掉了,说明非字母的的确会被去除,所有的词也都做了小写转换。

现在,我们来看下 Whitespace Analyzer 分词器:

它非常简单,根据名称也可以看出是 按照空格进行切分 的,下面我们来看下它是怎么样工作的:

可以看出,只是按照空格进行切分, 2020 数字还是在的, Java 的首字母还是大写的, , 还是保留的。

接下来看 Stop Analyzer 分词器:

它由 Lowe Case 的 Tokenizer 和 Stop 的 Token Filters 组成的,相较于刚才提到的 Simple Analyzer ,多了 stop 过滤,stop 就是会把 the , a , is 等修饰词去除,同样让我们看下运行结果:

可以看到 in is the 等词都被 stop filter 过滤掉了。

接下来看下 Keyword Analyzer :

它其实不做分词处理,只是将输入作为 Term 输出,我们来看下运行结果:

我们可以看到,没有对输入文本进行分词,而是直接作为 Term 输出了。

接下来看下 Pattern Analyzer :

它可以通过 正则表达式的方式进行分词 ,默认是用 \W+ 进行分割的,也就是非字母的符合进行切分的,由于运行结果和 Stamdard Analyzer 一样,就不展示了。

ES 为不同国家语言的输入提供了 Language Analyzer 分词器,在里面可以指定不同的语言,我们用 english 进行分词看下:

可以看出 language 被改成了 languag ,同时它也是有 stop 过滤器的,比如 in , is 等词也被去除了。

最后,让我们看下中文分词:

中文分词有特定的难点,不像英文,单词有自然的空格作为分隔,在中文句子中,不能简单地切分成一个个的字,而是需要分成有含义的词,但是在不同的上下文,是有不同的理解的。

比如以下例子:

那么,让我们来看下 ICU Analyzer 分词器,它提供了 Unicode 的支持,更好的支持亚洲语言!

我们先用 standard 来分词,以便于和 ICU 进行对比。

运行结果就不展示了,分词是一个字一个字切分的,明显效果不是很好,接下来用 ICU 进行分词,分词结果如下:

可以看到分成了 各国 , 有 , 企业 , 相继 , 倒闭 ,显然比刚才的效果好了很多。

还有许多中文分词器,在这里列举几个:

IK :

jieba :

THULAC :

大家可以自己安装下,看下它中文分词效果。

本文主要介绍了 ElasticSearch 自带的分词器,学习了使用 _analyzer API 去查看它的分词情况,最后还介绍下中文分词是怎么做的。

ElasticSearch 中文分词器对比

对以上分词器进行了一个粗略对比:

截止到目前为止,他们的分词准确性从高到低依次是:

结合准确性来看,选用中文分词器基于以下考虑:

截止目前,IK分词器插件的优势是支持自定义热更新远程词典。

IK分词器的github地址:

hanlp中文分词器的官网为:

hanlp中文分词器的github地址为:

ES中文分词器之精确短语匹配(解决了match_phrase匹配不全的问题)

调研了几种分词器,例如IK分词器,ansj分词器,mmseg分词器,发现IK的分词效果最好。举个例子:

在上述例子中,IK和Mmsg 用的同一套词典。Ansj和IK,Mmsg使用的不是一套词典,也没有配置停词。

本文讲的中文分词器就是IK分词器。

楼主意淫着将所有的单字放入词典中,这样用ik_max_word 对数据建索引时既可以把词分出来建索引,又可以把字分出来建索引。然后用 ik_smart 将查找短语,因为ik_smart分出的数据是 ik_max_word 的一个子集,如果要查找的短语在原文中有出现,那么一定可以查到。后来发现用ik_smart分词器查找句子(match_phrase)时一个都没有查到,exo???为什么会查不到呢?明明是一个子集。对此官方网站对match_phrase的解释如下:

意思就是说用match_phrase查找时,查找分词器分出的词的位置和要建索引时分出的词的位置一样。举个例子:

从上面可以看出,查找时ik_smart将语句分为了快乐和感恩两个词,位置分别为1和2,而ik_max_word建索引时,快乐和感恩的位置分别是1和4,在match_phrase看来,这种是不匹配的,所以用ik_smart分词短语时无法查到或者查全数据。

好吧,既然ik_smart无法查到,我用ik_max_word查找总行了吧。用上述的例子,查找”快乐“时,你会发现你用ik_max_word查找到的结果没有standard分词器建索引查找获取到的结果多。原因和上述讲的一样:

在构建索引的时候,快乐,快和乐的位置分别是1,2,4,而查找时分词的顺序是1,2,3,然后match_phrase认为其不匹配,因此查询不到这种结果。

遇到问题了,在网上寻求解决方案。看了几篇博客,都指出了match_phrase的这个匹配问题,解决方案有以下两种:

standard分词器大家都比较熟,针对于汉字就是一个一个分,这种肯定是可以查全的。但一个一个字分的话,每个字对应的文档集合非常多,如果数据量达到了百亿,在求交集,计算距离时,效果非常差。

Ngram分词器类似于standard分词器,他可以指定分词的长度,然后用standard的方法切割。比如说“节日快乐”,我们指定切割的长度为2,NGram会切成“节日”,“日快”,“快乐”。虽然查找时可以减少每个token对应的文档数,但是存储量会增大很多,而且不在支持模糊的match匹配。很土。

ik_max_word构建索引,ik_smart无法查找,原因是ik_max_word分出了所有的词,ik_smart只分出了一种词,由于match_phrase本身的限制导致ik_smart查找不到。那我构建的时候采用ik_smart,查找的时候也用ik_smart,这样只要原文中有数据,构建和查找用同一种分词方法,就应该可以查找得到。测试后发现,这种也有很大的问题,即像“潜行者”这样的词,只分为了“潜行”和“者”两个token,但是“行者”也是一个词,在查找“行者”时无法查全数据。

ik_smart无法查全的原因是只分出了一种词的可能性,导致有些词查询不全。ik_max_word能解决这个问题。。但是ik_max_word的问题是如果查找的最后一个字能和原文中这个字的下一个字组成词语,那么就会出现无法查全的问题。我们能不能让ik_max_word将词和字分开?

当然可以,对一个属性指定两种分词方法:

这样ulluin属性采用standard分词,即单字分词,ulluin.ik采用ik_max_word即按词分词, ik_max_word的词典中去除所有的单字 。

查询时先将查询短语分词,如果第一个token和最后一个token中存在一个字,那么这个字可能与原文中的下一个字或者上一个字组成词,导致ik_max_word无法查到,这时我们用standard分词器在ulluin中查询,如果第一个token和最后一个token都是词,那么说明可以在ik_max_word中查询。来吧,测试一下:

为什么还是有问题?????ik_max_word查出的数据量比standard的少???还是因为match_phrase的限制,索引中“节日”和“快乐”的位置是1和3,而查找时“节日”和“快乐”的位置是1和2。这个问题很好解决,用match_phrase_prefix查询即可,即:

上面还提到ik_max_word有一个问题是分出的词语比standard的多,我们过滤了单字分词后,这个效果就会有很大的提升。假设我们的词典没有四字分词,只有二三字。比如说

可以看出,修改后的效果要比standard的效果好的多,不但token数变少了,而且每个token对应的文档数也大大的降低,减少了求交集的数据量和计算距离的数据量。

至此总算解决了ES中文分词切精确匹配的问题。

ES中的分词器

全文搜索引擎会用某种算法对要建索引的文档进行分析, 从文档中提取出若干 Token(词元) , 这些算法称为 Tokenizer(分词器) , 这些Token会被进一步处理, 比如转成小写等, 这些处理算法被称为 Token Filter(词元处理器) ,被处理后的结果被称为 Term(词) , 文档中包含了几个这样的Term被称为 Frequency(词频) 。 引擎会建立Term和原文档的Inverted Index(倒排索引), 这样就能根据Term很快到找到源文档了。 文本被Tokenizer处理前可能要做一些预处理, 比如去掉里面的HTML标记, 这些处理的算法被称为 Character Filter(字符过滤器) , 这整个的分析算法被称为 Analyzer(分析器) 。

整个分析过程,如下图所示:

从第一部分内容可以看出:Analyzer(分析器)由Tokenizer(分词器)和Filter(过滤器)组成。

ES允许用户通过配置文件elasticsearch.yml自定义分析器Analyzer,如下:

上面配置信息注册了一个分析器myAnalyzer,在次注册了之后可以在索引或者查询的时候直接使用。该分析器的功能和标准分析器差不多,tokenizer: standard,使用了标准分词器 ;filter: [standard, lowercase, stop],使用了标准过滤器、转小写过滤器和停用词过滤器。

ElasticSearch默认使用的标准分词器在处理中文的时候会把中文单词切分成一个一个的汉字,所以在很多时候我们会发现效果并不符合我们预期,尤其在我们使用中文文本切分之后本该为一个词语却成了单个的汉字,因此这里我们使用效果更佳的中文分词器es-ik。

ik 带有两个分词器:

区别:

下面我们来创建一个索引,使用 ik。创建一个名叫 iktest 的索引,设置它的分析器用 ik ,分词器用 ik_max_word,并创建一个 article 的类型,里面有一个 subject 的字段,指定其使用 ik_max_word 分词器。

批量添加几条数据,这里我指定元数据 _id 方便查看,subject 内容为我随便找的几条新闻的标题

查询 “希拉里和韩国”

这里用了高亮属性 highlight,直接显示到 html 中,被匹配到的字或词将以红色突出显示。若要用过滤搜索,直接将 match 改为 term 即可。

(责任编辑:IT教学网)

更多

相关网页文字特效文章

推荐网页文字特效文章