ElasticSearch之向量空间模型算法介绍

China☆狼群 提交于 2019-12-19 15:49:31

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

一 检索模型

1.1 bool模式

bool模式下,是最简单的检索模式,依据操作符AND 或者 OR 过滤document,结果只是包含指定的term的文档。他不会对document打分,只是为了减少后续要计算的document的数量,提升性能

1.2 TF/IDF

TF 是 term frequency的缩写,表示这个词条term在该文档出现的频率,往往能够表现文档的主体信息,即TF值越大,应该给于这个单词更大权值,具体计算词频因子的时候,基于不同的出发点,可以采纳不同的计算公式,最直接的方式就是直接利用词频数。假设某一个term出现过5次,那么这个term的TF值就是5,还有些变体计算公式:

第一个变体,为身取log是因为基于如下考虑:假设一个term出现了10次,也不该在计算权值时比出现1次的情况大10倍。加上1的目的是为进行平滑,比如TF就是1,那么计算对数,就是0,本来出现了一次的term,现在是不出现了。所以需要+1进行平滑。

第二个变体:a 是调节因子,0.4效果更好,TF表示实际的词频数,Max(TF)表示文档中所有单词出现次数最多的单词对应的词频数。

之所以这样做是因为:出于对长文档的限制,因为如果文档比较长,与短文档相比,则长文档中所有单词的TF值普遍比短文档高,但是这并不意味着长文档更合查询相关。

IDF是inverse document frequency的缩写,表示逆文档频率因子。我们知道同一个单词在不同的文档中TF值可能是不一样的。而逆文档频率因子IDF则不同,它代表着文档集合范围内的全局因子。给定一个文档集合,那么每一个单词的IDF值就唯一确定,跟具体文档无关

而我们一般是TF * IDF权值,如果计算出来的权值越大,那么打分可能会更高

1.3 向量空间模型(VSM)

VSM是Vector Space Model的缩写,把对文本内容的处理简化为对向量运算,并且以空间上的相似度表达语义的相似度。

每一个term或者n-gram片段都是一个维度。首先会在向量空间中构建N个维度的文档

举个例子:

ES会根据Flexible Plastic Frame在所有doc中的权值计算出一个query vector(1,1,1),然后N维空间我们放入查询向量,此时我们就可以计算各个doc的权值向量与查询向量之间的相似度

我们知道,cos值越大,表示相似度越高,我们可以看出,doc3的相关度是最高,其次是doc2,doc1最低

二 查询是如何为文档打分的

查询为每一个文档打分最主要的会使用一个公式来计算:

三 对相关度评分进行调节和优化的常见的3种方法

3.1 query的时候进行boost

POST /typeahead/guitar/_search

{

"query":{

"bool":{

"should":{

"match":{

"title":{

"query":"Plastic Sunglasses",

"boost":2

}

}

}

}

}

}

3.2 negative boost

我们有时候可能需要搜索包含Plastic,但是不包行Sunglasses的文档,但是这样有可能返回的文档数量太少,即召回率太少。那我们可以将包含Sunglassesde也返回,只是降低其分数而已

召回率低的做法:

POST /ecommerce/glasses/_search

{

"query":{

"bool": {

"must":[

{"match":{"record.desc":"Metal Alloy"}}

],

"must_not": [

{"match":{"record.desc":"Spring"}}

]

}

}

}

召回率较好的做法:

POST /ecommerce/glasses/_search

{

"query":{

"boosting":{

"positive":{

"match":{"record.desc":"Metal Alloy"}

},

"negative": {

"match":{"record.desc":"Spark"}

},

"negative_boost": 0.2

}

}

}

3.3 constant_score

我们不需要进行相关度平分,所有的文档的分数都是1

POST /ecommerce/glasses/_search

{

"query":{

"constant_score": {

"filter": {

"term": {

"record.desc": "Metal Alloy"

}

}

}

}

}

四 function_score自定义相关度分数算法

有时候我们想自己根据数据进行一些打分计算,比如商品的review数量,由review在一定程度上增强商品的打分记录。

这时候我们看就可以使用function_score来自定义打分。

POST /ecommerce/glasses/_search

{

"query":{

"function_score":{

"query":{

"multi_match": {

"query": "hadoop spark",

"fields": ["record.desc","record.content"]

}

},

"field_value_factor":{

"field":"record.review",

"modifier":"log1p",

"factor":0.5

},

"boost_mode": "sum",

"max_boost": 2

}

}

}

POST /ecommerce/glasses/_search

{

"query":{

"function_score":{

"query":{

"match_all": {}

},

"boost":5,

"functions":[

{

"filter":{"match":{"record.color":"Red"}},

"weight":10

},

{

"filter":{"match":{"record.color":"Black"}},

"field_value_factor": {

"field":"record.review",

"modifier":"square",

"factor": 0.5

}

}

],

"boost_mode": "multiply",

"max_boost":1000,

"min_score":10

}

}

}

Function Score Query提供几种类型打分函数:

1 script_score

2 weight,相当于文档分数乘以这个权重

3 random_score: 随机打分

"random_score": {

"seed" : number

}

默认使用_uid字段,进行hash

4 field_value_factor 允许你使用一文档字段去影响打分结果

function_score下的参数解释

query 指定查询

field_value_factor 允许你使用一文档字段去影响打分结果,如果指定了多个字段,只有第一个字段才会被计算。它的主要属性如下:

1 field: 指定哪个字段去影响评分

2 factor: 一个可选的配置,它会乘以字段值,默认是1

3 modifier: 指定字段值的函数,即这个字段值应用一个函数,有如下选项可供选择:假设该字段值是8

none: 不应用函数到字段值

log: 应用log函数到这个字段值,即log8

log1p: 应用log函数到这个字段值,即log(8+1),主要是为了防止有的值是1,这样计算出来就是0

log2p: 应用log函数到这个字段值,即log(8+2)

ln: 使用自然对数函数,即ln8

ln1p: 自然对数函数加1,即ln(8+1)

ln2p:自然对数函数加2,即ln(8+2)

squre:平方

sqrt:开方

reciprocal: 即 1/field value,即这里1/8

4missing,如果没有这个字段,我们给它一个默认值

#boost_mode: 指定doc分数与指定字段的值如何计算

1 multiply:字段值乘以文档分数

2replace : 字段值替换文档分数

3 sum字段值加上文档分数

4 avg:字段值和文档分数的平均值

5 min:min{字段值,文档分数}

6 max:max{字段值,文档分数}

max_boost: 限制计算出来的分数不要超过max_boost指定的值

min_score: 最小分数

functions 可以分别定义计算规则

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!