从第一章翻译Elasticsearch官方指南Controlling Relevance一章。

控制相关度(Controlling Relevance)

对于仅处理结构化数据(比方日期。数值和字符枚举值)的数据库,它们仅仅须要检查一份文档(在关系数据库中是一行)是否匹配查询就可以。

虽然布尔类型的YES|NO匹配也是全文搜索的一个必要组成。它们本身是不够的。我们还须要知道每份文档和查询之间的相关程度。全文搜索引擎不仅要找到匹配的文档,还须要依据相关度对它们进行排序。

全文搜索相关度的公式,或者被称为相似度算法。将多个因素综合起来为没份文档产生一个相关度_score。在本章中。我们来讨论一下当中的一些变化的部分以及怎样控制它们。

当然相关度并不仅仅和全文查询相关;它或许会将结构化数据考虑在内。

我们可能在寻找一个拥有某些卖点(空调。海景,免费的WiFi)的度假旅店。

那么当某个度假旅店拥有的卖点越多。那么它也就越相关。或者我们希望除全文搜索本身的相关度外。同一时候将时间的远近,价格。流行度或者距离这类因素也考虑在内。

以上这些设想都是能够实现的,得益于ES中强大的分值计算功能。

我们首先会从理论角度来看看Lucene是怎样计算相关度的,然后从实际的样例出发来讨论一下怎样来控制该过程。

相关度分值计算背后的理论

Lucene(也就是ES)使用了布尔模型(Boolean Model)来寻找匹配的文档,以及一个被称为Prarical
Scoring Function
的公式来计算相关度。该公式借用了词条频度/倒排文档频度以及向量空间模型的概念,同一时候也添加了一些更现代的特性比方Coordination Factor,字段长度归约。以及词条/查询子句提升。

NOTE

不要害怕!这些概念并不像它们的名字那般复杂。

虽然在这一节中提到了算法,公式以及数学模型,它们的作用也仅仅只是是方便人类理解。理解算法本身并不比理解它们对结果的影响更重要。

布尔模型(Boolean
Model)

布尔模型简单地应用查询中的AND。OR以及NOT条件来寻找全部匹配的文档。以下的查询:

full AND text AND search AND (elasticsearch OR lucene)

会仅仅包含含有全部full,text。search词条。以及词条elasticsearch或者lucene之中的一个的文档。

这个过程是简单且迅速的。

它用来排除那些不会匹配查询的文档。

词条频度/倒排文档频度(TF/IDF)

一旦我们拥有了匹配文档的列表。我们就须要对它们进行相关度排序。并非全部的文档都会包括全部的词条。而一部分词条也比还有一部分的词条更加重要。

整个文档的相关度分值取决于(部分)出如今文档中的每一个查询词条的权重。

一个词条的权重通过三个因素决定。这在什么是相关度中已经介绍过了。

对该公式的介绍是为了兴趣,你不须要记住它们。

词条频度(Term Frequency)

词条在当前文档中出现的有多频繁?越频繁的话,那么权重就越高。在一个字段中出现了5次的词条应该比仅仅出现了1次的文档更加相关。

词条频度通过以下的公式进行计算:

tf(t in d) = √frequency

词条t在文档d中的词条频度tf,是该词条在文档中出现次数的平方根。

假设你不在乎一个词条在一个字段中的出现频度。相反你在意的是词条是否出现过。那么你能够在字段映射中禁用词条频度:

PUT /my_index
{
"mappings": {
"doc": {
"properties": {
"text": {
"type": "string",
"index_options": "docs"
}
}
}
}
}

将index_options设置为docs会禁用词条频度以及词条位置信息。使用了该设置的字段不会记录词条出现的次数,也不能被用在短语或者邻近度查询中。精确值的not_analyzed字符串字段默认使用该设置。

倒排文档频度(Inverse Document Frequency)

词条在全部的文档中出现的频繁吗?出现的越频繁,权重就越低。像and或者the这种常见词条对相关度的贡献差点儿没有,由于它们在绝大多数的文档中都会出现。而像elastic或者hippopotamus这种罕见词条则可以帮助找到我们最感兴趣的文档。倒排文档频度的计算方法例如以下:

idf(t) = 1 + log ( numDocs / (docFreq + 1))

对于词条t的倒排文档频度(idf)。通过将索引中的文档数量除以含有该词条的文档数量,再取其对数得到。

字段长度归约(Field-length Norm)

字段的有多长?字段越短。那么其权重就越高。假设一个词条出如今较短的字段,如title字段中,那么该字段的内容相比更长的body字段而言。更有可能是关于该词条的。字段长度归约的计算方法例如以下:

norm(d) = 1 / √numTerms

虽然字段长度归约对于全文搜索而言是重要的,也有很多其他字段不须要。不管文档是否含有该字段,对于索引中每份文档的每一个字符串字段,归约大概需消耗1个字节的空间。对于精确值的not_analyzed字符串字段,归约功能默认是被禁用的。可是你也能够对analyzed类型的字段通过字段映射禁用归约:

PUT /my_index
{
"mappings": {
"doc": {
"properties": {
"text": {
"type": "string",
"norms": { "enabled": false }
}
}
}
}
}

在以上的样例中,该字段不会将字段长度归约考虑在内。这就意味着字段的长度不再被相关度计算考虑在内。

对于日志记录这样的用例,归约是没有多大用处的。你在意的仅仅是某个特定错误代码或者某个浏览器标识码是否出如今了某个字段中。字段的长度不会对结果造成影响。禁用归约功能也能够省下相当的内存空间。

结合起来

以上的三个因素 - 词条频度。倒排文档频度以及字段长度规范 - 都是在索引期间被计算和保存的。

它们被用来计算单个词条对于某一份文档的权重。

TIP

我们前面讨论的文档,实际上是在讨论文档中的字段。

每一个字段都有它自己的倒排索引,因此对于TF/IDF而言,字段的值和文档的值是等效的。

当我们将explain设置为true(參考理解分值(Understanding the Score)),然后再执行简单的term查询时,你会发现參与到分值计算过程中的因素就是我们前面讨论的那些:

PUT /my_index/doc/1
{ "text" : "quick brown fox" } GET /my_index/doc/_search? explain
{
"query": {
"term": {
"text": "fox"
}
}
}

前面的请求得到的解释(有省略)例如以下所看到的:

weight(text:fox in 0) [PerFieldSimilarity]: 0.15342641 result of: fieldWeight in 0 0.15342641 product of: tf(freq=1.0), with freq of 1: 1.0 idf(docFreq=1, maxDocs=1): 0.30685282 fieldNorm(doc=0): 0.5

第一行:对于Lucene内部文档ID为0的文档,词条fox在其text字段中的终于分值。

第五行 - 第七行:词条频度,倒排文档频度以及字段长度归约得到的结果。

当然,查询通常都会由不止一个词条组成,因此我们须要一种将多个词条的权重联系起来的方法。为此我们能够求助向量空间模型(Vector Space Model)。

向量空间模型

向量空间模型提供了一种多词条查询的比較方法。它的输出是一个代表了文档和查询之间匹配程度的分值。为了计算该分值,文档和查询都被表示成向量。

一个向量实际上就是一个包括了数值的一维数组,比方:

[1,2,5,22,3,8]

在向量空间模型中。向量中的每一个数值都是由TF/IDF计算得到的一个词条的权重。

TIP

虽然TF/IDF是在向量空间模型中默认被用来计算词条权重的方法,它并非唯一可用的方法。在ES中,其他诸如Okapi-BM25的计算模型也是可用的。TF/IDF因为其简洁性。高效性。产生的搜索结果的高质量而经受了时间的考验,从而被当做是默认方法。

如果我们查询了"happy hippopotamus"。一个像happy这种常见单词的权重是较低的,然而像hippopotamus这种罕见单词则拥有较高的权重。

如果happy的权重为2而hippopotamus的权重为5。

我们能够使用坐标来表达这个简单的二维向量 - [2, 5] - 一条从坐标(0, 0)到坐标(2, 5)的直线,例如以下所看到的:

如今,如果我们有三份文档:

  1. I am happy in summer.
  2. After Christmas I’m a hippopotamus.
  3. The happy hippopotamus helped Harry.

我们能够为每份文档创建一个类似的向量,它由每一个查询词条的权重组成 - 也就是出如今文档中的词条happy和hippopotamus,然后将它绘制在坐标中,例如以下图:

  • 文档1:(happy,____________) — [2,0]
  • 文档2:( ___ ,hippopotamus) — [0,5]
  • 文档3:(happy,hippopotamus) — [2,5]

向量的一个非常棒的性质是它们可以被比較。通过測量查询向量和文档向量间的角度。我们可以给每份文档计算一个相关度分值。文档1和查询之间的角度较大,因此它的相关度较低。文档2和查询更靠近,所以它的相关度更高,而文档3和查询之间则是一个完美的匹配。

TIP

实际上。仅仅有二维向量(使用两个词条的查询)才可以被简单地表示在坐标中。幸运的是,线性代数 - 数学的一个分支,可以处理向量 - 提供了用来比較多维向量间角度的工具。这意味着我们可以使用上述原理对包括非常多词条的查询进行处理。

你能够获得关于使用余弦相似性来比較两个向量的很多其它信息:http://en.wikipedia.org/wiki/Cosine_similarity

我们已经讨论了点值计算的理论基础。现在让我们来看看Lucene什么分歧值计算。

[Elasticsearch] 控制相关性 (一) - 后面的相关度分值理论计算的更多相关文章

  1. 用 Mahout 和 Elasticsearch 实现推荐系统

    原文地址 本文内容 软件 步骤 控制相关性 总结 参考资料 本文介绍如何用带 Apache Mahout 的 MapR Sandbox for Hadoop 和 Elasticsearch 搭建推荐引 ...

  2. ElasticSearch 2 (18) - 深入搜索系列之控制相关度

    ElasticSearch 2 (18) - 深入搜索系列之控制相关度 摘要 处理结构化数据(比如:时间.数字.字符串.枚举)的数据库只需要检查一个文档(或行,在关系数据库)是否与查询匹配. 布尔是/ ...

  3. elasticsearch 深入 —— 相关度控制

    控制相关度 处理结构化数据(比如:时间.数字.字符串.枚举)的数据库, 只需检查文档(或关系数据库里的行)是否与查询匹配. 布尔的是/非匹配是全文搜索的基础,但不止如此,我们还要知道每个文档与查询的相 ...

  4. Elasticsearch BM25相关度算法超详细解释

    Photo by Pixabay from Pexels 前言:日常在使用Elasticsearch的搜索业务中多少会出现几次 "为什么这个Doc分数要比那个要稍微低一点?".&q ...

  5. Elasticsearch工作原理

    一.关于搜索引擎 各位知道,搜索程序一般由索引链及搜索组件组成. 索引链功能的实现需要按照几个独立的步骤依次完成:检索原始内容.根据原始内容来创建对应的文档.对创建的文档进行索引. 搜索组件用于接收用 ...

  6. ElasticSearch 处理自然语言流程

    ES处理人类语言 ElasticSearch提供了很多的语言分析器,这些分析器承担以下四种角色: 文本拆分为单词 The quick brown foxes → [ The, quick, brown ...

  7. [Elasticsearch] 多字段搜索 (三) - multi_match查询和多数字段 <译>

    multi_match查询 multi_match查询提供了一个简便的方法用来对多个字段执行相同的查询. NOTE 存在几种类型的multi_match查询,其中的3种正好和在“了解你的数据”一节中提 ...

  8. elasticsearch学习笔记--原理介绍

    前言:上一篇中我们对ES有了一个比较大概的概念,知道它是什么,干什么用的,今天给大家主要讲一下他的工作原理 介绍:ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户 ...

  9. [Elasticsearch] 多字段搜索 (三) - multi_match查询和多数字段

    multi_match查询 multi_match查询提供了一个简便的方法用来对多个字段执行相同的查询. NOTE 存在几种类型的multi_match查询,其中的3种正好和在"了解你的数据 ...

随机推荐

  1. Swift - 运算符重载和运算符函数

    让已有的运算符对自定义的类和结构进行运算或者重新定义已有运算符的运算规则,这种机制被称为运算符重载. 1,通过重载加号运算符,使自定义的两个坐标结构体对象实现相加: 1 2 3 4 5 6 7 8 9 ...

  2. maven项目配置Project Facets时further configuration available不出来问题

    如果下边的 further configuration available不出来 把Dynamic web module 去掉勾选,应用与项目,然后再点开项目的properties,再选中Dynami ...

  3. 14.5.1 Resizing the InnoDB System Tablespace

    14.5.1 Resizing the InnoDB System Tablespace 本节描述如何增加或者减少InnoDB 系统表空间的大小 增加InnoDB 系统表空间的大小 最简单的方式增加I ...

  4. mysql update 有无索引对比

    <pre name="code" class="html">mysql> desc ProductInfo; +--------------- ...

  5. RIO包 健壮的I/O函数代码

    下面是关于 #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/t ...

  6. Api之Cors跨域以及其他跨域方式

    Web Api之Cors跨域以及其他跨域方式(三)   我们知道ajax不能跨域访问,但是有时我们确实需要跨域访问获取数据,所以JSONP就此诞生了,其本质使用的是Script标签,除JSONP以外还 ...

  7. <Win32_17>集音频和视频播放功能于一身的简易播放器

    前段时间,在学习中科院杨老师的教学视频时,他说了一句话: "我很反对百八十行的教学程序,要来就来一个完整的程序" 对此,我很是赞同.所谓真刀真枪的做了,你才会发现其中的奥秘——然而 ...

  8. 开发腾讯移动游戏平台SDK Android版Ane扩展 总结

    本文记录了在开发 腾讯移动游戏平台SDK(MSDK) Android版Ane扩展 过程中所遇到的问题和相关解决方式 问题一:编译报错:Unable to resolve target 'android ...

  9. hdu3329(2次dfs)

    传送门:The Flood 题意:当水的高度升为多少的时候,能够将这块区域分为两个部分. 分析:枚举高度,先从外围开始一次dfs,将水能淹没的标记,然后看非标记的是否已分为多块. #include&l ...

  10. Java设置的读书笔记和集合框架Collection API

    一个.CollectionAPI 集合是一系列对象的聚集(Collection). 集合在程序设计中是一种重要的数据接口.Java中提供了有关集合的类库称为CollectionAPI. 集合实际上是用 ...