HNSW - 分层可导航小世界

背景

上一篇《商家平台AI智能搜索工程实践》提到向量数据库索引使用的是HNSW,具体的相关历史可自己了解,本文主要尝试用最通用的语言阐述HNSW原理和数据结构。

基础技术

HNSW 最大的两项基本技术:概率跳跃表和可导航小世界图。

概率跳跃表

概率跳跃表像排序数组一样快速搜索,同时使用链表结构可以轻松(且快速)地插入新元素(这是排序数组无法实现的)。

跳过列表的工作原理是构建多层链表。在第一层,我们找到跳过许多中间节点/顶点的链接。随着层级的下降,每个链接的“跳过”次数会减少。

要搜索跳跃表,我们从“跳跃”最长的最高层开始,沿着边缘向右(下方)移动。如果我们发现当前节点的“键”大于我们要搜索的键——我们就知道我们已经超出了目标,因此我们向下移动到下一层的上一个节点。

在这里插入图片描述

可导航小世界图

HNSW 继承了相同的分层格式,最高层的边较长(用于快速搜索),较低层的边较短(用于准确搜索)。

可导航小世界(NSW) 图采用一个邻近图,构建它时同时包含长距离和短距离链接,那么搜索时间就能降低到 (多/) 对数复杂度。

图中的每个顶点都与其他几个顶点相连。我们将这些相连的顶点称为“朋友”,每个顶点都维护一个“朋友”列表,构成了我们的图。

在搜索 NSW 图时,我们从一个预定义的入口点开始。该入口点连接到几个附近的顶点。我们确定这些顶点中哪个最接近我们的查询向量,然后移动到那里。

在这里插入图片描述
我们重复贪婪路由搜索过程,通过识别每个好友列表中最近的相邻顶点,从一个顶点移动到另一个顶点。最终,我们将找不到比当前顶点更近的顶点——这是一个局部最小值,并作为我们的停止条件。

可导航小世界模型被定义为任何使用贪婪路由且具有(多/)对数复杂度的网络。当图不可导航时,贪婪路由的效率对于较大的网络(1-10K+ 个顶点)会失效。

路由(字面意思是我们在图中的路径)由两个阶段组成。首先是“缩小”阶段,穿过低度顶点(度是指顶点的链接数);然后是“放大”阶段,穿过更高度顶点。

在这里插入图片描述
高度顶点具有许多链接,而低度顶点具有很少的链接。

我们的停止条件是在当前顶点的好友列表中找不到更近的顶点。因此,在缩小阶段(链接较少,找到更近顶点的可能性较小),我们更有可能陷入局部最小值并过早停止。

为了最大限度地降低提前停止的可能性(并提高召回率),我们可以增加顶点的平均度数,但这会增加网络复杂度(以及搜索时间)。因此,我们需要在召回率和搜索速度之间平衡顶点的平均度数。

另一种方法是从高维顶点开始搜索(先放大)。对于NSW,这确实提高了低维数据的性能。我们将看到,这也是HNSW结构中的一个重要因素。

HNSW 是 NSW 的自然演变,它借鉴了 Pugh 概率跳跃表结构的多层层次的灵感。

为 NSW 添加层级结构会生成一个图表,其中链接被分散在不同层级上。顶层包含最长的链接,底层包含最短的链接。

在这里插入图片描述
HNSW 的分层图,顶层是我们的入口点,仅包含最长的链接,随着我们向下移动层,链接长度变得更短且更多。

在搜索过程中,我们进入顶层,在那里找到最长的链接。这些顶点往往是度数较高的顶点(链接跨越多个层),这意味着我们默认从NSW 描述的放大阶段开始。

我们像在 NSW 中一样遍历每一层的边,贪婪地移动到最近的顶点,直到找到局部最小值。与 NSW 不同的是,此时,我们移动到较低层的当前顶点,并重新开始搜索。重复此过程,直到找到底层(即第 0 层)的局部最小值。

在这里插入图片描述
在构建图的过程中,向量会被逐个迭代插入。层数由参数L表示。向量插入到给定层的概率由概率函数给出,该概率函数经“层级乘数”m_L归一化,其中m_L = ~0表示向量仅插入到第 0 层。

在这里插入图片描述
概率函数在每一层(第 0 层除外)重复执行。该向量被添加到其插入层及其下方的每一层。

HNSW 的创建者发现,当我们最小化跨层共享邻居的重叠时,可以获得最佳性能。降低 m_L有助于最小化重叠(将更多向量推送到第 0 层),但这会增加搜索过程中的平均遍历次数。因此,我们使用一个能够平衡两者的m_L值。此最佳值的经验法则是 [1]。1/ln(M)

图的构建从顶层开始。输入图后,算法贪婪地遍历边,找到插入向量q的ef个最近邻——此时ef = 1。

找到局部最小值后,它会向下移动到下一层(就像搜索过程中所做的那样)。这个过程不断重复,直到到达我们选择的插入层。从这里开始构建的第二阶段。

ef值增加到(我们设置的参数),意味着将返回更多最近邻。在第二阶段,这些最近邻将成为新插入元素qefConstruction的链接候选,并作为下一层的入口点。

从这些候选对象中添加M 个邻居作为链接——最直接的选择标准是选择最接近的向量。

经过多次迭代后,添加链接时需要考虑另外两个参数。M_max定义顶点可以拥有的最大链接数,M_max0定义相同的链接数,但针对的是第0 层的顶点。

在这里插入图片描述
解释分配给每个顶点的链接数以及 M、M_max 和 M_max0 的影响。
插入的停止条件是达到第 0 层的局部最小值。

现在我们已经探索了 HNSW 背后的理论以及它在 Faiss 中的实现方式——让我们看看不同参数对我们的召回、搜索和构建时间以及每个参数的内存使用情况的影响。

我们将修改三个参数:M、、efSearch和efConstruction。

在这里插入图片描述
较高的M和efSearch值会对召回率产生很大影响——而且显然efConstruction需要一个合理的值。我们也可以增加 和 值,以在较低的和值efConstruction下实现更高的召回率。MefSearch

然而,这种性能并非免费。与往常一样,我们需要在召回率和搜索时间之间取得平衡——让我们来看看。

在这里插入图片描述
虽然较高的参数值可以提高召回率,但这对搜索时间的影响可能非常显著。这里我们搜索1000相似的向量(xq[:1000]),召回率/搜索时间可能在 80%(1 毫秒)到 100%(50 毫秒)之间变化。如果我们对一个不太好的召回率感到满意,搜索时间甚至可能达到 0.1 毫秒。

当我们使用少量查询进行搜索时,确实efConstruction对搜索时间影响不大。但对于这里1000使用的查询,的微小影响efConstruction就变得非常显著。

如果您认为您的查询量通常较低,efConstruction则这是一个值得增加的参数。它可以提高召回率,而对搜索时间的影响却很小,尤其是在使用较低M值时。

在这里插入图片描述
仅搜索一个查询时,efConstruction 和搜索时间。使用较低的 M 值时,对于不同的 efConstruction 值,搜索时间几乎保持不变。

这一切看起来都很棒,但是 HNSW 索引的内存使用情况怎么样呢?这里事情就变得不那么吸引人了。

在这里插入图片描述
使用我们的 Sift1M 数据集,随着 M 值的增加,内存使用量也随之增加。efSearch 和 efConstruction 对内存使用量没有影响。

和efConstruction都efSearch不会影响索引内存的使用,只剩下M。即使M在 的较低值下2,我们的索引大小也已经超过 0.5GB,在M的情况下则达到了近 5GB 512。

因此,尽管 HNSW 具有令人难以置信的性能,但我们需要权衡其高内存使用率以及由此产生的不可避免的高基础设施成本。

提高内存使用率和搜索速度

就内存利用率而言,HNSW 并非最佳索引。但是,如果这一点很重要,并且无法使用其他索引,我们可以通过使用乘积量化 (PQ)压缩向量来改进它。使用 PQ 会降低召回率并增加搜索时间——但一如既往,ANN 的大部分工作都是在平衡这三个因素。

如果我们想提高搜索速度,也可以!只需在索引中添加一个 IVF 组件即可。

本文就介绍完了用于向量相似性搜索的分层可导航小世界图!现在您已经了解了 HNSW 背后的原理以及如何在 Faiss 中实现它,您可以继续在自己的向量搜索应用程序中测试 HNSW 索引,或者使用像Pinecone或 OpenSearch 这样已经具备向量搜索功能的托管解决方案!

参考

[1] E. Bernhardsson,人工神经网络基准(2021),GitHub

[2] W. Pugh,《跳过列表:平衡树的概率替代方案》(1990 年),《ACM 通讯》,第 33 卷,第 6 期,第 668-676 页

[3] Y. Malkov、D. Yashunin,《使用分层可导航小世界图进行高效稳健的近似最近邻搜索》(2016),《IEEE 模式分析与机器智能学报》

[4] Y. Malkov 等人,近似最近邻搜索小世界方法(2011),国际信息与通信技术与应用会议

[5] Y. Malkov 等人,高维通用度量空间中近似最近邻搜索问题的可扩展分布式算法(2012),相似性搜索与应用,第 132-147 页

[6] Y. Malkov 等人,基于可导航小世界图的近似最近邻算法(2014),信息系统,第 45 卷,第 61-68 页

[7] M. Boguna 等人,《复杂网络的可导航性》(2009),《自然物理》,第 5 卷,第 1 期,第 74-80 页

[8] Y. Malkov, A. Ponomarenko,不断增长的同质网络是可自然导航的小世界(2015), PloS one

<think>嗯,用户之前问过Elasticsearch中的nested和parent-child的区别,现在又提到HNSW。看来他们对搜索引擎或数据库的底层算法感兴趣。HNSW可能是在讨论向量搜索相关的技术,比如近似最近邻(ANN)算法。我需要确认HNSW的全称和它在Elasticsearch中的应用场景。 首先,HNSW是Hierarchical Navigable Small World的缩写,常用于高效向量相似性搜索。用户可能是在学习向量搜索时遇到了这个术语,或者在使用Elasticsearch的kNN搜索功能时接触到HNSW。需要解释HNSW的基本原理、优势以及实际应用。 用户之前的问题涉及数据结构(nested和parent-child),现在转向算法,可能需要将HNSW与之前的内容联系起来,比如在Elasticsearch中如何应用HNSW进行向量检索。要注意用户的技术水平,可能需要用比较易懂的语言解释层次化的图结构,以及为什么HNSW适合高维数据。 还要考虑用户可能的实际需求,比如他们是否在构建推荐系统、语义搜索或图像检索,这些场景常用到向量相似度搜索。需要给出具体的使用例子,比如在Elasticsearch中如何配置HNSW索引,以及查询的示例。 另外,用户可能关心HNSW与其他ANN算法(如LSH、IVF)的比较,所以需要简要对比优缺点,帮助用户理解选择HNSW的原因。同时,提到参数调优也很重要,比如ef_construction和m对性能的影响,帮助用户在实际应用中进行优化。 最后,总结HNSW的适用场景,确保用户能根据自身需求判断是否采用该算法。可能还需要提示Elasticsearch版本兼容性,因为HNSW支持可能从某个版本开始引入,避免用户在使用旧版本时遇到问题。</think>以下是关于 **HNSW(Hierarchical Navigable Small World)** 算法的详细解析,从核心原理到实际应用场景的全方位解读: --- ### **1. 核心原理** #### **基本概念** HNSW 是一种**高效近似最近邻搜索(ANN)算法**,专为高维向量设计。其核心思想是构建一个**多层图结构**,通过分层跳跃机制加速搜索。 - **分层结构**: 由多层图组成,上层是稀疏图(快速导航),下层是稠密图(精确搜索)。 - **导航策略**: 从顶层开始搜索,逐步向下层细化,类似“先粗后精”的二分查找。 #### **关键技术** - **小世界网络**: 每个节点与邻近节点(短边)和随机远程节点(长边)连接,平衡搜索效率与精度。 - **动态插入**: 新向量根据概率分配到不同层,高层概率低(稀疏),低层概率高(稠密)。 --- ### **2. 算法流程** #### **搜索过程** 1. **入口选择**:从最高层的随机节点出发。 2. **贪婪下降**:在当前层找到距离目标最近的节点。 3. **逐层细化**:进入下一层继续搜索,直到最底层。 #### **插入过程** 1. **确定层级**:按指数衰减概率分配层级(例如:$P(level) = 1/2^{level}$)。 2. **逐层连接**:从高层到低层,在每层中找到最近邻节点并建立连接。 --- ### **3. 性能优势** | **维度** | **HNSW** 优势 | |-------------------|------------------------------------------------------------------------------| | **查询速度** | $O(\log n)$ 时间复杂度,比暴力搜索快 100-1000 倍 | | **内存占用** | 相比树型结构(如 KD-Tree),内存开销更低 | | **高维适应性** | 对维度灾难(Curse of Dimensionality)抗性更强 | | **精度控制** | 通过参数调节在速度与召回率之间平衡(如 `efSearch` 值越大精度越高) | --- ### **4. 参数调优** | **关键参数** | **作用** | **典型值** | |-------------------|-----------------------------------------------------------------------------|------------------| | `M` | 每层图中节点的最大连接数,影响内存和搜索速度 | 16-64 | | `efConstruction` | 控制插入时的搜索范围,值越大构建质量越高 | 100-400 | | `efSearch` | 控制查询时的搜索范围,值越大召回率越高 | 50-200 | --- ### **5. 实际应用** #### **典型场景** - **推荐系统**:用户/商品向量相似度匹配。 - **语义搜索**:文本嵌入向量的快速检索- **图像检索**:基于 CNN 特征向量的相似图片搜索。 #### **Elasticsearch 集成** Elasticsearch 从 8.0 版本开始支持 HNSW 作为 `dense_vector` 字段的索引类型: ```json PUT /my_index { "mappings": { "properties": { "vector": { "type": "dense_vector", "dims": 768, "index": true, "similarity": "cosine", "index_options": { "type": "hnsw", "m": 32, "ef_construction": 100 } } } } } ``` #### **查询示例** ```json GET /my_index/_search { "knn": { "field": "vector", "query_vector": [0.12, 0.24, ..., 0.88], "k": 10, "num_candidates": 100 } } ``` --- ### **6. 对比其他 ANN 算法** | **算法** | **优势** | **劣势** | |---------------|-----------------------------------|-----------------------------------| | **HNSW** | 综合性能最优,支持动态插入 | 内存消耗较高 | | **IVF** | 内存占用低,适合大规模数据 | 需要预训练,静态数据集支持更好 | | **LSH** | 计算简单,适合低精度场景 | 召回率较低 | --- ### **7. 总结** - **优先选 HNSW**:需要高精度、低延迟的向量搜索场景。 - **参数调优**:根据数据规模和质量调整 `M` 和 `ef` 系列参数。 - **资源权衡**:内存充足时首选 HNSW,资源受限可考虑 IVF 或 PQ 压缩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_sunjinxin

谢谢老板的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值