第 22 章 - 你不能错过的Elasticsearch核心知识点-BM25相关性评分算法(进阶)

news2024/10/16 15:02:43

文章目录

前言

上一章介绍了 Elasticsearch 的读写优化技巧。本章将深入探讨与 Elasticsearch 相关的 BM25 相关性评分公式。

我们将全面解析 BM25 如何在查询时影响文档评分。BM25 是 Elasticsearch 的核心内容之一,内容可能较为难懂,请耐心阅读。

分片对 Elasticsearch 相关性评分的影响

默认情况下,文档的评分是基于当前分片进行计算的。即,同一个 term 在不同的分片上评分会不一致。
我们来看下面这个例子。

创建一个 test_22 索引,并将分片数设置为 3

GET test_22/_search
{
  "explain": true, 
  "query": {
    "match": {
      "name": "hello"
    }
  }
}

紧接着,我们写入 3 条数据

PUT test_22/_doc/1
{
  "name": "hello es"
}
PUT test_22/_doc/2
{
  "name": "hello php"
}
PUT test_22/_doc/4
{
  "name": "hello world p"
}

OK,现在让我们来搜索 hello

GET test_22/_search
{
  "query": {
    "match": {
      "name": "hello"
    }
  }
}

结果可能会让你感到意外。
文档1的得分为0.2876821,文档2得分为0.19856803,文档4得分为0.16853255。
是不是感到困惑?文档1和文档2的结构相似,为什么文档1的得分更高呢?而文档4仅仅多了一个 P,它的得分却是最低的?

文档1为什么比文档2得分更高?
因为文档1 在分片2上,文档2、文档4在分片1上。这就是我上述所说的,得分是基于文档所在分片计算的。这与逆文档词频有关,下文会介绍。
查询参数最外层,添加 "explain": true,即可看到文档所在分片。

GET test_22/_search
{
  "explain": true, 
  "query": {
    "match": {
      "name": "hello"
    }
  }
}

文档2为什么比文档4得分更高?
文档2和文档4在同一个分片中,但是文档2的平均长度小于文档4。因此,文档2的得分比文档4更高。

简单来说:在一句话中出现 hello 的权重要高于在一段话中出现 hello 的权重。

这里提到的平均长度是以 term 为维度进行计算的。例如,文档2的平均长度为2,而文档4的平均长度为3。

BM25 算法和它的变量

上面提到的例子根源于 BM25 公式。接下来,我将重点介绍 BM25 公式的相关内容。
ES 的评分使用以下公式:
在这里插入图片描述

接下来,我将逐一介绍公式中的每个参数。

  • q i q_i qi
    表示当前查询的第几个term。例如,我们搜索 hello world,它包含 2 个term
    hello 对应 q 0 q_0 q0world 对应 q 1 q_1 q1

  • I D F ( q i ) IDF(q_i) IDF(qi)
    逆文档词频 (Inverse Document Frequency),其计算公式为:
    l n ( 1 + ( d o c C o u n t − f ( q i ) + 0.5 ) f ( q i ) + 0.5 ) ln(1+\frac{(docCount - f(q_i) + 0.5)}{f(q_i) + 0.5}) ln(1+f(qi)+0.5(docCountf(qi)+0.5))
    d o c C o u n t docCount docCount:当前分片文档数量
    f ( q i ) f(q_i) f(qi):在当前分片中,命中该term查询的文档数量
    如果一个 term 出现在大多数文档中,那么该 term 的得分也就越低。就像在做毕业设计时,你们班50个人的论文都是XXX管理系统,而只有你的论文是关于人工智能,那么你的论文更有可能被评为优秀论文。
    用上面的例子来说明:对于文档1的得分就是: l n ( 1 + ( 1 − 1 + 0.5 ) 1 + 0.5 ) ln(1+\frac{(1 - 1 + 0.5)}{1 + 0.5}) ln(1+1+0.5(11+0.5))。对于文档2得分就是: l n ( 1 + ( 2 − 2 + 0.5 ) 2 + 0.5 ) ln(1+\frac{(2 - 2 + 0.5)}{2 + 0.5}) ln(1+2+0.5(22+0.5))

  • f i e l d L e n a v g F i e l d L e n \frac{fieldLen}{avgFieldLen} avgFieldLenfieldLen
    这里的 avgFieldLen 指的是所有文档 term 的平均数量,fieldLen 则是指当前文档 term 的数量。就比如,在一篇300多页的文档中提到 term,跟在微博短短一句话提到的 term,肯定是后者的权重会更高。

  • b b b
    b b b 用于调整 文档长度( f i e l d L e n a v g F i e l d L e n \frac{fieldLen}{avgFieldLen} avgFieldLenfieldLen) 带来的影响。默认值为 0.75,取值范围为[0,1]
    b b b = 0 时,BM25 不考虑文档长度,即所有文档被视为相同长度。
    b b b = 1 时,文档长度的影响最大,较长的文档会受到更多惩罚。
    一般来说,b 的推荐值在 0.5 到 0.75 之间,这样可以较好地平衡文档长度的影响。
    例如,我们上面提到的文档2、文档4,他们都在同一个分片,仅因为文档4的长度大于文档2,文档4的得分就比文档2低。

  • f ( q i , D ) f(q_i,D) f(qi,D) k 1 k1 k1
    f ( q i , D ) f(q_i,D) f(qi,D) k 1 k1 k1 同时存在于分子、分母因此需要放在一起看。
    f ( q i , D ) f(q_i,D) f(qi,D) 表示 term 出现在文档中的频率,频率越高,文档得分越高。
    k 1 k1 k1 控制 term 的饱和度,默认值为 1.2,该值通常在 [0.5,2] 之间。
    k 1 k1 k1 越大时,词频的影响会增强。不过当并不会无限增强,而是当达到某一临界值时,就会停止增长。

效果应用

可以看到,我们能调整的值只有 b b b k 1 k1 k1。下面我带大家写几个例子,通过调整 b b b k 1 k1 k1 直观的感受一下。

b b b 值设置为 0

通过将 b b b 值设置为0,文档的长度将不对算分产生影响。

PUT test_22_1
{
  "settings": {
    "number_of_shards": 3,
    "index": {
      "similarity": {
        "default" : {
          "type" : "BM25",
          "b": 0,
          "k1": 1.2
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      }
    }
  }
}

写入文档

PUT test_22_1/_doc/1
{
  "name": "hello es"
}
PUT test_22_1/_doc/2
{
  "name": "hello php"
}
PUT test_22_1/_doc/4
{
  "name": "hello world p"
}

查询 hello

GET test_22_1/_search
{
  "query": {
    "match": {
      "name": "hello"
    }
  }
}

可以看到,现在文档2、文档4的分数一样了。
在这里插入图片描述

k 1 k1 k1 设置为0

k 1 k1 k1 设置为0,文档长度、词频将不对算分产生影响。

PUT test_22_2
{
  "settings": {
    "number_of_shards": 3,
    "index": {
      "similarity": {
        "default" : {
          "type" : "BM25",
          "b": 0.75,
          "k1": 0
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      }
    }
  }
}

写入文档

PUT test_22_2/_doc/1
{
  "name": "hello es"
}
PUT test_22_2/_doc/2
{
  "name": "hello php"
}
PUT test_22_2/_doc/4
{
  "name": "hello world hello"
}

查询文档

GET test_22_2/_search
{
  "query": {
    "match": {
      "name": "hello"
    }
  }
}

可以看到文档2、文档4的分数还是一致。
在这里插入图片描述

总结

  1. 文档评分是基于文档所在的分片进行计算的。
  2. 在同一个分片中,1个 term 出现在大多数文档中,那么该 term 的得分就会低,反之则高。
  3. 一个文档中,如果 term 出现的频率越高,它的得分就会越高,频率达到某个阈值后,得分将不再增加。
  4. b b b 用于调整文档长度对评分的影响,默认为 0.75,取值范围 [0,1]。
  5. k 1 k1 k1 用于调整文档词频对评分的影响,默认为 1.2,该值通常在 [0.5,2] 之间。
  6. b b b k 1 k1 k1 大多数情况下,我们不需要修改它。

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

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

相关文章

【Java】C++转Java基础知识

1. Java基础知识 1.1 JDK和JVM 在Java中,JDK称为Java开发工具包(Java Development Kit),包含了Java开发需要使用的工具包,前面的版本中JRE和JDK是分开的两个文件夹,从Java9开始,JDK中还包含了JRE(Java Runtime Envir…

STM32外设详解——ADC

来源:铁头山羊 基本概念 ①ADC是模数转换器的统称,stm32f103c8t6内部集成了2个12位主次逼近型ADC,外设名称为ADC1、ADC2。 ② 采样深度为12位意味着ADC可以将0~3.3V的模拟电压等比转换为0~4095的数字值(分割为2的12次方份&…

猫头虎分享:Python库 Selenium 的简介、安装、用法详解入门教程

🐯 猫头虎分享:Python库 Selenium 的简介、安装、用法详解入门教程 🚀 今天,猫头虎带大家深入了解 Selenium,这是一个非常流行的自动化测试工具,用于浏览器自动化。无论你是进行网页数据抓取,还…

Starrocks表的数据库字段类型及与MySQL 的差异

最近有用到Starrocks,实际使用中基本可以当作mysql来使用,但是数据库字段还是有所不同的。 与MySQL相同或相似的基础类型 数值类型 TINYINT、SMALLINT、INT/INTEGER、BIGINT:在Starrocks和MySQL中的定义和用途基本相似。都是用于存储整数&…

YOLO11改进|注意力机制篇|引入Mamba注意力机制MLLAttention

目录 一、【MLLAttention】注意力机制1.1【MLLAttention】注意力介绍1.2【MLLAttention】核心代码 二、添加【MLLAttention】注意力机制2.1STEP12.2STEP22.3STEP32.4STEP42.5STEP5 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【MLLAttention】注意力机制 1.1【MLLAtte…

[Linux#66][TCP->IP] 面向字节流 | TCP异常 | filesocket | 网络层IP

目录 1. 面向字节流 思考:对于UDP协议来说,是否也存在“粘包问题”呢? 2.TCP 异常情况 3.知识 1.UDP实现可靠传输(经典面试题) 2. 网络抓包 | 爬虫 3.打通文件和 socket 的关系 4.网络层:IP 前置知识 1. 面向字节流 udp…

Java+vue部署版本反编译

🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&am…

C++STL(2)

queue(队列) queue是一种先进先出的数据结构。 queue提供了一组函数来操作和访问元素,但它的功能相对较简单。 push(x):在队尾插入元素 x pop():弹出队首元素 front():返回队首元素 back():返回队尾元素 empty():检查队列是否为空 size0:返回队列中元素的个数 pri…

Android ViewModel

一问:ViewModel如何保证应用配置变化后能够自动继续存在,其原理是什么,ViewModel的生命周期和谁绑定的? ViewModel 的确能够在应用配置发生变化(例如屏幕旋转)后继续存在,这得益于 Android 系统的 ViewMod…

模拟电子电路基础(常见半导体+multisim学习1)

目录 1.半导体的基础 1.1.半导体基础知识 1.1.1本征半导体 1.1.2杂质半导体 1.1.3PN结 1.2半导体二极管 1.2.1半导体二极管的几种常见结构 1.2.2二极管的伏安特性曲线 1.2.3二极管的主要参数 1.2.4二级管的等效电路 1.2.5稳压二极管 1.2.其他类型二极管 2.multisim的…

双目视觉搭配YOLO实现3D测量

一、简介 双目(Stereo Vision)技术是一种利用两个相机来模拟人眼视觉的技术。通过对两个相机获取到的图像进行分析和匹配,可以计算出物体的深度信息。双目技术可以实现物体的三维重建、距离测量、运动分析等应用。 双目技术的原理是通过两…

Docker-nginx数据卷挂载

数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。 以Nginx为例,我们知道Nginx中有两个关键的目录: html:放置一些静态资源conf:放置配置文件 如果我们要让Nginx代理我们…

java项目之厨艺交流平台设计与实现(源码+文档)

项目简介 厨艺交流平台设计与实现实现了以下功能: 厨艺交流平台设计与实现的主要使用者管理员管理用户信息,可以添加,修改,删除用户信息信息。 💕💕作者:落落 💕💕个人…

分享一个从图片中提取色卡的实现

概述 最近在做“在线地图样式配置”的功能的时候,发现百度地图有个功能时上传一张图片,从图片中提取颜色并进行配图。本文就简单实现一下如何从图片中提取色卡。 效果 实现 实现思路 通过canvasdrawImage绘制图片,并通过getImageData获取…

主数据系统管理、运维的实践经验与建议

公司在预研一个新的主数据系统,领导问笔者给些建议。结合近两年的主数据系统管理、维护经验,给大致写了一些。 里面少数问题属于目前在运行的主数据系统的系统痛点所致,不过大多数笔者认为是通病,一口气写来已两千字,…

【验证码识别】Python+卷积神经网络算法+人工智能+深度学习+Django网页界面+计算机课设项目+TensorFlow+算法模型

一、介绍 验证码识别,使用Python作为开发语言,通过TensorFlow搭建CNN卷积神经网络算法模型,并通过对收集的几千张验证码图片作为数据集,然后进行迭代训练,最终得到一个识别精度较高的模型文件,然后使用Dja…

Cesium 区域高程图

Cesium 区域高程图 const terrainAnalyse new HeightMapMaterial({viewer,style: {stops: [0, 0.05, 0.5, 1],//颜色梯度设置colors: [green, yellow, blue , red],}});

JS 分支语句

目录 1. 表达式与语句 1.1 表达式 1.2 语句 1.3 区别 2. 程序三大流控制语句 3. 分支语句 3.1 if 分支语句 3.2 双分支 if 语句 3.3 双分支语句案例 3.3.1 案例一 3.3.2 案例二 3.4 多分支语句 1. 表达式与语句 1.1 表达式 1.2 语句 1.3 区别 2. 程序三大流控制语…

66 消息队列

66 消息队列 基础概念 参考资料:消息队列MQ快速入门(概念、RPC、MQ实质思路、队列介绍、队列对比、应用场景) 消息队列就是一个使用队列来通信的组件;为什么需要消息队列? 在实际的商业项目中,它这么做肯…

shell原理

shell 是个进程 , exe在user/bin/bash [用户名主机名 pwd] snprintf fflush(stdout),在没有\n情况下立马输出 strtok 第一个参数null表示传入上个有效参数 命令行中,有些命令必须由子进程执行, 如ls 有些…