温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

elasticsearch7.x中的IDF该怎么调试

发布时间:2021-09-14 11:57:33 来源:亿速云 阅读:193 作者:柒染 栏目:大数据

本篇文章给大家分享的是有关elasticsearch7.x中的IDF该怎么调试,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

简介

TF-IDF 是elasticsearch中的默认打分机制(与Lucene一样),解释:

一个词条出现在某个文档中的次数越多,它就越相关。但是词条出现在不同文档中的次数越多,它就越不相关。

TF 词频,词条在文档中出现的次数

比如现在有这样两个文档,搜索Elasticsearch时,文档2应该具有更高的得分,文档1的词频是1,文档2的词频是2

1、We will discuss Elasticsearch at the nex Big Data group

2、Tuesday the Elasticsearch team will gather to answer questions about Elasticsearch

IDF 逆文档频率,词条在索引下所有文档中出现的次数

比如现在有这样三个文档,the在每一个文档中都存在,假如我们搜索the score时,如果没有IDF的话,最先返回的文档可能是不准确的,IDF均衡了常见词的相关性影响

1、We ues Elasticsearch to power the search for our website

2、The developers like Elasticsearch so far

3、The scoring of documents is calculated by the scoring formula

如何调试

当查询结果与我们预期出现不符时,可以使用"explain": true来调试

GET /full_text_test123/_search
{
  "query": {
    "match": {
      "content": "北京市"
    }
  },
  "explain": true
}

在知道文档ID的情况下,如果想查询某文档为什么没有被查询出来可以使用_explain API

GET /full_text_test123/_explain/1
{
  "query": {
    "match": {
      "content": "云南省"
    }
  }
}

在查询时设置评分

使用boost字段来设置评分系数 ,当使用 bool 或 and/or/not 等组合查询时,boost查询才更有意义

dsl中指定评分

bool 查询指定"北京市"优先级为10,云南省为1

GET /full_text_test123/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "content": {
              "query" : "北京市",
              "boost" : 10
            }
          }
        },
        {
          "match": {
            "content": {
              "query" : "云南省",
              "boost" : 1
            }
          }
        }
      ]
    }
  }
}

查询的结果,可以看到北京市的几个镇排列在前

"hits" : [
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "1",
	"_score" : 7.315132,
	"_source" : {
	  "title" : "回龙观镇",
	  "content" : "中华人民共和国北京市昌平区回龙观镇",
	  "geolocation" : "40.0764332591,116.3429765651",
	  "clicknum" : 102,
	  "date" : "2019-01-01"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "3",
	"_score" : 7.315132,
	"_source" : {
	  "title" : "小汤山镇",
	  "content" : "中华人民共和国北京市昌平区小汤山镇",
	  "geolocation" : "40.1809900000,116.3915700000",
	  "clicknum" : 202,
	  "date" : "2019-03-03"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "2",
	"_score" : 7.156682,
	"_source" : {
	  "title" : "沙河镇",
	  "content" : "中华人民共和国北京市昌平区沙河镇",
	  "geolocation" : "40.1481760748,116.2889957428",
	  "clicknum" : 92,
	  "date" : "2019-02-02"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "6",
	"_score" : 1.4350727,
	"_source" : {
	  "title" : "勐仑镇",
	  "content" : "中华人民共和国云南省西双版纳自治州勐腊县孟仑镇",
	  "geolocation" : "21.9481406582,100.4479980469",
	  "clicknum" : 330,
	  "date" : "2019-10-05"
	}
  }
]

如果我们使用的是multi_match查询,该如何指定评分系数呢,可以使用^符合,如下content字段评分系数是3,title是4,所以以title匹配的结果优先content次之

GET /full_text_test123/_search
{
  "query": {
    "multi_match": {
      "query": "北京市",
      "fields": ["content^3","title^4"]
    }
  }
}

上面两种是比较简单的评分方法,让我们看一看elasticsearch为用户提供的更高一级的方式

function_score 设置评分

function_score 还提供了其他五种修改评分的方法分别是:

  1. filter,设置内容符合过滤条件的文档为指定评分

  2. field_value_factor,使用文档中的参数作为系数来影响评分,如消息的评论数量越多评分越高

  3. script_score,使用脚本来计算评分系数,可以使用doc['fieldname']访问文档中某字段的值,比如使用Math.log(doc['attendees'].values.size()) * myweight,其中myweight是查询时params字段中指定的参数

  4. random_score,随机分配一个数值,在某些场景下希望每次返回的数据都不一样可以使用这个函数

  5. 衰减功能(linear线性曲线、gauss高斯曲线、exp指数曲线)

filter

搜索出北京市昌平区关键字的文档,通过functions设置评分,根据需求设置优先级

这里的weight和上面示例中的boost的区别是,普通boost是按照标准化来增加分数,而weight是乘以一个常数

GET full_text_test123/_search
{
  "query": {
    "function_score": {
      "query": {"match": {
        "content": "北京市昌平区"
      }},
      "functions": [
        {
          "weight": 2,
          "filter": {"match":{"content":"沙河镇"}}
        },
        {
          "weight": 3,
          "filter": {"match":{"content":"回龙观镇"}}
        }
      ],
      "score_mode": "max",
      "boost_mode": "replace"
    }
  }
}

结果

"hits" : [
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "1",
	"_score" : 3.0,
	"_source" : {
	  "title" : "回龙观镇",
	  "content" : "中华人民共和国北京市昌平区回龙观镇",
	  "geolocation" : "40.0764332591,116.3429765651",
	  "clicknum" : 102,
	  "date" : "2019-01-01"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "2",
	"_score" : 3.0,
	"_source" : {
	  "title" : "沙河镇",
	  "content" : "中华人民共和国北京市昌平区沙河镇",
	  "geolocation" : "40.1481760748,116.2889957428",
	  "clicknum" : 92,
	  "date" : "2019-02-02"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "3",
	"_score" : 1.0,
	"_source" : {
	  "title" : "小汤山镇",
	  "content" : "中华人民共和国北京市昌平区小汤山镇",
	  "geolocation" : "40.1809900000,116.3915700000",
	  "clicknum" : 202,
	  "date" : "2019-03-03"
	}
  }
]

score_mode,从每个单独的函数而来的得分是如何合并的,分别有如下几种设置

  1. multiply,默认值

  2. sum

  3. avg

  4. first

  5. max

  6. min

boost_mode,从函数得到的得分如何同原始得分合并,原始得分指的是示例中的content:"北京市昌平区"的查询,分别有如下几种设置

  1. sum,评分_score与函数值间的和

  2. max,评分_score与函数值间的较大值

  3. min,评分_score与函数值间的较小值

  4. replace,将函数得分替换为原始得分

field_value_factor

field_value_factor,使用文档中的参数作为系数来影响评分

  1. field:指定是文档中的哪个字段名称参与计算

  2. factor:点击次数要乘以的评分倍数

  3. modifier:评分的计算方式,默认为none,共分为以下几种(log、log1p、log2p、ln、ln1p、ln2p、square、sqrt、reciprocal)

点击率越高优先级越高

GET full_text_test123/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "北京市"
        }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "clicknum",
            "factor": 2.2,
            "modifier": "log1p"
          }
        }
      ],
      "score_mode": "max",
      "boost_mode": "replace"
    }
  }
}

结果

[
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "3",
	"_score" : 2.6487503,
	"_source" : {
	  "title" : "小汤山镇",
	  "content" : "中华人民共和国北京市昌平区小汤山镇",
	  "geolocation" : "40.1809900000,116.3915700000",
	  "clicknum" : 202,
	  "date" : "2019-03-03"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "1",
	"_score" : 2.352954,
	"_source" : {
	  "title" : "回龙观镇",
	  "content" : "中华人民共和国北京市昌平区回龙观镇",
	  "geolocation" : "40.0764332591,116.3429765651",
	  "clicknum" : 102,
	  "date" : "2019-01-01"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "2",
	"_score" : 2.308351,
	"_source" : {
	  "title" : "沙河镇",
	  "content" : "中华人民共和国北京市昌平区沙河镇",
	  "geolocation" : "40.1481760748,116.2889957428",
	  "clicknum" : 92,
	  "date" : "2019-02-02"
	}
  }
]

script_score

使用脚本来计算评分系数,可以使用doc['fieldname']访问文档中某字段的值,比如使用Math.log(doc['attendees'].values.size()) * myweight,其中myweight是查询时params字段中指定的参数

source:脚本函数(在7.x版本和旧版有细微的差别,在source中指定脚本)

params:我们自定义的对象

GET full_text_test123/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "北京市"
        }
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "source": "doc['clicknum'].value * params.myweight",
              "params": {
                "myweight":3
              }
            }
          }
        }
      ],
      "score_mode": "max",
      "boost_mode": "replace"
    }
  }
}

结果

[
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "3",
	"_score" : 606.0,
	"_source" : {
	  "title" : "小汤山镇",
	  "content" : "中华人民共和国北京市昌平区小汤山镇",
	  "geolocation" : "40.1809900000,116.3915700000",
	  "clicknum" : 202,
	  "date" : "2019-03-03"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "1",
	"_score" : 306.0,
	"_source" : {
	  "title" : "回龙观镇",
	  "content" : "中华人民共和国北京市昌平区回龙观镇",
	  "geolocation" : "40.0764332591,116.3429765651",
	  "clicknum" : 102,
	  "date" : "2019-01-01"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "2",
	"_score" : 276.0,
	"_source" : {
	  "title" : "沙河镇",
	  "content" : "中华人民共和国北京市昌平区沙河镇",
	  "geolocation" : "40.1481760748,116.2889957428",
	  "clicknum" : 92,
	  "date" : "2019-02-02"
	}
  }
]

random_score

随机分配一个数值,在某些场景下希望每次返回的数据都不一样可以使用这个函数

seed:随机数的种子,如果两次查询seed相同,那么结果页相同

官网对seed和field字段的解释

Random

The random_score generates scores that are uniformly distributed from 0 up to but not including 1. By default, it uses the internal Lucene doc ids as a source of randomness, which is very efficient but unfortunately not reproducible since documents might be renumbered by merges.

In case you want scores to be reproducible, it is possible to provide a seed and field. The final score will then be computed based on this seed, the minimum value of field for the considered document and a salt that is computed based on the index name and shard id so that documents that have the same value but are stored in different indexes get different scores. Note that documents that are within the same shard and have the same value for field will however get the same score, so it is usually desirable to use a field that has unique values for all documents. A good default choice might be to use the _seq_no field, whose only drawback is that scores will change if the document is updated since update operations also update the value of the _seq_no field.

翻译如下(使用软件翻译的凑合看吧) 

可以在不设置字段的情况下设置种子,但不建议这样做,因为这需要在_id字段上加载fielddata,这会消耗大量内存。

默认情况下,它使用内部lucene doc id作为随机性的来源,这是非常有效的,但不幸的是不可复制,因为文档可能被合并重新编号。
如果您希望分数是可复制的,可以提供种子和字段。最后的得分将基于这个种子、所考虑文档的字段最小值和基于索引名和shard id计算的salt,这样具有相同值但存储在不同索引中的文档将得到不同的得分。

请注意,在同一个shard中并且字段值相同的文档将得到相同的分数,因此通常需要对所有文档使用具有唯一值的字段一个好的默认选择可能是使用_seq_no字段,其唯一的缺点是,如果文档被更新,分数将改变,因为更新操作也会更新seq no字段的值

GET full_text_test123/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "北京市"
        }
      },
      "functions": [
        {
          "random_score": {
            "seed": 314159265359, 
            "field": "_seq_no"
          }
        }
      ],
      "score_mode": "max",
      "boost_mode": "replace"
    }
  }
}

衰减功能

衰减函数根据文档的数值字段值与用户给定的原点之间的距离衰减函数,为文档打分,类似于范围的查询。

衰减功能提供三种曲线(linear线性曲线、gauss高斯曲线、exp指数曲线),这三种类型的衰减类型可以有4个配置参数

  1. origin,曲线的中心点或字段可能的最佳值,落在原点origin上的文档评分_score为满分,是用户希望的最高峰值最高分,假如在计算 “小明” 距离 “图书馆” 位置距离的例子中表示 “小明” 当前的位置,或在某日期到今天的例子中表示今天

  2. offset,以原点origin为中心点,为其设置一个非零的偏移量offset覆盖一个范围(origin+/-offset这个范围),而不只是单个原点,在范围内内的所有评分_score都是满分,默认是0

  3. scale:衰减率,即一个文档从原点origin下落时,评分_score改变的速度。

  4. decay:当字段吧值衰减到scale指定的值时,衰减到decay

elasticsearch7.x中的IDF该怎么调试

图中所有曲线的原点origin(即中心点)的值都是40 ,office是5 ,也就是在范围40 - 5 <= value <= 40+5内的所有值都会被当作原点origin处理——所有这些点的评分都是满分。

在此范围之外,评分开始衰减,衰减率由scale值(此例中的值为5)和 衰减值 decay(此例中为默认值0.5 )共同决定。结果是所有三个曲线在origin +/- (offset + scale)处的评分都是0.5,即点30和50处。

linear 、 exp 和 gauss (线性、指数和高斯)函数三者之间的区别在于范围( origin +/- (offset + scale) )之外的曲线形状:

  1. linear 线性函数是条直线,一旦直线与横轴 0 相交,所有其他值的评分都是 0.0 。

  2. exp 指数函数是先剧烈衰减然后变缓。

  3. gauss 高斯函数是钟形的——它的衰减速率是先缓慢,然后变快,最后又放缓。

选择曲线的依据完全由期望评分 _score 的衰减速率来决定,即距原点 origin 的值。

使用经纬度"47.7226969027,128.6911010742"(黑龙江省伊春市)进行查询

GET full_text_test123/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "中华人民共和国"
        }
      },
      "functions": [
        {
          "gauss": {
            "geolocation": {
              "origin": "47.7226969027,128.6911010742",
              "offset": "1km", 
              "scale": "3000km",
              "decay": 0.25
            }
          }
        }
      ],
      "score_mode": "max",
      "boost_mode": "replace"
    }
  }
}

结果

[
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "5",
	"_score" : 0.07333869,
	"_source" : {
	  "title" : "翠乌镇",
	  "content" : "中华人民共和国黑龙江省伊春市燕翠乌镇",
	  "geolocation" : "47.7226969027,128.6911010742",
	  "clicknum" : 50,
	  "date" : "2019-06-05"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "3",
	"_score" : 0.06053602,
	"_source" : {
	  "title" : "小汤山镇",
	  "content" : "中华人民共和国北京市昌平区小汤山镇",
	  "geolocation" : "40.1809900000,116.3915700000",
	  "clicknum" : 202,
	  "date" : "2019-03-03"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "1",
	"_score" : 0.060268145,
	"_source" : {
	  "title" : "回龙观镇",
	  "content" : "中华人民共和国北京市昌平区回龙观镇",
	  "geolocation" : "40.0764332591,116.3429765651",
	  "clicknum" : 102,
	  "date" : "2019-01-01"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "2",
	"_score" : 0.05901804,
	"_source" : {
	  "title" : "沙河镇",
	  "content" : "中华人民共和国北京市昌平区沙河镇",
	  "geolocation" : "40.1481760748,116.2889957428",
	  "clicknum" : 92,
	  "date" : "2019-02-02"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "4",
	"_score" : 0.054671418,
	"_source" : {
	  "title" : "燕郊镇",
	  "content" : "中华人民共和国河北省廊坊市三河市燕郊镇",
	  "geolocation" : "39.9601300000,116.8147600000",
	  "clicknum" : 100,
	  "date" : "2019-04-05"
	}
  },
  {
	"_index" : "full_text_test123",
	"_type" : "_doc",
	"_id" : "6",
	"_score" : 0.0073663373,
	"_source" : {
	  "title" : "勐仑镇",
	  "content" : "中华人民共和国云南省西双版纳自治州勐腊县孟仑镇",
	  "geolocation" : "21.9481406582,100.4479980469",
	  "clicknum" : 330,
	  "date" : "2019-10-05"
	}
  }
]

以上就是elasticsearch7.x中的IDF该怎么调试,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI