百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

ElasticSearch相关度评分算法 elasticsearch打分

yuyutoo 2024-10-28 20:21 3 浏览 0 评论

01 TF&IDF概念

TF

Term frequency:搜索文本中的各个词条在field文本中出现了多少次,出现次数越多,就越相关

term在一个doc中出现的次数,出现的次数越多,分数越高

IDF

Inverse document frequencry:搜索文本中的各个词条出现了多少次,出现的次数越多,越不相关

term在所有的doc中出现的次数,出现的次数越多,分数越低

length Norm

term搜索的那个Field的长度,长度越长,相关度越低,分数越低;长度越短,分数越高

最后结合TF,IDF,length Norm综合评分,得到该term对doc的最终分数

如何计算score

GET /website/article/1/_explain{  "query": {    "match": {      "title": "title"    }  }}
{  "_index" : "website",  "_type" : "article",  "_id" : "1",  "matched" : true,  "explanation" : {    "value" : 0.2876821,    "description" : "weight(title:title in 0) [PerFieldSimilarity], result of:",    "details" : [      {        "value" : 0.2876821,        "description" : "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:",        "details" : [          {            "value" : 0.2876821,            "description" : "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",            "details" : [              {                "value" : 1.0,                "description" : "docFreq",                "details" : [ ]              },              {                "value" : 1.0,                "description" : "docCount",                "details" : [ ]              }            ]          },          {            "value" : 1.0,            "description" : "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",            "details" : [              {                "value" : 1.0,                "description" : "termFreq=1.0",                "details" : [ ]              },              {                "value" : 1.2,                "description" : "parameter k1",                "details" : [ ]              },              {                "value" : 0.75,                "description" : "parameter b",                "details" : [ ]              },              {                "value" : 2.0,                "description" : "avgFieldLength",                "details" : [ ]              },              {                "value" : 2.0,                "description" : "fieldLength",                "details" : [ ]              }            ]          }        ]      }    ]  }}

02 boolean model (过滤模型)

即先过滤包含单个term进行分词后的doc,该步骤是不进行计算分数的,得到true/false

其目的是为了减少计算的数据量,提升性能

03 向量空间模型

TF/IDF是对单个term在doc中的分数计算

但当进行多个关键词匹配的时候,其实doc最终只有一个分数,那么这个分数的计算是通过向量空间模型得出的

向量空间模型:多个term对一个doc的分数

es会根据多个关键词对应的所有doc评分情况,计算出一个query vector(向量)


举例来讲,比如要搜索“hello world”这个term,那么es会给每个doc,拿每个term计算出一个分数,比如说hello 有一个分数为2,world有一个分数为5,然后再拿所有term的分数组成一个doc vector,然后取每个doc vector对query vector的弧度,给出每个doc对多个term的总分数


04 lucene的相关度分数算法

1.lucence practical scoring function

practical scoring function:计算一个query对一个doc的分数公式

score(q,d) = ? queryNorm(q) ? .coord(q,d) ? .Σ(

?? tf(t in d)

?? .idf(t)2

?? .t.getBoot()

?? . norm(t,d)

? ) ( t in q)

score(q,d)

这个公式的最终结果:一个query(q),对一个doc(d)的最终总评分

queryNorm(q)

用来让一个doc的分数处于一个合理的区间

queryNorm=1/sumOfSquaredWeights的平方根:即对所有term的IDF求和,然后平方根,最后再被除1,得到的分数会很小

sumOfSquaredWeights:所有term的IDF分数之和

coord(q,d)

对更加匹配的doc,进行一些分数上的成倍奖励

例如

Document 1 with hello -> score:1.5

Document 2 with hello world -> score:3.0

Document 3 with hello world java -> score:4.5

Document 1 with hello -> score:1.5*1/3 = 0.5

Document 2 with hello world-> score:3.0*2/3 = 2.0

Document 3 with hello world java-> score:4.5*3/3 = 4.5

把计算出来的总分数*匹配到的query数量/总query数量

Σ( t in q)

query中每个term对doc的分数,进行求和;多个term对一个doc的分数,组成一个空间向量,然后进行计算

比如query=hello world,那么就是对hello相对应的doc分数,world相对应的doc分数求和

tf( t in d)

计算每一个term对doc的分数,其实就是TF/IDF算法

idf(t)2

计算term对所有doc的分数,IDF算法

t.getBoost()

自定义控制查询的权重

norm(t,d)

就是term匹配到的field的长度,长度越长,分数越低

05 四种相关度评分优化方法

1.query time boost

query的时候指定boost

GET /forum/article/_search{  "query": {    "bool": {      "should": [        {"match": {          "sub_title": {            "query": "learn",            "boost": 10          }        }},        {          "match": {            "content": "java spark"          }        }      ]    }  }}

2.重构查询结果


GET /forum/article/_search{  "query": {    "bool": {      "should": [        {"term": {          "content": {            "value": "java"          }        }},        {          "term": {            "content": {              "value": "spark"            }          }        },        {          "term": {            "content": {              "value": "hadoop"            }          }        },        {          "term": {            "content": {              "value": "elasticsearch"            }          }        }      ]    }  }}

3.negative boost

negative的doc,会乘以negative_boost,这样分数会降低

GET /forum/article/_search{  "query": {    "boosting": {      "positive": {        "match": {          "content": "java"        }      },      "negative": {        "match": {          "content": "spark"   --不会排除spark内容,但是会将spark的分数降低        }      },      "negative_boost": 0.2    }  }}

4.constant_score

不需要相关度分数,直接使用constant_score,所有的doc score都是1

GET /forum/article/_search{  "query": {    "constant_score": {      "filter": {        "term": {          "content": "java"        }      }    }  }}

06 自定义function_score函数

自己将某个field的值,跟es内置算出来的分数进行运算,然后由自己指定的field来进行分数的增强

1.新增字段

POST /forum/article/_bulk{"update":{"_id":1}}{"doc":{"follower_num":50}}{"update":{"_id":2}}{"doc":{"follower":"30"}}{"update":{"_id":3}}{"doc":{"follower":40}}{"update":{"_id":4}}{"doc":{"follower":100}}{"update":{"_id":5}}{"doc":{"follower":60}}

2.自定义分数查询

GET /forum/article/_search{  "query": {    "function_score": {      "query": {        "multi_match": {          "query": "java spark elasticsearch hadoop",          "fields": ["content","tag"]        }      },      "field_value_factor": {        "field": "follower_num",        "modifier": "log1p",        "factor": 3      },      "boost_mode": "sum",      "max_boost": 10    }  }}

field

默认情况下每个doc的分数会和field的值进行相乘

modifier:

当doc分数与field相乘后,得到的分数分布可能不均衡,此时使用modifier,指定函数

log1p:公式 newscore = oldscore * log(1+numberofvotes)

将field的值+1取log后,然后与doc的分数进行相乘得到新的分数

factor:

进一步影响分数,计算公式为: newscore = oldscore * log(1+ factor * numberofvotes)

控制与field的值,可以影响权重

boost_mode:

可以决定分数与指定字段的值如何进行计算,默认是相乘(multiply)

sum,min,max,replace,multiply

max_boost:

限制计算出来的分数不要超过max_boost指定的值,这个参数影响作用不大

相关推荐

Java开发中如何优雅地避免OOM(OutOfMemoryError)

Java开发中如何优雅地避免OOM(OutOfMemoryError)在这个信息化高速发展的时代,内存就像程序员手中的笔,缺了它就什么都写不出来。而OOM(OutOfMemoryError)就像是横在...

常见的JVM调优方法和步骤

1、内存调优堆内存设置:通过-Xms和-Xmx参数调整初始和最大堆内存大小-Xms:初始堆大小(如-Xms512M)-Xmx:最大堆大小(如-Xmx2048M)调整新生代和老年代的比例...

Java中9种常见的CMS GC问题分析与解决(一)

目前,互联网上Java的...

JDK21新特性:Prepare to Disallow the Dynamic Loading of Agents

PreparetoDisallowtheDynamicLoadingofAgentsJEP451:准备禁止动态加载代理摘要...

Java程序GC垃圾回收机制优化指南

Java程序GC垃圾回收机制优化指南作为一个Java开发者,我们经常会在任务管理器里看到Java进程占用内存不断增长,然后突然下降的现象。这其实就是在Java虚拟机中运行的垃圾回收(GC)机制在起作用...

Java Java命令学习系列(一)——Jps

jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号。jps相当于Solaris进程工具ps。不象”pgrepjava”或”ps-efgrepjava”,jps...

面试题专题:头条一面参考答案(003)

前两篇文章也都是介绍头条一面的内容及参考答案...

Java JVM原理与性能调优:从基础到高级应用

一、JVM基础架构与内存模型1.1JVM整体架构概览Java虚拟机(JVM)是Java程序运行的基石,它由以下几个核心子系统组成:...

死锁攻防战:阿里架构师教你用3种核武器杜绝程序僵死

从线程转储分析到银行家算法,彻底掌握大厂必考的死锁解决方案以下是为Java死锁问题设计的结构化技术解析方案,包含代码级解决方案与高频追问应对策略:...

Java 1.8 虚拟机内存分布详解

Java1.8虚拟机内存分布详解Java1.8的JVM内存布局相比早期版本有显著变化(如永久代被元空间取代)。以下是其核心内存区域的划分、作用及配置参数:一、JVM内存整体结构...

Java 多线程开发难题?这篇文章给你答案!

作为互联网大厂的后端开发人员,在Java多线程开发过程中,必然会面临诸多复杂且具有挑战性的问题。在高并发场景下,各类潜在问题对系统的稳定性与性能产生严重影响,本文将深入探讨这些问题,并提供全面且有...

软件性能调优全攻略:从瓶颈定位到工具应用

性能调优是软件测试中的重要环节,旨在提高系统的响应时间、吞吐量、并发能力、资源利用率,并降低系统崩溃或卡顿的风险。通常,性能调优涉及发现性能瓶颈、分析问题根因、优化代码和系统配置等步骤,调优之前需要先...

JVM性能优化实战技巧

JVM性能优化实战技巧在现代企业级应用开发中,JavaVirtualMachine(JVM)作为承载Java应用程序的核心引擎,其性能直接决定了系统的响应速度、吞吐量以及资源利用率。因此,掌握一些...

JVM 深度解析:运行时数据区域、分代回收与垃圾回收机制全攻略

共同学习,有错欢迎指出。JVM运行时数据区域1.程序计数器程序计数器是一块较小的内存空间,可看作当前线程所执行的字节码的行号指示器。在虚拟机概念模型里,字节码解释器通过改变这个计数器的值选取下一条...

JVM内存管理详解与调优实战

JVM内存管理详解与调优实战Java虚拟机(JVM)作为Java程序运行的核心组件,其内存管理机制直接影响着应用程序的性能表现。今天,咱们就来一场既严肃又有趣的JVM内存管理之旅,看看这个“幕后英雄”...

取消回复欢迎 发表评论: