弹性搜索-评分机制详解

当使用搜索引擎时,它必须对这个模块进行排序。如果它没有选择按某个字段排序,那么它会默认按得分高低排序。所以正式使用的话,需要对默认排序的评分策略有详细的了解。不然为什么这个在前那个在后?

以查询为输入,最后通过公式综合各个因素,返回文档的最终得分。这个综合考虑的过程就是优先考虑相关文件的考虑过程。

Elasticsearch基于Lucene,所以它的评分机制也是基于Lucene的。在Lucene中,这种相关性被称为score,确定文档与查询的相关性的过程被称为scoring。

ES最常用的评分模型是TF/IDF和BM25。TF-IDF属于向量空间模型,BM25属于概率模型,但两者的评分公式差别不大。它们都是用IDF方法和TF方法的一个乘积来定义单个词的权重,然后加上与查询匹配的词的权重作为整个文档的得分。

ES 5.0之前使用TF/IDF算法,ES 5.0之后默认使用BM25方法。

相关性得分:简单来说,就是计算一个索引中的文本与搜索文本的相关匹配程度。

通过倒排索引可以得到与查询语句相匹配的文档列表,那么如何将最符合用户查询需求的文档放在最前面呢?

本质是一个排序问题,排序的基础是相关分数。

Elasticsearch使用$ TERM频率/逆文档频率算法,简称TF/IDF算法。TF词频($ Term频率),IDF反向文档频率(IDF反向文档频率)

相关分数的几个重要概念如下:

目前,专家系统的相关评分模型主要有以下两种:

BM25中的IDF公式为:

原始BM25日志中没有1。Lucene做了一点优化来防止负值。虽然改了配方,但实际上和原来的配方没有实质性的区别。以下是新旧函数曲线的比较:

BM25中TF的公式为:

其中tf是传统的词频值。我们来看看改进前后的函数曲线对比(下图中k=1.2):

可以看出,在传统的计算tf的公式中,词频越高,tf值越大,且没有上限。但是随着词频的增加,BM中的tf值会无限接近(k+1),相当于一个上限。这就是两者的区别。一般K是1.2,Lucene也用1.2作为K的默认值..

在传统的公式中,也有一个规范。BM25在TF的计算公式中加入了这个因子,BM25结合范数因子的TF公式为:

与之前相比,一个乘数(1.0?b+b?L)(1.0?b+b?l).l的计算公式为:

其中|d|是当前文档的长度,avgDl是语料库中所有文档的平均长度。

b是常数,用来控制L对总分的影响。一般取0到1之间的数(取0表示完全忽略L)。Lucene中b的默认值是0.75。

通过这些细节的改进,BM25在很多实际场景中的表现都优于传统的TF-IDF,所以从Lucene 6.0.0版本开始,上位成为默认的相似度评分算法。

在上述示例中,评分模型由相似性属性指定,并且使用了以下三个参数:

如果我们想使用一个特定的评分模型,并想将其应用于整个世界,那么请添加:

Boosting可以人为控制得分过程中一个场的比重。有两种类型:

通过在映射中设置提升参数,您可以在索引过程中更改字段的评分权重:

应该注意,在索引期间修改的文档提升存储在索引中。如果要修改提升,必须对文档重新编制索引。

一旦映射完成,所有的name字段将自动拥有一个boost值,该值将存储在Lucene的内部索引结构中,并具有一个降低的精度值。只使用一个字节存储浮点值(如果保存不了,精度会损失),在计算文档最终得分时可能会损失精度。

此外,boost适用于术语。因此,如果在已经提升的字段中匹配了多个条目,则意味着多次计算提升,这将进一步增加字段的权重,并可能影响最终的文档分数。

查询时助推可以避免上述问题。

几乎所有查询类型都支持boost,例如:

就最终得分而言,带boost的姓名查询更有影响力。只有在bool查询中,boost才更有意义。

Boost还可以用于multi_match查询。

此外,我们可以使用特殊的语法为一个特定的字段只指定一个boost。通过在字段名后添加一个符号和boost值。告诉ES去加强那个领域:

在上面的例子中,标题字段被放大了3倍。

需要注意的是,使用boost时,字段和条目都是根据相对值进行增强,而不是乘以乘数。如果对所有要搜索的词提升相同的值,似乎没有提升。因为Lucene会把boost的值标准化。如果boost是一个场的4倍,并不代表这个场的分数乘以4。

ES背后的评分过程比我们想象的要复杂。有时查询结果可能与我们的预期不同。这时候可以通过explain让ES解释一下评分细节。

因为结果太长,我们在这里过滤结果(“size”:1返回一个文档),只看指定的字段(“source”:“name”只返回名称字段)。

在新增加的_ explanation字段中,可以看到值为0.9331132,那么是如何计算的呢?

春天这个词在描述字段(名称)中出现了1次,所以TF的综合得分是通过“描述”来计算的:“TF,计算为freq/(freq+k 1 *(1-b+b * dl/avgdl))from:“”。

逆文档词频呢?根据“描述”:“IDF,计算为Log(1+(n-n+0.5)/(n+0.5))From:”计算出的分数为0.98082924。

需要注意的是,explain的特性会给ES带来额外的性能开销,一般只在调试时使用。

搜索的时候,要依靠倒排索引;在排序时,需要依靠正字法索引来查看每个文档的每个字段,然后进行排序。所谓的正字法指标,其实就是doc值。

建立索引时,一方面会建立倒排索引进行搜索;一方面,它会建立一个正索引,即doc值,用于排序、聚合、过滤等操作。

Doc值保存在磁盘上。此时如果内存足够,os会自动缓存在内存中,性能依然会很高。如果没有足够的内存,操作系统会将其写入磁盘。

默认情况下启用DocValues,创建索引时可以将其关闭。如果以后要打开DocValues,则需要进行reindex操作。

参考:

/elastic search/guide/current/scoring-theory . html

blogs.com/Neeo/articles/10721071.html

blogs.com/jpfss/p/10775376.html

/p/27951938