干货 | 一步步拆解 Elasticsearch BM25 模型评分细节
Elasticsearch 5 之前的版本,评分机制或者打分模型基于 TF-IDF 实现。
从 Elasticsearch 5 开始,Elasticsearch 的默认相似度算法是 Okapi BM25,Okapi BM25模型于 1994 年提出,BM25 的 BM 是缩写自 Best Match, 25 是经过 25 次迭代调整之后得出的算法,该模型也是基于 TF/IDF 进化来的,Okapi 信息检索系统是第一个实现此功能的系统,之后被广泛应用在不同系统里。
相似性(评分/排名模型)定义了匹配文档的评分方式, 对一组文档执行搜索并提供按相关性排序的结果。在这篇文章中,我们将一步步拆解 Okapi BM25 模型的内部工作原理。
在拆解评分算法之前,必须简单解释一下背后的理论——Elasticsearch 基于 Lucene。要了解 Elasticsearch,我们必须了解 Lucene。
类似的公式,我看到后的第一反应:这是科研人员才能搞懂的事情,我等只能围观。
但,为了进一步深入算分机制,我们一个个参数拆解一下,期望能“拨开云天、豁然开朗”!
上述公式中:
• D:代表文档。
• Q:代表查询。
• K1:自由参数,默认值:1.2。
• b:自由参数,默认值:0.75。
参见 Lucene 官方文档:
https://lucene.apache.org/core/8_0_0/core/org/apache/lucene/search/similarities/BM25Similarity.html
词频英文释义:TF(Term Frequency) ,即:分词单元(Term)在文档中出现的频率。
由于每个文本的长度不同,一个单词在长文档中出现的次数可能比短文档中出现的次数要多得多。
一个词出现的次数越多,它的得分就越高。
逆文档频率英文释义: IDF(Inverse Document Frequency),衡量分词单元Term的重要性。
但是,众所周知,诸如“the”、“is”、“of、“that”、“的”、“吗”等之类的特定词可能会出现很多次但重要性不大。
因此,我们需要通过计算以下公式来降低常用分词单元的权重,同时扩大稀有分词单元的权重。
本文基于:7.12.0 版本的 Elasticsearch 进行拆解验证。
创建索引:got,并制定字段 quote 为 text 类型,同时指定:english 分词器。
bulk 批量导入数据,数据来自《权利的游戏》电视剧的台词。
返回结果(仅列举评分、Quote 字段)如下:
这时候会面临我们的终极疑惑——这些评分咋来的?咋计算的呢?
别急,我们一步步拆解。
拿第一个返回文档也就是评分为:3.3297362 的结果数据为例,自顶向下的方法有利于理解计算。
如下拆解结果所示,分数 3.3297362 是分词单元 live 的 boost * IDF * TF 三者的乘积,简记为:
explain 执行后的结果,核心部分如下所示:
执行 explain 后,词频 TF 拆解计算如下,
词频计算涉及参数如下:
可以借助——analyze API 验证:
分词后的 token 为:
• avgdl:等于所有文档的分词单元的总数 / 文档个数) ,计算结果为:16.807692。如何计算的呢?这里有同学会有疑惑,解读如下:
avgdl 计算步骤 1:所有文档的分词单元的总数。
如下所示:共 437个。文档数为 26 个。
为了方面查看,我把 26 个文档的全部 document 内容集合到一个文档里面,求得的分词后的结果值为 437 。
avgdl 计算步骤 2:avgdl = 437 / 26 = 16.807692。
最终 TF 词频 求解结果为:0.740803524(该手算值精度和最终 Elasticsearch 返回结果精度值不完全一致,属于精度问题,不影响理解全局),其求解步骤如下:
• N:待检索文档数,本示例为 26。
• n:包含分词单元 live 的文档数目,本示例为 3。
最终 IDF 求解结果为:2.043074,其计算公式如下:
如上计算对数, 底数为 e。
一步步拆解,才能知道 BM25 模型的评分‘奥秘’所在,原来难懂的数学计算公式,也变得清晰明朗!
有了拆解,再来看其他的检索评分问题自然会“毫不费力"。
本文由英文博客:https://blog.mimacom.com/bm25-got/ 翻译而来,较原来博客内容,增加了计算的细节和个人解读,确保每一个计算细节小学生都能看懂。
欢迎就评分问题留言交流细节。