Elasticsearch评分相关度算法解析

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: Elasticsearch评分相关度算法解析

Elasticsearch评分相关度算法解析

TF算法

TF算法,全称 Term frequency ,索引词频率算法。意义就像它的名字,会根据索引词的频率来计算,索引词出现的次数越多,分数越高。

例子如下

  • 搜索 hello

有两份文档:A文档:hello world!,B文档:hello hello hello

结果是B文档的 score 大于A文档。

  • 搜索 hello world

有两份文档:A文档:hello world!,B文档:hello,are you ok?

结果是A文档的score大于B文档。

要根据索引词来综合考虑。

如果不在意词在某个字段中出现的频次,而只在意是否出现过,则可以在字段映射中禁用词频统计

{
  "mappings": {
    "_doc": {
      "properties": {
        "text": {
          "type":          "string",
          "index_options": "docs"
        }
      }
    }
  }
}

将参数 index_options 设置为 docs 可以禁用词频统计及词频位置,这个映射的字段不会计算词的出现次数,对于短语或近似查询也不可用。要求精确查询的 not_analyzed 字符串字段会默认使用该设置。

IDF算法

IDF 算法全称 Inverse Document Frequency ,逆文本频率。搜索文本的词在整个索引的所有文档中出现的次数越多,这个词所占的 score 的比重就越低。

例子如下

搜索hello world,其中索引中hello出现次数1000次,world出现100次。

有三份文档:A 文档 hello,are you ok? , B 文档 The world is interesting! , C 文档 hello world!

结果是:C>B>A

由于hello出现频率高,所以单个hello得到的score比不上world

Field-length norm算法 (字段长度归一值)

  • 字段的长度是多少?

字段越短,字段的权重越高 。如果词出现在类似标题 title 这样的字段,要比它出现在内容 body 这样的字段中的相关度更高。

例子如下:

搜索 hello world!

有两份文档:A文档 hello world! ,B文档 hello world,I'm xxx!

结果是:A>B

词频(term frequency)、逆向文档频率(inverse document frequency)和字段长度归一值(field-length norm)——是在索引时计算并存储的。 最后将它们结合在一起计算单个词在特定文档中的 权重 。

当然,查询通常不止一个词,所以需要一种合并多词权重的方式——向量空间模型(vector space model)。

三种算法的综合

(下面属于理论分析,并不真实这样计算)

TF 算法针对在 Field 中,索引词出现的频率;

IDF 算法针对在整个索引中的索引词出现的频率;

Field-length norm 算法针对 Field 的长度。

那么可以这样分析,由于 Field-length norm 算法并不直接针对 score ,所以它是最后起作用的,它理论上类似于一个除数。而 TFIDF 是平等的, IDF 计算出每一个索引词的 score 量, TF 来计算整个文档中索引词的 score 的加和。

  • 也就是如下的计算:
  1. IDF:计算索引词的单位 score ,比如 hello=0.1,world=0.2
  2. TF:计算整个文档的 sum(score)hello world!I'm xxx. 得到 0.1+0.2=0.3
  3. Field-length norm:将 sum(score)/对应Field的长度 ,得出的结果就是 score

利用score计算API分析

创建模拟数据

  • PUT /test-7
{
  "settings": {
    "index":{
      "number_of_shards":3,
            "number_of_replicas":1
    }
  },
  "mappings": {
      "properties": {
        "name":{
          "type": "text"
        }
      }
  }
}
  • PUT /test-7/_doc/1
{
    "name": "li feng"
}
  • PUT /test-7/_doc/2
{
    "name": "li er"
}

explain分析

  • /test-7/_doc/_search?explain=true
{
    "query": {
        "match": {
            "name": "li"
        }
    }
}
  • 响应
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.2876821,
        "hits": [
            {
                "_shard": "[test-7][1]",
                "_node": "DpJZ5rhrStKpiur5hZ_ilw",
                "_index": "test-7",
                "_type": "_doc",
                "_id": "2",
                "_score": 0.2876821,
                "_source": {
                    "name": "li er"
                },
                // 先列出分数
                "_explanation": {
                    "value": 0.2876821,
                    // 分数的组成, details详细分析
                    "description": "weight(name:li in 0) [PerFieldSimilarity], result of:",
                    // 解释分数
                    "details": [
                        {
                            "value": 0.2876821,
                            "description": "score(freq=1.0), computed as boost * idf * tf from:",
                            "details": [
                                {
                                    "value": 2.2,
                                    "description": "boost",
                                    "details": []
                                },
                                {
                                    "value": 0.2876821,
                                    "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                                    // 逆文本频率 计算 idf
                                    "details": [
                                        {
                                            "value": 1,
                                            // 表示从当前分片中匹配到的文档记录数
                                            "description": "n, number of documents containing term",
                                            "details": []
                                        },
                                        {
                                            "value": 1,
                                            // 表示的是当前查询记录所处的分片上当前索引的文档数; 如果我们有多个分片,那么索引数据会被存储到多个分片上,每个分片上的文档记录数相加,得到的就是当前索引的文档总计录数了
                                            "description": "N, total number of documents with field",
                                            "details": []
                                        }
                                    ]
                                },
                                {
                                    "value": 0.45454544,
                                    "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                                    // 索引词频率计算 tf
                                    "details": [
                                        {
                                            "value": 1.0,
                                            // 检索关键词组在被检索字段的词组中出现的频率,即出现了多少次,比如上面的执行计划搜索 li 在字段中出现1次 即为1
                                            "description": "freq, occurrences of term within document",
                                            "details": []
                                        },
                                        {
                                            "value": 1.2,
                                            // 词的饱和度值,默认值为1.2
                                            "description": "k1, term saturation parameter",
                                            "details": []
                                        },
                                        {
                                            "value": 0.75,
                                            // 长度归一化评分 默认值为0.75
                                            "description": "b, length normalization parameter",
                                            "details": []
                                        },
                                        {
                                            "value": 2.0,
                                            // 被检索字段分词后的词组长度
                                            "description": "dl, length of field",
                                            "details": []
                                        },
                                        {
                                            "value": 2.0,
                                            // 分片中当前被检索字段的平均词组数值
                                            "description": "avgdl, average length of field",
                                            "details": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "_shard": "[test-7][2]",
                "_node": "DpJZ5rhrStKpiur5hZ_ilw",
                "_index": "test-7",
                "_type": "_doc",
                "_id": "1",
                "_score": 0.2876821,
                "_source": {
                    "name": "li feng"
                },
                "_explanation": {
                    "value": 0.2876821,
                    "description": "weight(name:li in 0) [PerFieldSimilarity], result of:",
                    "details": [
                        {
                            "value": 0.2876821,
                            "description": "score(freq=1.0), computed as boost * idf * tf from:",
                            "details": [
                                {
                                    "value": 2.2,
                                    "description": "boost",
                                    "details": []
                                },
                                {
                                    "value": 0.2876821,
                                    "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                                    "details": [
                                        {
                                            "value": 1,
                                            "description": "n, number of documents containing term",
                                            "details": []
                                        },
                                        {
                                            "value": 1,
                                            "description": "N, total number of documents with field",
                                            "details": []
                                        }
                                    ]
                                },
                                {
                                    "value": 0.45454544,
                                    "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                                    "details": [
                                        {
                                            "value": 1.0,
                                            "description": "freq, occurrences of term within document",
                                            "details": []
                                        },
                                        {
                                            "value": 1.2,
                                            "description": "k1, term saturation parameter",
                                            "details": []
                                        },
                                        {
                                            "value": 0.75,
                                            "description": "b, length normalization parameter",
                                            "details": []
                                        },
                                        {
                                            "value": 2.0,
                                            "description": "dl, length of field",
                                            "details": []
                                        },
                                        {
                                            "value": 2.0,
                                            "description": "avgdl, average length of field",
                                            "details": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
}

上面还有一个 boost,这个我们解释一下,

对于每一个 term 的权值,其默认值为2.2,我们可以在创建索引 mapping 结构的时候指定字段的 boost 的值,更多情况下,我们可以使用 boost 来作为 ES搜索结果的调优方案,比如搜索文档标题我们可以将boost 权重设置大一些,在搜索文档内容的时候,我们可以将 boost 权重设置小一些,从而实现动态的调整搜索结果,实现搜索不同的字段计算权重不同

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
4月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
80 3
|
10天前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
40 17
|
15天前
|
算法 搜索推荐 Java
【潜意识Java】深度解析黑马项目《苍穹外卖》与蓝桥杯算法的结合问题
本文探讨了如何将算法学习与实际项目相结合,以提升编程竞赛中的解题能力。通过《苍穹外卖》项目,介绍了订单配送路径规划(基于动态规划解决旅行商问题)和商品推荐系统(基于贪心算法)。这些实例不仅展示了算法在实际业务中的应用,还帮助读者更好地准备蓝桥杯等编程竞赛。结合具体代码实现和解析,文章详细说明了如何运用算法优化项目功能,提高解决问题的能力。
49 6
|
2月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
2月前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
249 30
|
2月前
|
存储 监控 算法
企业内网监控系统中基于哈希表的 C# 算法解析
在企业内网监控系统中,哈希表作为一种高效的数据结构,能够快速处理大量网络连接和用户操作记录,确保网络安全与效率。通过C#代码示例展示了如何使用哈希表存储和管理用户的登录时间、访问IP及操作行为等信息,实现快速的查找、插入和删除操作。哈希表的应用显著提升了系统的实时性和准确性,尽管存在哈希冲突等问题,但通过合理设计哈希函数和冲突解决策略,可以确保系统稳定运行,为企业提供有力的安全保障。
|
2月前
|
存储 算法
深入解析PID控制算法:从理论到实践的完整指南
前言 大家好,今天我们介绍一下经典控制理论中的PID控制算法,并着重讲解该算法的编码实现,为实现后续的倒立摆样例内容做准备。 众所周知,掌握了 PID ,就相当于进入了控制工程的大门,也能为更高阶的控制理论学习打下基础。 在很多的自动化控制领域。都会遇到PID控制算法,这种算法具有很好的控制模式,可以让系统具有很好的鲁棒性。 基本介绍 PID 深入理解 (1)闭环控制系统:讲解 PID 之前,我们先解释什么是闭环控制系统。简单说就是一个有输入有输出的系统,输入能影响输出。一般情况下,人们也称输出为反馈,因此也叫闭环反馈控制系统。比如恒温水池,输入就是加热功率,输出就是水温度;比如冷库,
447 15
|
4月前
|
搜索推荐 算法
插入排序算法的平均时间复杂度解析
【10月更文挑战第12天】 插入排序是一种简单直观的排序算法,通过不断将未排序元素插入到已排序部分的合适位置来完成排序。其平均时间复杂度为$O(n^2)$,适用于小规模或部分有序的数据。尽管效率不高,但在特定场景下仍具优势。
|
3月前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
90 4
|
3月前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####

推荐镜像

更多