简化 KNN 检索【翻译】Simplifying kNN search

简化 KNN 检索

#转载 #大数据/ES #翻译

这篇文章是关于如何简化 k 最近邻(k-Nearest Neighbors,简称 kNN)搜索的深入探讨。以下是对全文的翻译(借助 kimi AI):


在这篇博客文章中,我们将深入探讨我们为使 kNN 搜索的入门体验更加轻松所做的努力!

向量搜索

向量搜索在 Elasticsearch 中已经可用了一段时间,通过使用新的专用 knn 搜索类型,同时我们也在 8.12.0 版本中将 kNN 作为查询引入(有关这个惊人的博客文章,我们最近发表了更多内容!)。

尽管每种方法的执行流程和应用有一些差异,但进行基本 kNN 检索的语法非常相似。因此,一个典型的 knn 搜索请求看起来像这样:

GET products/_search
{"knn": {"field": "my_vector","query_vector": [1, 2, 3],"k": 5,"num_candidates": 10}
}

前几个参数非常直观:我们指定数据存储的位置(field)和我们想要比较的内容(query_vector)。

另一方面,knum_candidates 参数则有点晦涩,需要一些理解才能进行微调。它们特定于我们使用的算法和数据结构,即 HNSW(层次导航小世界),主要存在是为了控制我们想要执行的图形探索量。

Elasticsearch 文档是搜索相关所有事物的绝佳资源,所以查看 knn 部分,我们有:

k:作为顶级命中返回的最近邻居的数量。这个值必须小于 num_candidates

num_candidates → 在每个分片上考虑的最近邻居候选数。需要大于 k,或者如果省略了 k,则不能超过 size,并且不能超过 10,000。Elasticsearch 从每个分片收集 num_candidates 结果,然后将它们合并以找到前 k 个结果。增加 num_candidates 往往会提高最终 k 结果的准确性。

然而,当您第一次遇到类似这样的情况时,这些值应该是多少并不明显,正确配置它们可能是一个挑战。这些值越大,我们将探索的向量就越多,但这将带来性能成本。我们再次面临准确性与性能之间的永恒权衡。

为了使 kNN 搜索更加简单和直观,我们决定使这些参数成为可选的,这样您只需要提供您想要搜索的位置和内容,如果确实需要,您可以调整它们。虽然看似一个相当小的变化,但它使事情变得更加清晰!因此,上述查询现在可以简单地重写为:

GET products/_search
{"knn": {"field": "my_vector","query_vector": [1, 2, 3]}
}

使 knum_candidates 成为可选的

所以我们希望使 knum_candidates 成为可选的。太好了!我们应该如何设置默认值呢?

有两种选择。选择一个看起来像是个好选项的,发布它,然后希望最好的结果,或者做艰苦的工作并进行广泛的评估,让数据驱动我们的决策。在 Elastic,我们喜欢这样的挑战,并希望确保任何决策都是有理由的,并且是出于好的原因!

正如我们上面提到的,kNN 搜索的 k 是每个分片返回的结果数量,所以一个明显的默认值就是使用 size。因此,每个分片将返回 size 个结果,我们将合并并排序它们以找到全局前 size 个结果。这也与没有 k 参数的 kNN 查询很好地配合,而是根据请求的 size 操作(记住,knn 查询的行为就像任何其他查询,如 termprefix 等)。所以,size 似乎是一个合理的默认值,可以涵盖大多数用例(或者至少在入门体验中足够好!)。

另一方面,num_candidates 则有些不同。此参数特定于 HNSW 算法,并控制我们要考虑的最近邻居队列的大小(对于好奇的人:这相当于原始论文中的 ef 参数)。

我们可以考虑采取多种方法:

  • 我们可以考虑到每个图的大小,并设计一个函数来计算 N 个索引向量的适当 num_candidates
  • 我们可以查看底层数据分布,并尝试估计所需的探索(也许还考虑 HNSW 的入口点)
  • 我们可以假设 num_candidates 与索引数据没有直接关系,而是与搜索请求有关,并确保我们进行所需的探索以提供足够好的结果。

作为开始,并保持事情简单,我们研究了将 num_candidates 值相对于 k(或 size)进行设置。因此,您实际想要检索的结果越多,我们在每个图上执行的探索就越多,以确保我们从局部最小值中逃脱。我们将重点关注的候选选项如下:

  • num_candidates = k
  • num_candidates = 1.5 * k
  • num_candidates = 2 * k
  • num_candidates = 3 * k
  • num_candidates = 4 * k
  • num_candidates = Math.max(100, k)

值得注意的是,最初考虑了更多的替代方案,但更高的值几乎没有带来好处,因此在博客的其余部分,我们将主要关注上述内容。

有了一组 num_candidates 候选项(没有双关语!),我们现在专注于 k 参数。我们选择同时考虑标准搜索和非常大的 k 值(以查看我们执行的探索的实际影响)。因此,我们决定更关注以下值:

  • k = 10(用于没有指定 size 的请求)
  • k = 20
  • k = 50
  • k = 100
  • k = 500
  • k = 1000

数据

由于没有一种解决方案适用于所有情况,我们希望测试具有不同属性的不同数据集。因此,不同的总向量数量、维度,以及由不同模型生成,因此具有不同的数据分布。

同时,我们有 rally,这是一个用于基准测试 Elasticsearch 的很棒的工具(https://github.com/elastic/rally),它支持运行一堆查询并提取多个向量数据集的指标。在 Elastic,我们广泛使用 rally,并依赖它进行我们所有的夜间基准测试,您可以在这里查看!

在 rally 上运行基准测试就像运行以下命令一样简单:

pip3 install esrally && esrally race --track=dense-vector

为此,我们略微修改了赛道(即 rally 的测试场景),以包含额外的指标配置,添加了一些新的,最终得到了以下赛道集:

  • dense-vector(200 万文档,96 维):https://github.com/elastic/rally-tracks/tree/master/dense_vector
  • so-vector(200 万文档,768 维):https://github.com/elastic/rally-tracks/tree/master/so_vector
  • cohere-vector(300 万文档,768 维):https://github.com/elastic/rally-tracks/tree/master/cohere_vector
  • openai-vector(250 万文档,1536 维):https://github.com/elastic/rally-tracks/tree/master/openai_vector
  • Glove 200d(120 万,200 维)基于https://github.com/erikbern/ann-benchmarks repo 创建的新赛道

同样值得注意的是,对于前几个数据集,我们还想考虑有一个与多个段的情况,因此我们包含了每种的两个变体,

  • 一个我们执行 force_merge 并拥有单个段,
  • 一个我们依赖底层的 MergeScheduler 来做它的魔法,最终得到它认为合适的段数。

指标

对于上述每个赛道,我们计算了标准的召回率和精确度指标、延迟,以及通过报告我们访问的节点来实际探索的图形。前几个指标是针对真正的最近邻居评估的,因为在我们的场景中,这是黄金标准数据集(记住,我们正在评估近似搜索的质量,而不是向量本身的质量)。nodes_visited 属性最近已添加到 knn 的配置文件输出中(https://github.com/elastic/elasticsearch/pull/102032),因此,通过对赛道定义进行一些微小的更改以提取所有所需的指标,我们应该可以开始了!

开始实际工作

现在我们知道了我们想要测试的内容、要使用的数据集以及如何评估结果,是时候实际运行基准测试了!

为了有一个标准化的环境,对于每个测试,我们使用了一个干净的 n2-standard-8(8 vCPU,4核,32 GB内存) 云节点。Elasticsearch 配置以及所需的映射和所有其他内容都通过 rally 配置和部署,因此对于所有类似测试都是一致的。

上述每个数据集都执行了多次,收集了所有候选集定义的所有可用指标,确保结果不是一次性的。

结果

每个指定数据集和参数组合的召回率-延迟图可以在下面找到(越高越向左越好,延迟以毫秒为单位测量):

针对dense_vectoropenai_vector赛道的绝对延迟@50 th 百分位值和召回率值如下:

类似地,每个场景下 HNSW 图形节点访问的 99 th 百分位数可以在下面找到(越小越好):

少即是多*

*嗯,在所有情况下都不是这样,但嘿 😃

从结果来看,有两点比较突出:

一个分段与多个分段明显成反比地影响召回率和延迟指标。分段越少,延迟就越短(因为我们需要遍历的图更少,也就是需要运行的搜索更少),这固然很好,但它也会以相反的方式影响召回率,因为很有可能一些好的候选者会被遗漏(因为候选者列表数量更少)。
即使探索很少,我们也能在几乎所有情况下获得足够好的召回率,这非常好!
我们一直在努力改进多分段搜索(本文章中就有一个很好的例子),因此我们希望在今后的工作中,这种取舍将不再是一个问题(此处报告的数据不包括这些改进)。

考虑到所有因素,我们讨论的两个主要选项如下:

Num_candidates = 1.5 * k - 这在几乎所有情况下都能达到足够好的召回率,同时获得非常好的延迟分数。
Num_candidates = Math.Max (100, k)–这种方法的召回率稍高,尤其是在 k 值较低的情况下,但代价是增加了图形探索和延迟。
经过仔细考虑和(漫长的!)讨论,我们选择了前者作为默认设置,即设置 num_candidates = 1.5 * k。在我们测试的几乎所有情况下,我们需要做的探索工作要少得多,召回率也都超过了 90%(有些报告的数字还明显更高),这应该能带来足够好的上机体验。

结论

Elastic 处理 kNN 搜索的方式一直在不断发展,我们也在不断引入新功能并进行改进,因此这些参数和整体评估很可能很快就会过时!我们一直在关注这一变化,无论何时发生,我们都会确保跟进并适当调整我们的配置!

需要记住的重要一点是,这些值只是简化上架体验和非常通用的使用案例的合理默认值。人们可以在自己的数据集上轻松地进行实验,并根据自己的需求进行相应的调整(例如,在某些情况下,召回可能比延迟更重要)。

调优愉快 😃

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/10205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mes系统业务学习

MES-生产溯源: 一物一码:一物一码,通过包装物或产品本身的条码追溯相关联原料、供应商、客户、订单、生产人员、生产过程、质检报告、售后等关键信息,覆盖产品全生命周期。精准质量追溯:通过采集扫描即时记录跟踪每一个关键信息&…

Arduino-ILI9341驱动开发TFT屏显示任意内容三

Arduino-ILI9341驱动开发TFT屏显示任意内容三 1.概述 这篇文章介绍使用ILI9341驱动提供的函数控制TFT屏显示字符串、图形、符号等等内容的编辑和展示。 2.硬件 2.1.硬件列表 名称数量Arduino Uno12.8" TFT彩色液晶触摸屏模块(ILI9431)110K 电阻…

SpringBootWeb 篇-深入了解请求响应(服务端接收不同类型的请求参数的方式)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 请求响应概述 1.1 简单参数 1.2 实体参数 2.3 数组集合参数 2.4 日期参数 2.5 json 参数 2.6 路径参数 3.0 完整代码 1.0 请求响应概述 当客户端发送不同的请求参…

Selenium定位方法及代码

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

中国1KM年相对湿度数据集1981-2020

大气相对湿度(RH)是气象/气候监测和研究的关键因素。然而,相对湿度在气候变化研究中的应用并不是很普遍,部分原因是相对湿度观测系列容易由于观测系统中的非气候变化而产生不均匀偏差。 该数据集是中国1km分辨率年相对湿度数据&am…

使用依赖注入(DI)的方式实现对冗余代码的解耦

1.1、优化前代码 GetMapping("/test") public void test(RequestParam("params") String params){if("1".equals(params)){// 逻辑代码}if("2".equals(params)){// 逻辑代码}if("3".equals(params)){// 逻辑代码} }1.2、优…

『大模型笔记』Google DeepMind and Isomorphic Labs联合发布AlphaFold 3!

Google DeepMind and Isomorphic Labs联合发布AlphaFold 3! 文章目录 一. Google DeepMind and Isomorphic Labs联合发布AlphaFold 3!AlphaFold 3 及其后续研究总结视频中提到的局限性AlphaFold Server结论二. 参考文献中文字幕视频链接,欢迎关注我的xhs账号:Google CEO 皮…

【MsSQL】数据库基础 库的基本操作

目录 一,数据库基础 1,什么是数据库 2,主流的数据库 3,连接服务器 4,服务器,数据库,表关系 5,使用案例 二,库的操作 1,创建数据库 2,创建…

华为配置Ethernet over GRE实现AC与无线网关之间的二层互通

华为配置Ethernet over GRE实现AC与无线网关之间的二层互通 组网图形 图1 通过Ethernet over GRE实现AC与无线网关之间的二层互通的组网图 组网需求数据规划配置思路操作步骤配置文件 组网需求 如图1所示,某企业通过无线网络为用户提供上网服务,其中A…

探索静态住宅代理IP:网络安全的隐形守护者

在当今这个数字化高速发展的时代,网络安全问题愈发凸显其重要性。无论是企业级的网络运营,还是个人用户的网络活动,都需要一个安全、稳定的网络环境。而在这个环境中,静态住宅代理IP以其独特的优势,逐渐成为了网络安全…

Java——类与对象

目录 一、面向对象的初步认识 1.1 什么是面向对象 1.2 面向对象与面向过程 二、类的定义与使用 2.1 简单认识类 2.2 类的定义格式 三、类的实例化 3.1 什么是实例化 3.2 类和对象的说明 四、this引用 4.1 为什么要有this引用 4.2 什么是this引用 ​编辑 4.3 this引用…

鸿蒙OpenHarmony:【常见编译问题和解决方法】

常见问题 常见编译问题和解决方法 鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 提示“usr/sbin/ninja: invalid option -- w” 现象描述: 编译失败,提示“usr/sbin/ninja: invalid…

GO: 定时器NewTimer、NewTicker 和time.After

Go 之iota iota是一个常量计数器,一般在常量表达式中使用,可以理解为const定义常量的行数的索引,注意是行数 使用场景 主要应用在需要枚举的地方 示例1 package main import "fmt" const (NoPay iota // 订单未支付 0Pai…

设备二维码怎么生成?三分钟即可搞定

在现代工业生产中,设备的维护和巡检是保障生产连续性和安全性的重要环节。随着技术的发展,二维码技术因其便捷性和高效性被广泛应用于设备巡检中。 给每个设备配备一个二维码,一线人员用手机扫一扫,几秒钟就能上报巡检结果&#…

Measurement and Analysis of Large-Scale Network File System Workloads——论文泛读

ATC 2008 Paper 分布式元数据论文阅读笔记整理 问题 网络文件系统在当今的数据存储中发挥着越来越重要的作用。使用网络文件系统可以降低管理成本,从多个位置可靠地访问的数据。这些系统的设计通常以对文件系统工作负载和用户行为的理解为指导[12,19&a…

Chrome浏览器的一些实用命令

Chrome浏览器提供了许多实用的命令和内部页面,可以帮助用户更高效地管理和使用浏览器。以下是一些常用的Chrome命令和内部页面: chrome://about/: 查看所有支持的命令和内部页面。在地址栏中输入这个命令后,会列出所有可用的内部命令和URL&a…

C++ LCR 090. 打家劫舍 II

文章目录 一、题目描述二、参考代码 一、题目描述 一个专业的小偷,计划偷窃一个环形街道上沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋…

408数据结构算法题专项-链表总结归纳

历年链表题目详解: 2009 倒数第k结点 2012 找共同后缀起始 2015 删除绝对值相同点 2019 重新排列结点 分析:难度整体来说不难,重点考察的是基本功和画图。 重点需要掌握的技巧: ①增 增加即利用头插法或尾插法进行结点添加 …

docker 容器无法直接读取宿主机文件

最近一个需求, 要在后端直接使用代码直接生成 pdf 文档, 由于使用的 apache 的工具包, 该工具包无法直接解析中文字体, 需要导入外部 中文插件包, 相关代码如下: PDPage page new PDPage(PDRectangle.A4);document.addPage(page);PDFont fontFile PDType0Font.load(document…

瑞友天翼应用虚拟化系统SQL注入漏洞

文章目录 漏洞描述漏洞原理影响版本漏洞复现防御方法 漏洞描述 瑞友天翼应用虚拟化系统是基于服务器计算架构的应用虚拟化平台,它将用户各种应用软件集中部署到瑞友天翼服务集群,客户端通过 WEB 即可访问经服务器上授权的应用软件,实现集中应…