ElasticSearch之score打分机制原理


Elasticsearch 的得分机制是一个基于词频和逆文档词频的公式,简称为 TF-IDF 公式,所以先来研究下 TF-IDF原理。

1. TF-IDF原理

TF-IDF的英文全称是:Term Frequency - Inverse Document Frequency,中文名称词频-逆文档频率。

常用于文本挖掘,资讯检索等应用,在NLP以及推荐等领域都是一个常用的指标,用于衡量字词的重要性。

比较直观的解释是,如果一个词本来出现的频率就很高,如the,那么它就几乎无法带给读者一些明确的信息。

一般地,以TF-IDF衡量字词重要性时

  • 某个字词在某个文档中出现的频率越高,那么该字词对该文档就有越大的重要性,它可能会是文章的关键词(词在单个文档中出现的频率,相对于当个文档!!!)
  • 但若字词在词库中出现的频率越高,那么字词的重要性越低,如the。(相对于整个文档集合,也就是词库)

1.1 计算公式

TF-IDF即是两者相乘,词频乘以逆文档频率,如下:
T F − I D F = T F ∗ I D F TF-IDF=TF*IDF TFIDF=TFIDF
下标ij的含义:编号为j的文档中的词语i在该文档中的词频,即所占比例,n为该词语的数量。如下:

换言之,就是词语出现的次数与文档中所有词总数的比值。
T F i j = n i j n ∗ j TF_{ij} = \frac{n_{ij}}{n_{*j}} TFij=njnij
N表示文档总数,Ni表示文档集中包含了词语i的文档数。

对分子分母加一是为了避免某些词语没有在文档中出现过,导致分母为零的情况。

IDF针对某个词计算了它的逆文档频率,即包含该词语的文档比例的倒数(再取对数),若IDF值越小,分母越大,说明这个词语在文档集中比较常见不具有鲜明的信息代表性,TF-IDF的值就小。

总之TF-IDF的值,通常希望它越大越好,大值代表性强。如下:
I D F i = l o g ( N + 1 N i + 1 ) IDF_i=log (\frac{N+1}{N_i+1}) IDFi=logNi+1N+1

1.2 示例说明

有两个文档,即doc1doc2,并去它们的并集

doc1 = "The cat sat on my bed"
doc2 = "The dog sat on my knees"
# 构建词库,union是并集操作
wordSet = set(doc1.split()).union(set(doc2.split()))

两个文档的并集如下:

{‘The’,‘bed’,‘cat’,‘dog’,‘knees’,‘my’,‘on’,‘sat’}

doc1doc2两个文档对应的词在并集中的统计情况:

序号catsatmyondogbedTheknees
011110110
101111011

1.2.1 计算TF

计算词频 TF,对单个文档统计:

再理解一下,何为TF,表示单个单词占当前文档所有单词集合的比值。即1/6=0.16666666666…

catsatmyondogbedTheknees
11110110
0.166666…0.166666…0.166666…0.166666…00.166666…0.166666…0

1.2.2 计算IDF

逆文档频率IDF,全局只有一份逆文档频率,对所有文档统计

N表示文档总数,Ni`表示文档集中包含了词语i的文档数。

此时N=2,共有两个文档。Ni表示含有单词的文档个数。

catsatmyondogbedTheknees
0.17609125…0.00.00.0…0.17609125…0.17609125…0.00.17609125…

1.2.3 TF-IDF计算

最终计算:TF-IDF = TF * IDF

序号catsatmyondogbedTheknees
00.0293490000.029349000
10000.0293490000.029349

2. Elasticsearch打分机制

上面介绍了TF-IDF的原理,而ES的得分机制就是基于词频和逆文档词频的公式,即TF-IDF公式。
s c o r e ( q , d ) = c o o r d ( q , d ) ⋅ q u e r y N o r m ( q ) ⋅ ∑ t i n q ( t f ( t i n d ) ⋅ i d f ( t ) 2 ⋅ t . g e t B o o s t ( ) ⋅ n o r m ( t , d ) ) score(q,d) = coord(q,d)\cdot queryNorm(q)\cdot \sum_{t in q}(tf(t in d)\cdot idf(t){^2}\cdot t.getBoost()\cdot norm(t,d)) score(q,d)=coord(q,d)queryNorm(q)tinq(tf(tind)idf(t)2t.getBoost()norm(t,d))
公式中将查询作为输入,使用不同的手段来确定每一篇文档的得分,将每一个因素最后通过公式综合起来,返回该文档的最终得分。这个综合考量的过程,在ES中这种相关性称为得分。

考虑到查询内容和文档的关系比较复杂,所以公式中需要输入的参数和条件非常得多,但是其中比较重要的其实是TF-IDF算法 ,再次解释一下。

  • TF (词频)

Term Frequency : 搜索文本中的各个词条在查询文本中出现了多少次,次数越多,就越相关,得分会比较高

  • IDF(逆文档频率)

Inverse Document Frequency : 搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,说明越不重要,也就越不相关,得分就比较低。

2.1 示例说明

在查询语句的最后加上explain=true ,会把得分过程打印。

注:当前ElasticSearchscorpios索引里,只有一个文档。

# 创建索引
PUT /scorpios
# 增加文档数据,此时索引中只有这一条数据
PUT /scorpios/_doc/1
{
 "text":"hello"
}

# 增加分析参数 
GET /scoripos/_search?explain=true 
{ 
 "query": { 
     "match": { 
         "text": "hello" 
         } 
     } 
}

执行后,会发现打分机制中有 2 个重要阶段:计算 TF 值和 IDF
在这里插入图片描述

在这里插入图片描述

最后的分数为:

在这里插入图片描述

2.2 计算 TF 值

f r e q / ( f r e q + k 1 ∗ ( 1 − b + b ∗ d l / a v g d l ) ) freq/(freq + k1 * (1-b+b*dl/avgdl)) freq/(freq+k1(1b+bdl/avgdl))

参数含义取值
freq文档中出现词条的次数1.0
k1术语饱和参数1.2(默认值)
b长度规格参数(单词长度对于整个文档的影响程度)0.75(默认值)
dl当前文中分解的字段长度1.0
avgdl查询文档中分解字段数量/查询文档数量1.0
TF(词频)1.0/(1+1.2 * (1-0.75+0.75 * 1.0/1.0))0.454545

2.3 计算 IDF 值

l o g ( 1 + ( N − n + 0.5 ) / ( n + 0.5 ) ) log(1+(N -n +0.5)/(n + 0.5)) log(1+(Nn+0.5)/(n+0.5))

参数含义取值
N包含查询字段的文档总数(不一定包含查询词条)1
n包含查询词条的文档数1
IDF(逆文档频率)log(1+(1-1+0.5)/(1+0.5))0.2875821

注:这里的 log 是底数为e 的对数

2.4 计算文档得分

b o o s t ∗ i d f ∗ t f boost * idf * tf boostidftf

参数含义取值
boost词条权重2.2(基础值)*查询权重(1)
idf逆文档频率0.2876821
tf词频0.454545
score(得分)2.20.28768210.4545450.2876821

2.5 增加新的文档测试得分

  • 增加一个毫无关系的文档
# 增加文档
PUT /scorpios/_doc/2
{
 "text" : "spark"
}
# 得分:0.6931741
GET /scorpios/_search
{
     "query": {
        "match": {
            "text": "hello"
        }
     } 
 }

因为新文档无词条相关信息,所以匹配的文档数据得分就应该较高

  • 增加一个一模一样的文档
# 增加文档
PUT /scorpios/_doc/2
{
 "text" : "hello"
}

# 得分:0.18232156
GET /scorpios/_search
{
 	"query": {
 		"match": {
 			"text": "hello"
 		}
	}
}

因为新文档含词条相关信息,且多个文件含有词条,所以显得不是很重要,得分会变低

  • 增加一个含有词条,但是内容较多的文档
# 增加文档
PUT /scorpios/_doc/2 
{
	"text" : "hello elasticsearch" 
}
# 得分:0.14874382
GET /scorpios/_search
{
     "query": {
         "match": {
         	"text": "hello"
         }
     }
 }

因为新文档含词条相关信息,但只是其中一部分,所以查询文档的分数会变得更低一些。

3. 案列

3.1 需求

查询文档标题中含有Hadoop,Elasticsearch,Spark的内容,优先选择Spark的内容

3.2 准备数据

# 创建索引
PUT /test
# 准备数据
PUT /test/_doc/1001
{
	"title" : "Hadoop is a Framework",
	"content" : "Hadoop 是一个大数据基础框架" 
}
PUT /test/_doc/1002
{
	"title" : "Hive is a SQL Tools",
	"content" : "Hive 是一个 SQL 工具" 
}
PUT /test/_doc/1003
{
	"title" : "Spark is a Framework",
	"content" : "Spark 是一个分布式计算引擎" 
}

3.3 查询数据

# 查询文档标题中含有“Hadoop”,“Elasticsearch”,“Spark”的内容
GET /test/_search?explain=true
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "Hadoop", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Hive", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Spark", "boost": 1
            }
          }
        }
      ]
    }
  }
}

此时会发现,Spark的结果并不会放置在最前面

在这里插入图片描述

此时可以更改 Spark 查询的权重参数 boost,看看查询的结果有什么不同

# 查询文档标题中含有“Hadoop”,“Elasticsearch”,“Spark”的内容
GET /test/_search?explain=true
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "Hadoop", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Hive", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Spark", "boost": 2
            }
          }
        }
      ]
    }
  }
}

在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

止步前行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值