当前位置: 首页 > article >正文

Elasticsearch 相似度评分模型介绍

前言

Elasticsearch 是基于 Lucene 的世界范围内最流行的全文检索框架,其文档相似度算法包含 TF/IDF 和 BM25,从 ES 5.0开始 BM25 算法已经成为 ES 默认的相似度评分模块。

TF-IDF 与 BM25 的区别

TF-IDF 和 BM25 都是计算文本相似性的常用算法。TF-IDF 的计算方法简单,计算复杂度低,但对高频词不敏感,参数难以调节。BM25 是在 TF-IDF 的基础上进行改进的,它考虑了文档的长度和查询词在文档中出现的次数,在大多数情况下都能够产生比 TF-IDF 更准确的相关性评分

TF-IDF 和 BM25 的主要区别在于计算方法的不同。TF-IDF 的计算方法为:

TF-IDF(t,d) = TF(t,d) * IDF(t)

其中:

  • TF(t,d) 表示词 t 在文档 d 中的词频
  • IDF(t) 表示词 t 的逆文档频率

BM25 的计算方法为:

BM25(t,d) = (k1 + 1) * TF(t,d) / (k1 * (1 - b + b * df / docLength) + TF(t,d))

其中:

  • k1 是控制词频对权重的贡献的参数
  • b 是控制逆文档频率对权重的贡献的参数
  • d 是控制文档长度对权重的贡献的参数

TF-IDF 和 BM25 的区别主要体现在以下几个方面:

  • 参数数量:TF-IDF 只需要一个参数,即逆文档频率。BM25 需要三个参数,即 k1、b 和 d,可以根据实际需求进行调节,以提高相关性评分的准确性
  • 计算复杂度:TF-IDF 的计算复杂度为 O(n),其中 n 是文档中的词数。BM25 的计算复杂度与 TF-IDF 相当,即 O(n)。
  • 相关性评分:BM25 在大多数情况下都能够产生比 TF-IDF 更准确的相关性评分。
评分在查询业务场景中的应用

在实际业务中,有关查询场景的评分可以分为如下四类:

不关注评分

这类场景下,纯粹把 ES 当作检索库使用,不关注相似度评分,那么可以使用 constant query 或者使用 bool query 中的 filter 来进行过滤即可,这样可以提高检索性能

默认评分

默认评分,也就是框架默认评分。这类场景下,仅使用最简单的查询方式,比如 查询 name:"tom",并没有人为额外干预评分的机制,仅靠默认的评分算法的得到 rank 列表 ,做为检索结果

业务评分 + 框架评分

此种场景下比较常见,比如查询 name:"tom"^10 name:"cat"^5, 或者更加复杂的结合通过 Function Score Query 来完成更加复杂的业务

仅业务评分

这种场景下,一般在推荐业务中比较常见,其完全忽略框架的评分策略,而采纳业务方或者产品方定义的评分规则,实现起来一般比较复杂,看一个例子:

GET /pi_ent_work/_search
{
    "query": {
        "function_score": {
            "query": {
                "bool": {
                    "must": [
                        {
                            "query_string": {
                                "boost": 0, # 注意此处禁用框架评分
                                "query": "prov:(33 OR 36)"
                            }
                        }
                    ], 
                    "must_not": [
                        {
                            "terms": {
                                "id": [
                                    "123"
                                ]
                            }
                        }
                    ], 
                    "filter": [
                        {
                            "term": {
                                "count": {
                                    "value": "1"
                                }
                            }
                        }
                    ]
                }
            }, 
            "score_mode": "sum", 
            "boost_mode": "replace", 
            "functions": [
                {
                    "script_score": {
                        "script": {
                            "lang": "expression", 
                            # 完全采用自定义评分并与数据中的某个字段关联
                            "source": " _score*0.8 + doc['custom_score'].value*0.4"
                        }
                    }
                }, 
                {
                    "weight": 6, 
                    "filter": {
                        "query_string": {
                            "query": "prov:(33 OR 36)"
                        }
                    }
                }, 
                {
                    "weight": 4, 
                    "filter": {
                        "query_string": {
                            "query": " product_id:112900 "
                        }
                    }
                }, 
                {
                    "weight": 2, 
                    "filter": {
                        "query_string": {
                            "query": "price:[* TO 3]"
                        }
                    }
                }
            ]
        }
    }, 
    "size": 100, 
    "_source": {
        "includes": [
            "id",
            "_score",
            "prov",
            "product_id",
            "custom_score",
            "count"
        ]
    }
}

上面的例子完全忽略了框架评分,而全部采用自己指定的规则评分,在 ES 中可以结合 Function Score Query来实现

总结

在实际工作中,搜索和推荐业务会比较依赖全文检索框架,很多情况下框架的默认的评分机制并不能很好的满足我们的需求,所以需要结合一些自定义评分策略来完善我们的 rank 效果


http://www.kler.cn/a/156544.html

相关文章:

  • 嵌入式硬件实战基础篇(一)-STM32+DAC0832 可调信号发生器-产生方波-三角波-正弦波
  • 23种设计模式的Flutter实现第一篇创建型模式(一)
  • MySQL查询某个数据库中特定表的空间占用大小
  • Vim 编辑器学习笔记
  • 实验5:网络设备发现、管理和维护
  • idea 弹窗 delete remote branch origin/develop-deploy
  • JVM 运行时内存篇
  • ubuntu使用SSH服务远程登录另一台设备
  • 并发编程笔记
  • qiankun: 关于ElementUI字体图标加载不出来的问题
  • C++ Easyx 让圆球跟随鼠标移动
  • 【Node.js】解决npm报错:RequestError: unable to verify the first certificate
  • 手动安装配置dapr环境
  • 人工智能发展史
  • 算法leetcode|91. 解码方法(rust重拳出击)
  • 网易区块链,网易区块链赋能赣州脐橙数字藏品,数字指纹解决方案
  • 【Altera】Cyclone10 FPGA DDR3使用
  • 预约系统源码解析:打造智能定制化预约服务的技术奇迹
  • SQL Sever Unicode字符串简单介绍
  • 抽象类与接口
  • localForage使用 IndexedDB / WebSQL存储
  • 3D模型渲染导致电脑太卡怎么办?
  • 比特币上的有状态多重签名
  • 09 C++ 中的循环(while循环、do-while循环、for循环及嵌套循环)
  • Android 源码编译
  • Go 语言真正有什么用处?