ES3_2分析
搜索的前提是分析文档和搜索词。
分析器和倒排索引
一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。建立倒排索引的过程称为分析,执行分析过程的程序称为 分析器:
- 字符过滤器(Character Filters):字符串按顺序通过每个 字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉 HTML,或者将 & 转化成
and
。 - 分词器(Tokenizer):将待索引的内容拆分成单独的 词(我们称它为 词条 或 tokens ),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。
- Token 过滤器:删除无用词(a、and、the 等),合并统一大小写后相同的词(Quick 和 quick)、具有相同词根的词(fox 和 foxes),增加同义词(jump 和 leap)等。
内置分析器
“Set the shape to semi-transparent by calling set_trans(5)”
- 标准分析器
标准分析器是 Elasticsearch 默认使用的分析器。它是分析各种语言文本最常用的选择。它根据 Unicode 联盟 定义的 单词边界 划分文本(standard 分词器)。删除绝大部分标点(standard 语汇单元过滤器)。最后将词条小写(lowercase 语汇单元过滤器),stop 语汇单元过滤器是被禁用的,它会删除停用词–对搜索相关性影响不大的常用词,如 a , the , and , is ,如需启用它,你可以通过创建一个基于 standard 分析器的自定义分析器并设置 stopwords 参数,可以给分析器提供一个停用词列表,或者告知使用一个基于特定语言的预定义停用词列表。。它会产生:
set, the, shape, to, semi, transparent, by, calling, set_trans, 5 - 简单分析器
简单分析器在任何不是字母的地方分隔文本,将词条小写。它会产生:
set, the, shape, to, semi, transparent, by, calling, set, trans - 空格分析器
空格分析器在空格的地方划分文本。它会产生:
Set, the, shape, to, semi-transparent, by, calling, set_trans(5) - 语言分析器
特定语言分析器可用于 很多语言。它们可以考虑指定语言的特点。例如, 英语 分析器附带了一组英语无用词(常用单词,例如 and 或者 the ,它们对相关性没有多少影响),它们会被删除。 由于理解英语语法的规则,这个分词器可以提取英语单词的 词干 。英语 分词器会产生下面的词条(注意看 transparent、
calling 和 set_trans 已经变为词根格式):
set, shape, semi, transpar, call, set_tran, 5
常用字符过滤器
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-charfilters.html
字符过滤器用来整理 一个尚未被分词的字符串:
- Html 擦除字符过滤器
擦除像这样的 HTML 标签,以及将像Á转换为相对应的 Unicode 字符Á。
常用分词器
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html
分词器把字符串分解成单个词条或者词汇单元:
- 标准分词器
把一个字符串根据单词边界分解成单个词条,并且移除掉大部分的标点符号。 - 关键词分词器
完整地输出 接收到的同样的字符串,并不做任何分词。 - 空格分词器
只根据空格分割文本 。 - 正则分词器
根据匹配正则表达式来分割文本。
常用词单元过滤器
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenfilters.html
词单元过滤器可以修改、添加或者移除词单元:
- lowercase
- stop
- 词干
把单词 遏制 为 词干。 - ascii_folding
移除变音符,把一个像 “très” 这样的词转换为 “tres” 。 - ngram 和 edge_ngram
可以产生 适合用于部分匹配或者自动补全的词单元。
自定义分析器
- 一个分析器可以有多个过滤器及唯一一个分词器,自定义分析器的格式如下:
1
2
3
4
5
6
7
8
9
10
11PUT /my_index
{
"settings": {
"analysis": {
"char_filter": { ... custom character filters ... },
"tokenizer": { ... custom tokenizers ... },
"filter": { ... custom token filters ... },
"analyzer": { ... custom analyzers ... }
}
}
} - 下面创建了一个新的分析器,叫做 es_std , 并使用预定义的 西班牙语停用词列表:es_std 分析器不是全局的–它仅仅存在于我们定义的 spanish_docs 索引中。 为了使用 analyze API 来对它进行测试,我们必须使用特定的索引名,这会发现停用词 El 已被正确移除:
1
2
3
4
5
6
7
8
9
10
11
12
13PUT /spanish_docs
{
"settings": {
"analysis": {
"analyzer": {
"es_std": {
"type": "standard",
"stopwords": "_spanish_"
}
}
}
}
}1
2
3
4
5GET /spanish_docs/_analyze
{
"analyzer": "es_std",
"text": "El veloz zorro marrón"
} - 下面这个分析器除了使用 Html 擦除字符过滤器移除 HTML 部分、标准分词器分词、lowercase 词过滤器将单词转为小写,还使用一个自定义的字符过滤器把
&
替换为and
,一个自定义停词过滤器移除自定义的停止词列表中包含的词:调用下面的接口来测试:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22PUT /my_index
{
"settings": {
"analysis": {
"char_filter": {
"&_to_and": {
"type": "mapping",
"mappings": [ "&=> and "]
}},
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": [ "the", "a" ]
}},
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": [ "html_strip", "&_to_and" ],
"tokenizer": "standard",
"filter": [ "lowercase", "my_stopwords" ]
}}
}}}这个分析器现在是没有多大用处的,除非我们告诉 Elasticsearch在哪里用上它。我们可以像下面这样把这个分析器应用在一个 string 字段上:1
2
3
4
5GET /my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "The quick & brown fox"
}1
2
3
4
5
6
7
8
9PUT /my_index/_mapping/my_type
{
"properties": {
"title": {
"type": "string",
"analyzer": "my_analyzer"
}
}
}
分析器使用时机
- 索引一个文档时,它的全文域(包括自动给出的**_all**)被分析成词条以用来创建倒排索引。
具体的,当 Elasticsearch 在你的文档中检测到一个新的字符串域 ,它会自动设置其为一个全文 字符串 域,使用 标准 分析器对它进行分析。 - 还有在全文域搜索的时候,需要将查询字符串通过 相同的分析过程 ,以保证我们搜索的词条格式与索引中的词条格式一致(当查询一个精确值域时不会分析)。
- 或者直接使用以下链接测试分析器: 结果中的每个 token 都代表一个实际存储到索引中的词条, position 指明词条在原始文本中出现的位置。 start_offset 和 end_offset 指明字符在原始字符串中的位置。
1
2
3
4
5GET /_analyze
{
"analyzer": "standard",
"text": "Text to analyze"
}
自然语言与查询Recall
在处理人类自然语言时,有些情况,尽管搜索和原文不完全匹配,但是还是希望搜到一些内容(也即提升recall值):
- 归一化词元:比如played被转换为play。
- 抽取词根:清除单复述和时态的差异
- 包含同义词
- 拼写错误、同音异形词等
中文分词方法的演变
- 查字典
从左往右扫描一次,遇到有的词就标示出来,复合词就找最长的,不认识的就分割成单字词。 - 最小词数的分词理论
查字典方法的理论化
但仍有二义性问题 - 统计语言模型
解决二义性问题 - 基于统计的机器学习算法
中文分词器的现状是以统计语言模型为基础,使用机器学习算法和词典相结合的方式实现,一方面能够提高分词准确率,另一方面能够改善领域适应性。
不同分词器的好坏,主要差别在于数据的使用和工程使用的精度
一些中文分词器
- HanLP
- IK
混合多语言的场景
一些混合多语言的场景:
- 不同的索引使用不同的语言
- 同一个索引中,不同的字段使用不同的语言
- 一个文档的一个字段内混合不同的语言
混合多语言存在的一些挑战:
- 词干提取:一些中文文本中可能穿插了英文、拼音等。
- 不正确的文档频率:根据TF/IDF算法,匹配到的稀有词的算分可能会比较高,比如英文中出现的德文。
- 语言识别:识别用户输入的语言
分词挑战:
- 英文分词
You’re、Half-baked这种词要不要切分、分成一个还是多个 - 中文分词
具体情况需制定不同的标准:哈工大标准中姓和名分开,HanLP是在一起的
歧义(组合型歧义、交集型歧义、真歧义)
分析 - demo
1、standard
1 | GET _analyze |
注意结果中的:
- 按词切分,因此2会出现在结果中
- 大写的Hello和World被转换成小写了
- are这些停用词没有被真正去掉
2、simple
1 | GET _analyze |
- 按照非字母切分,非字母的都被去除,2也会被去掉
- 转小写处理
3、whitespace
1 | GET _analyze |
- 按空格切分,”-“、”!”还是保留的
4、stop
1 | GET _analyze |
- 相对simple Analyzer,多了停用词的过滤,因此are这些词会被去掉
5、keyword
1 | GET _analyze |
- 没有进行任何处理
6、pattern
1 | GET _analyze |
- 按正则表达式分割,默认按\W+识别
7、language analyzers
按语言分析
1 | GET _analyze |
- evening被改成了even,英文词被转换了
中文的词之间没有空格分隔,而且根据上下文不同也会有不同的分词方式,可以下载ICU插件实现中文分词:
https://blog.csdn.net/qq_34069839/article/details/107639301
1 | GET _analyze |
除了icu分词器外,还有ik、thulac等。