ElasticSearch 如何计算得分及一个不太成熟的使用

1.背景

最近在做 ES 相关东西,只最会在查询的时候给不同的字段设置不同的权重,但是得分具体怎么算的不太明白,花了4-5 天研究和总结了一下。这样不至于被别人问到“这个分数怎么算出来的?”,两眼一抹黑,不知其所以然,总结下方便之后学习;

2.准备

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

  • 我创建了一个 book 索引,是一个分片一个副本,有三条数据;我 match 查询 java 时, java 编程思想 的得分 0.5619609,深入理解 Java 虚拟机得分 0.40390933;(分片会影响得分,请先使用一个片,后面会给出解释)

3.详情

  • 使用 explain 参数查询会给出得分计算过程
    在这里插入图片描述
  • 把 detail 全拿出来就是
"details" : [{"value" : 0.5619609,"description" : "score(freq=1.0), computed as boost * idf * tf from:","details" : [{"value" : 2.2,"description" : "boost","details" : [ ]},{"value" : 0.47000363,"description" : "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:","details" : [{"value" : 2,"description" : "n, number of documents containing term","details" : [ ]},{"value" : 3,"description" : "N, total number of documents with field","details" : [ ]}]},{"value" : 0.54347825,"description" : "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:","details" : [{"value" : 1.0,"description" : "freq, occurrences of term within document","details" : [ ]},{"value" : 1.2,"description" : "k1, term saturation parameter","details" : [ ]},{"value" : 0.75,"description" : "b, length normalization parameter","details" : [ ]},{"value" : 3.0,"description" : "dl, length of field","details" : [ ]},{"value" : 5.0,"description" : "avgdl, average length of field","details" : [ ]}]}]}]

3.1 粗略查看 ES 得分详情

  • 我们发现第四行好像就是公式 ,而且与 details 数组的元素对应
    在这里插入图片描述
  • 而且每个元素都有一个 value 值,把 value 值带进公式,正好等于 0.5619608507173045
    在这里插入图片描述

3.2 详细查看 es 得分

  • 第一项 2.2 不用解释,是 es 默认的一个常数,我们看第二项 idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:和第三项 tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:
  • 第二项截图
    在这里插入图片描述
    小 n :number of documents containing term,翻译一下,包含词项(也就是 java) 的文档数量,因为我们查询的是 name 字段,所以就是所有文档中 name 字段,包含 java 的文档数量,即 Java 编程思想深入理解 Java 虚拟机 ,vulue 等于 2 。
    大 N :total number of documents with field,翻译一下,有 name 这个字段的文档的数量,我们的三个文档都有 name 这个字段,即 Java 编程思想深入理解 Java 虚拟机Spring 5 个核心原理 value 等于 3 。
  • log(1 + (N - n + 0.5) / (n + 0.5)) = log(1 + (3 - 2 + 0.5) / (2 + 0.5) = log(1 + 1.5 / 2.5) = log1.6 =0.47000363,取的是自然数的对数,如图:
    在这里插入图片描述

3.2 第三项

  • 第三项截图
    在这里插入图片描述
    freq:occurrences of term within document,翻译一下,freq 是 frequency 的简写,频率的意思,即词项(java)在 Java 编程思想发生的频率, value 等于 1.
    k1:term saturation parameter,翻译一下,词项饱和度参数,value 是一个常数 1.2
    b:length normalization parameter,翻译一下,长度规格化参数,value 是一个常数 0.75
    dl:length of field,翻译一下,“字段”的长度,这里长度可不是 Java 编程思想.length(),而是Java 编程思想能分成多少个词,看下面 3.3 截图,
    avgdl:average length of field,翻译一下,“字段”的平均长度,同样也不是Java 编程思想 、 深入理解 Java 虚拟机、Spring 5 个核心原理.length()/3,而是Java 编程思想 、 深入理解 Java 虚拟机、Spring 5 个核心原理分词后的长度除以 33是有name 字段的数量,也看下面 3.3 截图

3.3 ik 分词器分词

在这里插入图片描述

  • Java 编程思想 、 深入理解 Java 虚拟机、Spring 5 个核心原理,分词后词项太多截图不全,我放到 JSON 解析器下,可以看到 数量是 15 ,平均数量是 5
    在这里插入图片描述
    在这里插入图片描述
  • freq / (freq + k1 * (1 - b + b * dl / avgdl) = 1 /(1 + 1.2 * (1 - 0.75 + 0.75 * 3 /5)) = 1 / (1 + 1.2 * (0.25 + 0.75 * 0.6)) = 1 / (1 + 1.2 * 0.7) = 1 / 1.84 = 0.54347826 约等于0.54347825,不纠结那 0.00000001至此,得分的所有项解读完毕,另一个查询结果“深入理解 Java 虚拟机”也可以按照这个方式计算出来

4.公式解释

  • 已经知其然了,现在看知其所以然,它是根据公式及经过大数据量实验设置参数后计算的结果。主角就是 BM25 算法,公式如下
    在这里插入图片描述
  • 我们在 kibana 上 explain 后公式的第二项和第三项分别对应这个公式的这两部分:
    在这里插入图片描述
  • 倒写的 3,表示求和,就是查询项分词后,每个分词都要计算分数,把每个查询词项的分数相加,比如我查询的是 “Java Spirng”,那么会把 Java 得分计算出来,再把 Spring 得分计算出来,然后相加;
  • 第二项,原谅我打不出这个公式,就是上面截图中上面两个箭头的第一个, idf 是 inverse document frequency 的简写,翻译一下,逆文档频率,详情是 log(1 + (N - n + 0.5) / (n + 0.5));如果小 n 趋近于 大 N,那么整个公式值越小,大家可以把 N 固定为 3,然后小 n 分别为 1、2、3 时,换算下是不是 小 n 越大,计算结果越小。翻译成人话就是,当一个词在所有文档中都出现了,那么它显得不那么重要,得分就低了。
  • 第三项,上面截图中上面两个箭头的第二个,如果说第二项是各个文档之间的纵向的比较,那么第三项更倾向于定位某个文档后的横向比较,
  • 第三项(1),比较频率,即这个词项出现的次数 ,ES 的的公式是freq / (freq + k1 * (1 - b + b * dl / avgdl)),比 BM25 分子少乘了一个 (k1 + 1)有区别,但差别不大;因为分母 k1 * (1 - b + b * dl / avgdl))可以看作是一个常数,那么当 freq 越大时,freq / (freq + k1 * (1 - b + b * dl / avgdl))值越大,但是最大值不超过 1,是无限趋近于 1 的数,当 freq 越小时,计算结果越小,翻译成人话也好理解,此项频率越高,得分越高。
  • 第三项(2),比较词项占比,这里的此项是 name 字段分词后的个数除以所有 name 字段分词平均值,当 dl 越大时分母越大,得分越小,翻译成人话是,比如我的 name 有一千个字且包含 java ,其他文档是十个字且包含 Java,那么我一千个字里面有个 Java 显得没那么重要。

4.分片情况下

如果你按照我上面计算时,发现中分词数量计算不对,那么很可能是你有多个分片,ES 不会把同一个字段各个分片的内容统一计算,而是每个片单独计算得分后就排名了,你可以通过指定 routing 来固定某个分片,验证得分结果。
在这里插入图片描述

5.前人的解读,帮助很大

bm25算法详解-bilibili
Elasticsearch BM25相关度评分算法超详细解释

6.一个不太成熟的使用

  • 我项目中有一个索引,有两个字段,分别记录用户搜索的内容 searchFor 和这个内容被搜索的次数 count,我想要把 count 也融入得分公式中,ES 默认的得分记作 _score,我本想把 count 按 log10 取对数变成 _score*log10(count),但是当 count 超过很大时会把 _score的得分放大很多倍,不同次数的文档得分跨度也比较大;
  • 研究 ES 的得分步骤后,我发现我的次数和第三项 freq / (freq + k1 * (1 - b + b * dl / avgdl))特别像,count 没有字段长度的比较所以我直接把关于长度 b(饱和度)dl/avgdl去掉了,改成 count / (count+k1) = count / (count + 1.2),最终得分是 _score*count / (count + 1.2)
  • 当然这样算不一定成熟,但是看起来起作用了,而且不同次数的文档得分跨度也变小了;但是因为我工作中的测试数据量不够,这个类 BM25的公式可能也不能这么硬套,要经过实际数据测试及业务需求匹配度验证后才能下定论,这只是一个不太成熟但是有点道理的使用,希望大家多留言讨论

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

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

相关文章

【vue组件库搭建05】vitePress中使用vue/antd/demo预览组件

一、vitepress使用vue及antd组件 1.安装antd之后在docs\.vitepress\theme\index.ts引入文件 // https://vitepress.dev/guide/custom-theme import { h } from vue import type { Theme } from vitepress import DefaultTheme from vitepress/theme import ./style.css impor…

Vue进阶(四十五)Jest集成指南

文章目录 一、前言二、环境检测三、集成问题汇总四、拓展阅读 一、前言 在前期博文《Vue进阶(八十八)Jest》中,讲解了Jest基本用法及应用示例。一切顺利的话,按照文档集成应用即可,但是集成过程中遇到的问题可能五花八…

基于Java的网上花店系统

目 录 1 网上花店商品销售网站概述 1.1 课题简介 1.2 设计目的 1.3 系统开发所采用的技术 1.4 系统功能模块 2 数据库设计 2.1 建立的数据库名称 2.2 所使用的表 3 网上花店商品销售网站设计与实现 1. 用户注册模块 2. 用户登录模块 3. 鲜花列表模块 4. 用户购物车…

【ARMv8/v9 GIC 系列 1.5 -- Enabling the distribution of interrupts】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 Enabling the distribution of interruptsGIC Distributor 中断组分发控制CPU Interface 中断组分发控制Physical LPIs 的启用Summary Enabling the distribution of interrupts 在ARM GICv3和GICv4体系结构中,中断分发…

Windows上Docker的安装与初体验

Docker Desktop下载地址 国内下载地址 一、基本使用 1. 运行官方体验镜像 docker run -d -p 80:80 docker/getting-started执行成功 停止体验服务 docker stop docker/getting-started删除体验镜像 docker rmi docker/getting-started2. 修改docker镜像的存储位置 3. …

Django开发实战(1)- 认识django

1.django 使用MTV模式,其实与MVC本质一样: model:业务对象和关系映射(ORM) template:客户端页面展示 view:业务逻辑,根据需求调用 2.开发相关 √ python √ html&…

简单的手动实现spring中的自动装配案例

简简单单的实现一个spring中的自动装配和容器管理的小骚操作。 1,创建AutoSetBean.java 使用injectBeans静态方法,可以扫描指定包下的所有带MyInject注解的字段,如果在beans的Map中存在这个字段的实例化类,则执行装配。 import…

无人机企业需要什么资质?

无人机企业所需的资质主要可以分为几大类,以确保其合法、安全、高效地进行相关业务活动。以下是对这些资质的详细解释和归纳: 1. 基础企业资质: - 工商营业执照:这是企业合法经营的基本证书,所有企业都需要取得。无人…

软连接迁移 Docker 的默认安装(存储)目录

前言 经常我们会拿到一些别人装好的服务器,需要在这些系统上启动我们的docker服务。 但是这些“专业人员”呢,有时候就会有非常不专业的操作,比如他把根目录/只划分50GB,/home却有51TB。这个时候就会导致我们的服务器还有很多空间…

9 redis,memcached,nginx网络组件

课程目标: 1.网络模块要处理哪些事情 2.reactor是怎么处理这些事情的 3.reactor怎么封装 4.网络模块与业务逻辑的关系 5.怎么优化reactor? io函数 函数调用 都有两个作用:io检测 是否就绪 io操作 1. int clientfd = accept(listenfd, &addr, &len); 检测 全连接队列…

基于工业互联网的智慧矿山解决方案PPT(38页)

文章摘要 工业互联网与智慧矿山 基于工业互联网的新一代智慧矿山解决方案,将互联网和新一代IT技术与工业系统深度融合,形成关键的产业和应用生态,推动工业智能化发展。该方案以“四级、三层、两网、一平台”为总体框架,强调应用目…

刷代码随想录有感(127):动态规划——判断是否为子序列

题干&#xff1a; 代码&#xff1a; class Solution { public:bool isSubsequence(string s, string t) {vector<vector<int>>dp(s.size() 1, vector<int>(t.size() 1, 0));for(int i 1; i < s.size(); i){for(int j 1; j < t.size(); j){if(s[i …

【人工智能】-- 智能机器人

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a; 专业知识 文章目录 &#x1f349;引言 &#x1f349;机器人介绍 &#x1f348;机器人硬件 &#x1f34d;机械结构 &#x1f34d;传感器 &#x1f34d;控…

One day for Chinese families

周围生活中的普通家庭的一天流程&#xff1a; 【上班的一天】 【放假的一天】 有家庭的人&#xff0c;上班流程&#xff1a; 01&#xff09;准备早餐&#xff0c;牛奶&#xff0c;面包 02&#xff09;叫娃娃起床&#xff0c;一般要蛮久的&#xff1b;沟通交流 -- 哄娃娃 -- 生气…

【TB作品】基于ATmega48的开机登录程序设计

使用Proteus仿真软件设计一个开机登录程序,单片机选用ATmegga48. 基础要求: 1.程序启动后在LCD1602液晶屏上提示用户通过独立按键输入密码(6位)。 2.密码输入错误则在屏幕上提示密码错误,密码输入正确则在屏幕上提示密 码正确后等待约3秒后进入主界面,在屏幕中央显示HelloWorld…

windows下编译ffmpeg 最详细教程

1 Ffmpeg下载地址&#xff1a;FFmpeg 使用命令下载 git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg 下载完成后会发现如下目录&#xff1a; 2 msys2下载地址&#xff1a;MSYS2 解压好后&#xff0c;选择一个非空路径安装&#xff0c;安装好后路径如下&#xff1a; 为…

自己动手实现语音识别

声音的本质是震动,震动的本质是位移关于时间的函数,波形文件(.wav)中记录了不同采样时刻的位移。 通过傅里叶变换,可以将时间域的声音函数分解为一系列不同频率的正弦函数的叠加,通过频率谱线的特殊分布,建立音频内容和文本的对应关系,以此作为模型训练的基础。 语音mfc…

ROS——坐标系管理、监听与广播、常用可视化工具

坐标系管理 TF功能包 小海龟追踪实验 ros版本(20.04)的tf安装命令: sudo apt-get install ros-noetic-turtle-tf 解决因python版本出现的无法生成跟随海龟&#xff1a; sudo ln -s /usr/bin/python3 /usr/bin/python ( -s 软链接,符号链接) ln命令&#xff08;英文全拼&#…

grpc-go服务端接口添加

【1】新建一个目录whgserviceproto&#xff0c;目录下新建一个proto包&#xff1a;whgserviceproto.proto &#xff08;注意目录和包名称保持一致&#xff09; //协议为proto3 syntax "proto3"; // 指定生成的Go代码在你项目中的导入路径 option go_package"…

代理模式详解、RESTFul风格、Spring IOC

Day49 代理模式proxy 概念&#xff1a; 代理(Proxy)是一种设计模式&#xff0c;提供了对目标对象另外的访问方式&#xff0c;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 代理模式分为静态代理和动态代理…