【推荐】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 可以分别定义计算规则
来源:oschina
链接:https://my.oschina.net/u/3901188/blog/3144946