Elasticsearch:简化 KNN 搜索

这篇具有很好参考价值的文章主要介绍了Elasticsearch:简化 KNN 搜索。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:来自 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 设为可选项。太好了!但是默认值应该设置为多少呢?

knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库

此时有两个选项。选择看起来不错的选项,发布并希望一切顺利,或者做出艰苦的努力,进行广泛的评估以让数据驱动我们的决策。在 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 进行配置和部署的,因此对于所有类似的测试都是一致的。

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

结果

每个指定数据集和参数组合的召回率 - 延迟图可以在下面找到(越高且越靠左越好):

knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库

将范围缩小到 dense_vector 和 openai_vector 轨迹,我们有关于 latency@50th 和召回率的绝对值数据如下:

knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
Dense Vector latency@50
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
Dense Vector recall
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
OpenAI latency@50
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
OpenAI Recall

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

knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
Dense Vector Multiple Segments
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
标题
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
Cohere Vector
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
OpenAI Vector
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
Dense Vector

   

knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
Dense Vector Multiple Segments
knn elas,Elasticsearch,AI,Elastic,elasticsearch,jenkins,大数据,搜索引擎,全文检索,数据库
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文章来源地址https://www.toymoban.com/news/detail-860042.html

到了这里,关于Elasticsearch:简化 KNN 搜索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 增强FAQ搜索引擎:发挥Elasticsearch中KNN的威力

    英文原文地址:https://medium.com/nerd-for-tech/enhancing-faq-search-engines-harnessing-the-power-of-knn-in-elasticsearch-76076f670580 增强FAQ搜索引擎:发挥Elasticsearch中KNN的威力 2023 年 10 月 21 日 在一个快速准确的信息检索至关重要的时代,开发强大的搜索引擎是至关重要的。随着大型语言模型(LLM)和

    2024年02月02日
    浏览(35)
  • Elasticsearch:探索 k-nearest neighbor (kNN) 搜索

    由于新一代机器学习模型可以将各种内容表示为向量,包括文本、图像、事件等,人们对向量搜索的兴趣激增。 通常称为 “ 嵌入模型 (embedding models)”,这些强大的表示可以以超越其表面特征的方式捕获两段内容之间的相似性。 K 最近邻 (KNN) 搜索又名语义搜索是一种简单

    2024年02月08日
    浏览(40)
  • 增强常见问题解答搜索引擎:在 Elasticsearch 中利用 KNN 的力量

    在快速准确的信息检索至关重要的时代,开发强大的搜索引擎至关重要。 随着大型语言模型和信息检索架构(如 RAG)的出现,在现代软件系统中利用文本表示(向量/嵌入)和向量数据库已变得越来越流行。 在本文中,我们深入研究了如何使用 Elasticsearch 的 K 最近邻 (KNN) 搜

    2024年02月08日
    浏览(49)
  • Elasticsearch:什么是 kNN?

    kNN(即 k 最近邻算法)是一种机器学习算法,它使用邻近度将一个数据点与其训练并记忆的一组数据进行比较以进行预测 。 这种基于实例的学习为 kNN 提供了 “惰性学习(lazy learning)” 名称,并使算法能够执行分类或回归问题。 kNN 的假设是相似的点可以在彼此附近找到

    2024年02月20日
    浏览(37)
  • Elastic 发布 Elasticsearch Relevance Engine™ — 为 AI 革命提供高级搜索能力

    作者:Matt Riley 今天我们将向大家介绍 Elasticsearch Relevance Engine™(ESRE™) ,这是一种创建高度相关的 AI 搜索应用程序的新功能。ESRE 建立在 Elastic 在搜索领域的领导地位以及超过两年的机器学习研究和开发基础之上。Elasticsearch Relevance Engine 结合了 AI 的最佳实践和 Elastic 的文

    2024年02月06日
    浏览(39)
  • ES-KNN搜索

    根据向量查询相近的目标。 常见的使用场景: 基于自然语言算法的相关性排名 相似推荐 相似的图片或视频搜索 使用knn需要对数据进行预处理,你需要把需要匹配的数据转换为有意义的向量值,然后写入目标索引的dense_vector字段中。 对于KNN搜索,ES支持两种方法: 使用scr

    2024年01月24日
    浏览(44)
  • Elasticsearch:如何在 Elastic 中实现图片相似度搜索

    作者:Radovan Ondas 在本文章,我们将了解如何通过几个步骤在 Elastic 中实施相似图像搜索。 开始设置应用程序环境,然后导入 NLP 模型,最后完成为你的图像集生成嵌入。 Elastic 图像相似性搜索概览 Elasticsearch:如何在 Elastic 中实现图片相似度搜索 第一步是为你的应用程序设

    2024年01月22日
    浏览(48)
  • java程序中使用ES knn搜索

    Elasticsearch 向量搜索应用介绍_es 向量检索_文晓武的博客-CSDN博客 Elasticsearch8.x KNN search 使用方式及参数介绍_elasticsearch knn_小帅毛的博客-CSDN博客 ElasticSearch的Dense Vector_elasticsearch dense vector_若石之上的博客-CSDN博客 Elastic Search : 8.0.1  RestClient restClient = RestClient.builder(          

    2024年02月12日
    浏览(45)
  • Elasticsearch:使用 ELSER 释放语义搜索的力量:Elastic Learned Sparse EncoderR

    在信息过载的时代,根据上下文含义和用户意图而不是精确的匹配来查找相关搜索结果已成为一项重大挑战。 传统的搜索引擎通常无法理解用户查询的语义上下文,从而导致相关性较低的结果。 在现代向量搜索之前,我们有 “传统”的 词袋(Bags of word - BOW)方法。

    2024年02月15日
    浏览(53)
  • ES8 向量搜索(knn-search)java-api 实践

    官方文档-knn-search kNN搜索 k-nearest neighbor (kNN)搜索找到与查询向量最近的k个向量,如通过相似度计算。 kNN的常见用例包括: 基于自然语言处理(NLP)算法的相关性排序 产品推荐和推荐引擎 图像或视频的相似性搜索 要运行kNN搜索,您必须能够将数据转换为有意义的向量值

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包