弹性搜索-评分机制详解
以查询为输入,最后通过公式综合各个因素,返回文档的最终得分。这个综合考虑的过程就是优先考虑相关文件的考虑过程。
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