Elasticsearch:实用 BM25 - 第 3 部分:在 Elasticsearch 中选择 b 和 k1 的注意事项

news2024/9/23 21:28:13

 这是系列文章的第三篇文章。之前的文章是:

  • Elasticsearch:实用 BM25 - 第 1 部分:分片如何影响 Elasticsearch 中的相关性评分

  • Elasticsearch:实用 BM25 - 第 2 部分:BM25 算法及其变量

选择 b 和 k1

值得注意的是,当你的用户不能快速找到文档时,选择 b 和 k1 通常不是第一件事。 b = 0.75 和 k1 = 1.2 的默认值适用于大多数语料库,因此你可能对默认值没有意见。 更有可能的是,你想从以下内容开始:

  • 为 bool 查询中的精确短语匹配(phrase matches)之类的事物提升或添加常量分数
  • 利用同义词(synonyms)来匹配用户可能感兴趣的其他术语
  • 添加模糊性(fuziness)、预输入(typeahead)、语音匹配(phonetic matching)、词干提取(stemming)和其他文本/分析组件,以帮助解决拼写错误、语言差异等问题。
  • 添加或使用函数分数(function score)来衰减旧文档或地理上远离最终用户的文档的分数

Elasticsearch 如此强大的部分原因在于你可以使用这些原始的工具来创建非常强大的搜索体验。 但是假设你已经完成了所有其他工作,并且想查看 b 和 k1 的最后一英里……你如何选择它们?

已经相当深入地研究了所有数据/查询没有 “最佳” b 和 k1 值。 确实更改 b 和 k1 参数的用户通常通过评估每个增量来逐步执行此操作。 Elasticsearch 中的 Rank Eval API 可以帮助评估阶段。

在试验 b 和 k1 时,你应该首先考虑它们的边界。 我还建议你查看过去的实验,让你对你可能感兴趣的实验类型有一个粗略的了解 —— 尤其是如果你是第一次接触这种实验:

  • b 需要在 0 和 1 之间。许多实验以 0.1 左右的增量测试值,大多数实验似乎表明最佳 b 在 0.3-0.9 的范围内(Lipani、Lupu、Hanbury、Aizawa(2015 年); Taylor、Zaragoza、Craswell、Robertson、Burges (2006);Trotman、Puurula、Burgess (2014);等)
  • k1 通常在 0 到 3 的范围内进行评估,但没有什么可以阻止它变得更高。 许多实验都集中在 0.1 到 0.2 的增量上,大多数实验似乎表明最佳 k1 在 0.5-2.0 的范围内

对于 k1,你应该问,“我们什么时候认为一个词项可能饱和?” 对于像书籍这样的非常长的文档 —— 尤其是虚构或多主题的书籍 —— 很可能在一部作品中多次出现很多不同的术语,即使这些术语与整个作品的相关性并不高。 例如,“eye” 或 “eyes” 在一本虚构的书中可能出现数百次,即使 “eyes” 不是该书的主要主题之一。 然而,一本提到 “eyes” 一千次的书可能与眼睛有更多关系。 在这种情况下,你可能不希望术语很快饱和,因此有人建议,当文本更长且更多样化时,k1 通常应该趋向于更大的数字。 对于相反的情况,建议将 k1 设置在较低的一侧。 短新闻文章集出现几十次 “eyes” 而不与眼睛作为主题高度相关的可能性很小。

对于 b,你应该问,“我们什么时候认为文档可能很长,什么时候应该隐藏它与术语的相关性?” 高度具体的文件(如工程规范或专利)为了更具体地说明一个主题而显得冗长。 它们的长度不太可能对相关性产生不利影响,b 越小越好。 另一方面,广泛涉及多个不同主题的文档 —— 新闻文章(政治文章可能涉及经济、国际事务和某些公司)、用户评论等。 — 通常通过选择更大的 b 获益,这样与用户搜索不相关的主题(包括垃圾邮件等)将受到惩罚。

这些是一般的起点,但最终你应该测试您设置的任何参数。 这也展示了相关性如何真正紧密地绑定到同一索引中的相似文档(相似的语言、相似的一般结构等)。

Explain API

既然你了解了 BM25 算法的工作原理以及参数的工作原理,我想简要介绍一下 Elasticsearch 工具箱中最方便的工具之一,为你提供更多信息以回答不可避免地出现的 “为什么” 问题。 如果您曾经不得不回答 “为什么文档 x 的排名高于文档 y” 这个问题,Explain API 可以为你提供显着帮助。 让我们看一下 people 索引中的文档 4,这次是一个包含两个术语的查询:

GET /people/_explain/4
{
  "query": {
    "match": {
         "title": "shane connelly"
     }
  }
}

这将返回有关如何针对此查询对文档 4 进行评分的大量信息:

{
  "_index": "people3",
  "_type": "_doc",
  "_id": "4",
  "matched": true,
  "explanation": {
    "value": 0.71437943,
    "description": "sum of:",
    "details": [
      {
        "value": 0.102611035,
        "description": "weight(title:shane in 3) [PerFieldSimilarity], result of:",
        "details": [
          {
            "value": 0.102611035,
            "description": "score(doc=3,freq=1.0 = termFreq=1.0\n), product of:",
            "details": [
              {
                "value": 0.074107975,
                "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
                "details": [
                  {
                    "value": 6,
                    "description": "docFreq",
                    "details": []
                  },
                  {
                    "value": 6,
                    "description": "docCount",
                    "details": []
                  }
                ]
              },
              {
                "value": 1.3846153,
                "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",
                "details": [
                  {
                    "value": 1,
                    "description": "termFreq=1.0",
                    "details": []
                  },
                  {
                    "value": 5,
                    "description": "parameter k1",
                    "details": []
                  },
                  {
                    "value": 1,
                    "description": "parameter b",
                    "details": []
                  },
                  {
                    "value": 3,
                    "description": "avgFieldLength",
                    "details": []
                  },
                  {
                    "value": 2,
                    "description": "fieldLength",
                    "details": []
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "value": 0.61176836,
        "description": "weight(title:connelly in 3) [PerFieldSimilarity], result of:",
        "details": [
          {
            "value": 0.61176836,
            "description": "score(doc=3,freq=1.0 = termFreq=1.0\n), product of:",
            "details": [
              {
                "value": 0.44183275,
                "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
                "details": [
                  {
                    "value": 4,
                    "description": "docFreq",
                    "details": []
                  },
                  {
                    "value": 6,
                    "description": "docCount",
                    "details": []
                  }
                ]
              },
              {
                "value": 1.3846153,
                "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",
                "details": [
                  {
                    "value": 1,
                    "description": "termFreq=1.0",
                    "details": []
                  },
                  {
                    "value": 5,
                    "description": "parameter k1",
                    "details": []
                  },
                  {
                    "value": 1,
                    "description": "parameter b",
                    "details": []
                  },
                  {
                    "value": 3,
                    "description": "avgFieldLength",
                    "details": []
                  },
                  {
                    "value": 2,
                    "description": "fieldLength",
                    "details": []
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}

我们可以看到 k1 和 b 的单独值,还有 fieldLength 和 avgFieldLength 等每个 term 得分的组成部分! 因此,根据我们的最终得分 0.71437943,我们可以看到 0.102611035 来自 “shane”,0.61176836 来自 “connelly”。 Connelly 在我们的语料库中是一个罕见得多的术语,因此它具有更高的 IDF,这似乎是得分的主要影响因素。 但我们也可以看到文档的长度(2 个词项对比平均 3 个词项)也提高了分数的 “tfNorm” 部分。 如果我们觉得这不公平,我们可能会降低 b 的值来进行补偿。 当然,对 b 或 k1 的任何更改不仅会影响此处给定的一个查询,因此如果你最终更改了这些,请确保在许多查询和许多文档中重新测试。

请注意,Explain API 是一种调试工具,并被视为调试工具。 就像在正常情况下你不会在调试模式下运行生产应用程序一样,在正常情况下,你应该在 Elasticsearch 的生产部署中关闭对 _explain 的调用。

最后的话

BM25 不是镇上唯一的评分算法! 有经典的 TF/IDF,与随机性的分歧,还有很多很多 —— 更不用说基于超链接的修饰符,比如 pagerank —— 而且你通常还可以将其中的许多组合在一起! 此外,多年来出现了核心 BM25 算法的各种排列。 例如,已经有一些学术努力通过其中一些 BM25 排列自动选择/建议/解释 k1 和 b 的最佳值。 事实上,有一些理由/证据相信至少 k1 会在逐项的基础上得到最佳优化(Lv,ChengXiang(2011))。 有了这个,很自然地会问 “为什么是 BM25?” 或者 “为什么 BM25 具有这些特定的 k1 = 1.2 和 b = 0.75 值?”

简短的回答是,在算法或选择 k1 或 b 值时似乎没有任何灵丹妙药,但 k1 = 1.2 和 b = 0.75 的 BM25 似乎在大多数情况下都能给出非常好的结果。 在“BM25 的改进和检查的语言模型”(Trotman、Puurula、Burgess (2014))中,Trotman 等人。 搜索 b = 0-1 和 k1 = 0-3,并应用了许多不同的相关算法,包括尝试自动调整 BM25 参数的算法。 我认为他们在结论中说得最好:

“这项调查检查了 9 个排名函数、2 个相关反馈方法、5 个词干提取算法和 2 个停用词列表。 它表明停用词无效,词干提取有效,相关反馈有效,并且不停止、词干提取和反馈的组合通常会导致普通排名函数的改进。 然而,没有明确的证据表明排名函数中的任何一个在系统上优于其他函数。”

所以,当我们开始这个博客时,我们应该结束:你的大部分调优工作可能最好花在使用富有表现力的 Elasticsearch 查询语言、索引/语言控制以及整合用户反馈上,所有这些都可以通过 Elasticsearch API 完成。 对于那些做了所有这些然后想深入研究的人,可以考虑改变 k1 和 b 参数。 对于那些想要走得更远的人,Elasticsearch 支持可插入的相似性算法,包括附带许多更常见的算法。 但无论你做什么,请务必测试你的更改!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/658615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【备战秋招】每日一题:2023.05-B卷-华为OD机试 - 比赛的冠亚季军

为了更好的阅读体检,可以查看我的算法学习博客比赛的冠亚季军 题目描述 有个运动员,他们的id为0到N-1,他们的实力由一组整数表示。他们之间进行比赛,需要决出冠亚军。比赛的规则是0号和1号比赛,2号和3号比赛,以此类推…

014、数据库管理之配置管理

配置管理 TiDB配置系统配置集群配置配置的存储位置区分TiDB的系统参数和集群参数 系统参数系统参数的作用域系统参数的修改 集群参数集群参数的修改配置参数的查看 实验一: 在不同作用域下对数据库的系统参数进行修改session级别global级别 实验二: 修改…

Redis入门(二)

3.7 Redis 默认16个库 1)Redis默认创建16个库,每个库对应一个下标,从0开始. 通过客户端连接后默认进入到0 号库,推荐只使用0号库. 127.0.0.1:6379> 16个是因为配置文件中是这样的 [aahadoop102 redis]$ vim redis.conf 2)使用命令 sele…

DataX和SQLServer的导入导出案例

DataX和SQLServer的导入导出案例 文章目录 DataX和SQLServer的导入导出案例写在前面SQLServer数据库的简单使用SQLServer数据库一些常用的Shell脚本命令创建数据库 DataX 导入导出案例创建表并插入数据读取 SQLServer 的数据导入到 HDFS读取 SQLServer 的数据导入 MySQL 总结 写…

【C++Coppeliasim】UR机械臂位置正逆解Coppeliasim集成测试

前言: 基于改进的 Denavit-Hartenberg 参数的UR机械臂正向运动学求解和基于几何分析的逆运动学求解。该代码在 C 和 MATLAB 中可用,两者都与 CoppeliaSim 集成。 该解决方案是使用 Microsoft Visual Studio 2022 和 C 20 标准构建的。 依赖: …

C++ 类继承

目录 类继承基类派生一个类构造函数访问权限派生类与基类之间的特殊关系 完整demo 类继承 基类 #ifndef __TEST_1_H_ #define __TEST_1_H_ #include <iostream> #include<string> using namespace std; typedef unsigned int uint;//father class class TableTen…

《编译原理》2022年期末试卷

北京信息科技大学《编译原理》2022年期末考试 试卷附录

双指针-链表相交

面试题 02.07. 链表相交 同&#xff1a;160.链表相交 力扣题目链接 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保…

用c语言查找交通肇事者。

问题&#xff1a; 一辆卡车违反交通规则&#xff0c;撞人后逃跑。现场有3人目击事件&#xff0c;但都没有记住车号&#xff0c; 只记下车号的一些特征。 甲说&#xff1a;“牌照的前两位数字是相同的”。 乙说&#xff1a;“牌照的后两位…

如何高效阅读源码

最近在研究一款开源软件&#xff0c;从初步上手使用到源码分析&#xff0c;依靠看源码解决问题&#xff0c;可以说让自己在阅读源码能力上有了一点小的成长。鲁迅先生曾没说过&#xff0c;“源码是最好的文档”&#xff0c;他还没说过&#xff0c;“带着问题阅读源码最有效”。…

bat脚本添加以管理员权限执行方法

在windows上运行bat脚本的时候&#xff0c;有时候&#xff0c;会因为权限问题导致操作失败&#xff0c;这时候&#xff0c;需要在脚本中提升权限&#xff0c;以管理员权限执行脚本命令。 现在介绍两种方法可以实现管理员权限执行&#xff0c;如下所示&#xff0c;是一段以管理员…

【C++】STL的list容器介绍

目录 6、list容器 6.1list构造函数 6.2list赋值和交换 6.3list大小操作 6.4list插入 6.5list删除 6.6list数据存取 6.7list反转和排序 6、list容器 list本质是带头节点的双向循环链表&#xff0c;链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结…

学生必看!免费领取一台阿里云服务器

阿里云学生服务器优惠活动&#xff1a;高效计划&#xff0c;可以免费领取一台阿里云服务器&#xff0c;如果你是一名高校学生&#xff0c;想搭建一个linux学习环境、git代码托管服务器&#xff0c;或者创建个人博客网站记录自己的学习成长历程&#xff0c;拥有一台云服务器是很…

Redis 批处理优化

一、优化建议 1、使用Pipeline Redis 的 Pipeline 可以将多个命令打包成一个请求&#xff0c;从而减少通信次数和网络开销。在批处理时&#xff0c;可以使用 Pipeline 来提高效率。 2、使用批量插入 Redis 支持批量插入&#xff0c;可以将多个数据一次性插入数据库&#xf…

一文看完Vue3的渲染过程

Vue3官网中有下面这样一张图&#xff0c;基本展现出了Vue3的渲染原理&#xff1a; 本文会从源码角度来草率的看一下Vue3的运行全流程&#xff0c;旨在加深对上图的理解&#xff0c;从下面这个很简单的使用示例开始&#xff1a; import { createApp, ref } from "vue"…

Python3 列表与元组 | 菜鸟教程(六)

目录 一、Python3 列表 &#xff08;一&#xff09;简介相关 1、序列是 Python 中最基本的数据结构。 2、序列中的每个值都有对应的位置值&#xff0c;称之为索引&#xff0c;第一个索引是 0&#xff0c;第二个索引是 1&#xff0c;依此类推。 3、Python 有 6 个序列的内置…

Qt编写手机版本视频播放器和Onvif工具(可云台和录像)

一、前言 用Qtffmpeg写播放器很多人有疑问&#xff0c;为何不用Qt自己的多媒体框架来写&#xff0c;最重要的原因是Qt自带的目前都依赖具体的本地解码器&#xff0c;如果解码器不支持&#xff0c;那就是歇菜的&#xff0c;最多支持个MP4格式&#xff0c;而且在手机上也都是支持…

有效的括号

数据结构与算法应用往往隐藏在我们看不到的地方 20. 有效的括号 力扣题目链接 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串&#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括…

【Python 随练】打印楼梯与笑脸

题目&#xff1a; 打印楼梯&#xff0c;并在楼梯上方打印两个笑脸 简介&#xff1a; 在本篇博客中&#xff0c;我们将使用 Python 代码打印一个楼梯&#xff0c;并在楼梯上方打印两个笑脸。我们将给出问题的解析&#xff0c;并提供一个完整的代码示例来实现这个效果。 问题…

多目标优化算法:多目标浣熊优化算法(multi-objective Coati Optimization Algorithm,MOCOA)

一、浣熊优化算法COA 浣熊优化算法&#xff08;Coati Optimization Algorithm&#xff0c;COA&#xff09;由Dehghani Mohammad等人于2022年提出的模拟浣熊狩猎行为的优化算法&#xff0c;该算法具有进化能力强&#xff0c;收敛速度快&#xff0c;收敛精度高等特点。 COA具体…