Elasticsearch:简化 KNN 搜索

news2024/11/16 21:38:01

作者:来自 Elastic Panagiotis Bailis

在这篇博客文章中,我们将深入探讨我们为了使 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)。

另一方面,k 和 num_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]
   }
}

使 k 和 num_candidates 成为可选项

我们想要将 k 和 num_candidates 设为可选项。太好了!但是默认值应该设置为多少呢?

此时有两个选项。选择看起来不错的选项,发布并希望一切顺利,或者做出艰苦的努力,进行广泛的评估以让数据驱动我们的决策。在 Elastic,我们喜欢这样的挑战,并希望确保任何决定都是有充分理由的!

刚刚我们提到,KNN 搜索中的 k 是每个分片返回的结果数,因此一个明显的默认值是使用 size。因此,每个分片将返回 size 个结果,然后我们将它们合并并排序以找到全局前 size 个结果。这也非常适用于 KNN 查询,其中根本没有 k 参数,而是基于请求的 size 进行操作(请记住,KNN 查询的行为就像任何其他查询,如 term、prefix 等)。因此,size 看起来是一个合理的默认值,可以涵盖大多数用例(或者至少在入门体验期间足够好!)。

另一方面,num_candidates 则大不相同。这个参数特定于 HNSW 算法,控制着我们将考虑的最近邻队列的大小(对于感兴趣的人来说:这相当于原始论文中的 ef 参数)。

在这里,我们可以采取多种方法:

  • 我们可以考虑每个图的大小,并制定一个函数,用于计算适当的 num_candidates,以匹配 N 个索引向量。
  • 我们可以查看底层数据分布,并尝试估算所需的探索(也许还可以考虑 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(考虑到指定了 no size 的请求)
  • k = 20
  • k = 50
  • k = 100
  • k = 500
  • k = 1000

数据

鉴于没有放之四海而皆准的解决方案,我们希望测试具有不同属性的各种数据集。因此,这些数据集具有不同的总向量数、维度,并且来自不同的模型,因此具有不同的数据分布。同时我们也可以使用 rally,这是一个很棒的基准测试工具(https://github.com/elastic/rally),它已经支持运行一系列查询并为多个向量数据集提取指标。

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

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

为此,我们稍微修改了轨迹(即 rally 的测试场景),以包括额外的度量配置,添加了一些新的配置,最终得到了以下一组轨迹:

  • dense-vector (2M docs, 96dims): https://github.com/elastic/rally-tracks/tree/master/dense_vector
  • so-vector (2M docs, 768 dims): https://github.com/elastic/rally-tracks/tree/master/so_vector
  • cohere-vector (3M docs, 768 dims): rally-tracks/cohere_vector at master · elastic/rally-tracks · GitHub
  • openai-vector (2.5M docs, 1536dims): https://github.com/elastic/rally-tracks/tree/master/openai_vector
  • Glove 200d (1.2M, 200dims) new track created based on GitHub - erikbern/ann-benchmarks: Benchmarks of approximate nearest neighbor libraries in Python 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_vector 和 openai_vector 轨迹,我们有关于 latency@50th 和召回率的绝对值数据如下:

Dense Vector latency@50

Dense Vector recall

OpenAI latency@50

OpenAI Recall

类似地,每个场景的 HNSW 图节点访问的第 99 百分位数如下(数值越小越好):

Dense Vector Multiple Segments
标题

Cohere Vector

OpenAI Vector
Dense Vector

   

Dense Vector Multiple Segments

Glove Vector

少即是多*

*嗯,并非在所有情况下都是如此,但嘿 :) 从结果中可以看出两点:

  • 单个段与多个段明显影响召回率和延迟指标呈反比关系。段数较少会降低延迟(因为我们要遍历的图较少,即运行的搜索较少),这很好,但它也以相反的方式影响了召回率,因为由于 num_candidates 列表较少,可能会漏掉一些好的候选项。
  • 即使探索量很少,我们在几乎所有情况下都可以达到足够好的召回率,这很棒!

我们一直致力于改进多段搜索(这篇文章中有一个很好的例子),因此我们预计这种权衡在未来将不再是一个问题(这里报告的数字不包括这些改进)。

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

  • num_candidates = 1.5 * k - 这几乎在所有情况下都能达到足够好的召回率,并且延迟得分非常好。
  • num_candidates = Math.max(100, k) - 这在特别是较低的 k 值时达到了稍微更好的召回率,但权衡之处在于增加了图探索和延迟。

经过认真考虑和(漫长的!)讨论,我们决定采用前一种默认设置,即设置 num_candidates = 1.5 * k。我们需要进行的探索要少得多,而且召回率始终在 75% 以上,大多数情况下在 90% 以上,这应该能够提供足够好的入门体验。

结论

我们在 Elastic 处理 knn 搜索的方式在不断进化,我们持续引入新功能和改进,因此这些参数和整体评估很可能很快就会过时!我们总是在密切关注,一旦发生变化,我们将确保跟进并相应调整我们的配置!

需要记住的一件重要事情是,这些值仅作为简化入门体验和非常通用用例的合理默认值。用户可以轻松地在自己的数据集上进行实验,并根据自己的需求进行相应调整(例如,在某些情况下,召回率可能比延迟更重要)。

快乐调优 😃

准备在你的应用中构建 RAG 吗?想尝试使用向量数据库的不同 LLM 吗? 查看 Github 上的 LangChain、Cohere 等示例笔记本,并加入即将开始的 Elasticsearch 工程师培训!

原文:Simplifying knn search — Elastic Search Labs

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

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

相关文章

对接浦发银行支付(八)-- 对账接口

一、背景 本文不是要讲述支付服务的对账模块具体怎么做,仅是介绍如何对接浦发银行的对账接口。 也就是说,本文限读取到对账文件的内容,不会进一步去讲述如何与支付平台进行对账。 如果要获取商户的对账单,需要遵循以下步骤&…

数据分析_数据分析思维(1)

数据分析_数据分析思维(1) 这篇文章具体的给大家介绍数据分析中最为核心的技术之一: 数据分析思维的相关内容。 一、数据分析的三种核心思维 作为新手数据分析师或数据运营, 在面对数据异常的时候, 好多小伙伴都会出现: “好像是A引起的”, “好像也和B渠道有关”, “也可能…

江苏瑞达环保科技股份有限公司| 邀您参加2024全国水科技大会暨技术装备成果展览会

—— 展位号:A18 —— 江苏瑞达环保科技股份有限公司是一家致力于环境保护和可持续发展的高新技术企业,专注于环境治理技术研发和环保节能装备制造,为工业企业提供可靠的工程解决方案。2023年,瑞达科技被认定为江苏省省级专精特新企业。 瑞达科技成立于2…

rCore-Turorial-Book第三课(计算机启动流程和程序内存布局与编译流程探索)

本节任务:梳理程序在操作系统中被编译运行的全流程,大体了解我们在没有操作系统的情况下,我们会面对那些困难 重点 1. 计算机组成基础 面对的困难:没有操作系统,我们必须直面硬件资源,管理起他们并为应用程…

本地环境通过ssh通道连接服务器数据库,实现本地客户端和代码可以访问数据库

使用方法: ssh -p 搭建隧道的端口 -fNL 本地端口:远程ip:远程端口号 搭建隧道的账号搭建隧道的ip 可以增加参数-v,输出更多的信息 ssh -p 搭建隧道的端口 -fNL 本地端口:远程ip:远程端口号 -v 搭建隧道的账号搭建隧道的ip 有时候,测试环境的数据库不允许…

YOLOv8-PySide --- 基于 ultralytics 8.1.0 发行版优化 | 代码已开源

YOLOv8-PySide — 基于 ultralytics 8.1.0 发行版优化 Github 项目地址:https://github.com/WangQvQ/Ultralytics-PySide6 BiliBili视频地址:https://www.bilibili.com/video 页面效果 如何使用 pip install ultralytics8.1.0 or git clone --branch v…

如何判别三角形和求10 个整数中最大值?

分享每日小题,不断进步,今天的你也要加油哦!接下来请看题------> 一、已知三条边a,b,c能否构成三角形,如果能构成三角形,判断三角形的类型(等边三角形、等腰三角形或普通三角形 …

通过Docker新建并使用MySQL数据库

1. 安装Docker 确保您的系统上已经安装了Docker。可以通过以下命令检查Docker是否安装并运行: systemctl status docker如果没有安装或运行,请按照官方文档进行安装和启动。 2. 拉取MySQL镜像 从Docker Hub拉取MySQL官方镜像。这里以MySQL 5.7版本为…

(回溯)记忆化搜索和dp

动态规划的核心就是 状态的定义和状态的转移 灵神 的 回溯改递归思路 首先很多动态规划问题都可以采用 回溯 的思想 回溯主要思想就是把 一个大问题分解成小问题 比如 采用子集类回溯问题中的核心思想-> 选或不选 或者 选哪个 记忆化搜索之后 我们可以发现 每个新节点依…

【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制(CRC算法、MD5算法)

目录 UDP协议 UDP协议的报文结构及注意事项 UDP报文结构中的校验和字段 1. 校验和主要校验的内容 2. UDP校验和的实现方式 3. CRC(循环冗余校验)算法 4. MD5(Message Digest Algorithm 5) UDP协议 上一篇文章提过&#xf…

【C++】双指针算法:复写零

1.题目 别看这是一道简单题,它的通过率低于一些中等甚至困难的题目! 大大增加这道题目难度的是最后一句话:1.不可越界写入。2.就地修改。 如果可以再创建一个数组的话,那么这道题目就会非常简单,但这道题目必须要求在…

汽车IVI中控开发入门及进阶(十六):carplay认证

现在有些中控采用高通的芯片如8155、8295等,实现多屏互动等,但是也有一些车型走低成本方案,比如能够实现HiCar、CarLife或者苹果Apple的Carplay等能进行手机投屏就好了。 能实现CarPlay功能通过Carplay认证,也就成了一些必须的过程,国产车规级中控芯片里,开阳有一款ARK1…

AI视频分析技术的常用开源模型及TSINGSEE青犀AI视频识别分析能力介绍

AI视频分析技术是指利用人工智能技术来对视频数据进行分析和处理的技术。开源模型是指可以免费获取和使用的代码模型,可以帮助开发人员快速构建和部署AI视频分析应用程序。 以下是一些业内常用的用于AI视频分析技术的开源模型: OpenCV:Open…

kali搭建vulfocus靶场

电脑安装kali,使用kali搭建靶场,自己电脑作为VPS使用 kali 先装好docker: # docker version # 查看当前是否有docker,如果无docker ,则进行docker安装 # apt install docker.io 安装完成后,再次输入 # docker…

【数据结构】二叉树链式结构的实现《遍历,实现》(题库+解析+源码)

前言 二叉树的学习离不开对堆的理解,这是上篇堆的传送门 http://t.csdnimg.cn/F6Jp3 1.二叉树链式结构的实现 1.1 前置说明 在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二 叉树结构掌握还…

【Java】常见锁策略 CAS机制 锁优化策略

前言 在本文会详细介绍各种锁策略、CAS机制以及锁优化策略 不仅仅局限于Java,任何和锁相关的话题,都可能会涉及到下面的内容。 这些特性主要是给锁的实现者来参考的. 普通的程序猿也需要了解一些, 对于合理的使用锁也是有很大帮助的 文章目录 前言✍一、…

收集统计信息报错ora-00600[16515]问题处理

1、基础环境 操作系统Oracle Solaris 11.3 数据版本Oracle 12.2 2、故障理像 对一个20T的大库收集一下全库的统计信息 原因是现在都2024年了,这个库的统计信息基本都是2021年, 没具体查找啥原因导致的系统自定义的收集任务失败,于是决定手…

2024年内外贸一体化融合发展(长沙)交易会

2024年内外贸一体化融合发展(长沙)交易会 一、总体思路 充分发挥湖南作为全国内外贸一体化试点地区作用,坚持“政府主导、市场驱动、企业为主”的原则,以“助力双循环,拓展新市场,促进新消费”为主题&…

腾讯云服务器价格明细表2024年最新(CPU内存/带宽/磁盘)

腾讯云服务器价格明细表2024年最新(CPU内存/带宽/磁盘)腾讯云服务器租用优惠价格表:轻量应用服务器2核2G3M价格61元一年,2核2G4M价格99元一年、135元15个月、540元三年,2核4G5M带宽165元一年、252元15个月、756元3年&a…

VBA运行后,为什么excel的三个工作表结果一样?

运行完了excel的三个工作表的结果一样,问题在哪呢? 代码如下: Sub 计算成绩() 计算成绩 Macro i为工作表行号 Dim i, m, total As Integer Dim w1 As Worksheet For m 1 To Worksheets.count Set w1 Worksheets(m) i 2 total 0 …