随着机器学习、深度神经网络的不断发展,数据的向量化无处不在。而针对海量向量数据的搜索,无论是工业界还是学术界都做了大量的研究。本文主要讲解两个基于近邻图的向量搜索算法,并比较其适用场景。

这里不得不先提一个学术上的对应名词 Approximate Nearest Neighbor Search (ANNS),近似的最近邻搜索。之所以近似是由于精确的近邻搜索太过困难,研究随之转向了在精确性和搜索时间做取舍。由于精确的向量搜索在海量数据的场景下搜索时间过长,所以目前的常见做法,是在向量上建立近似搜索索引。

这里先介绍一下现在常用的索引类型以及它们的局限性。首先是基于树的算法,这里举例较为经典的 KD-tree。这种索引类型在向量维度稍大一些的情况下 (d>10),索引性能会急剧下降甚至不如暴力搜索。再说说基于 LSH (locality-sensitive hashing) 的索引,如果想要取得高召回率,LSH算法必须要建立大量的Hash表,这会使得索引大小膨胀数倍。不仅如此,树和LSH都属于空间切分类算法,此类算法有一个无法避免的缺陷,即为了提高搜索精度,只能增大搜索空间。图1-A描述了基于树的切分搜索,每个虚线分割出的区域是一个子树,如果搜索向量在子树的边缘时,算法需要搜索多个子树来获取结果。图1-B描述了基于 Hash 的切分搜索,虚线描述了每个独立的hash表,搜索面临的问题与基于树的搜索算法类似。所以空间切分类算法在最坏的情况下需要扫描几乎整个数据集,这在很多场景下显然是无法接受的。

由于图数据结构有天生近邻关系的特性,在图上做最近邻搜索看来是一种不错的思路,所以近年来基于图的向量搜索算法也是一个研究热点。

近邻图(Proximity Graph):最朴素的图算法

近邻图的特性可以粗略理解成:构建一张图,每一个顶点连接着最近的N个顶点。它的搜索过程可见下图,Target是待查询的向量。在搜索时,由于无法知道该从图的哪个区域开始搜索,所以我们选择任意一个顶点S出发。首先遍历S的邻居,找到距离与 Target 最近的A节点,将A设置为起始节点,再从A节点出发进行遍历,反复迭代,不断逼近,最后找到与 Target 距离最近的节点A``时搜索结束。

尽管思路很棒,但是基础的近邻图存在着非常多的问题,最为关键的就是搜索复杂度无法确定,孤岛效应难以解决,以及构建图的开销太高,复杂度达到了指数级别。由于这些原因,学术界在基础的近邻图上,对图的构建、度数的限制、边的裁选、图的连通性、节点的导向性等方面都做了许多改进。这里我们简单介绍下近年来较为热门的算法:HNSW 和 NSG。

HNSW

HNSW 的前身是 NSW (Navigable-Small-World-Graph)。NSW 通过设计出一个具有导航性的图来解决近邻图发散搜索的问题,但其搜索复杂度仍然过高,达到多重对数的级别,并且整体性能极易被图的大小所影响。HNSW 则是着力于解决这个问题。作者借鉴了 SkipList 的思想,提出了 Hierarchical-NSW 的设想。简单来说,按照一定的规则把一张的图分成多张,越接近上层的图,平均度数越低,节点之间的距离越远;越接近下层的图平均度数越高,节点之间的距离也就越近(见下图)。

搜索从最上层开始,找到本层距离最近的节点之后进入下一层。下一层搜索的起始节点即是上一层的最近节点,往复循环,直至找到结果(见下图)。由于越是上层的图,节点越是稀少,平均度数也低,距离也远,所以可以通过非常小的代价提供了良好的搜索方向,通过这种方式减少大量没有价值的计算,减少了搜索算法复杂度。更进一步,如果把 HNSW 中节点的最大度数设为常数,这样可以获得一张搜索复杂度仅为 log(n) 的图。

HNSW 利用多层图的优势,天生保证了图的连通性。并且由于每个新节点的加入都会被随机到任意一层中,这样做一定程度上避免了由于数据输入顺序从而改变图的分布,最后影响搜索路径的情况。

让我们来看看插入操作。新节点在插入到图中任意位置后,会建立 candidate pool,它用来保存所有搜索过的节点。首先将插入位置附近的节点加入到 pool 中,从 pool 中挑选出距离最近的节点,再从它出发寻找更近的节点,找到后将其加入到 pool 中(下图2-A到2-B),如果此节点都已搜索完毕,则挑选 pool 中的下一个节点进行搜索,不断循环N次,直至搜索到了 pool 的尾部,此时算法结束。在此过程中,如果pool满了但却发现了更近的节点,那么将它插入到 pool 中,剔除最远的节点,并且从新插入的位置处重新开始搜索(下图2-B到2-C)。这样减少了边的数量,改善了局部图的导航性。

NSG

NSG 全写为 Navigating Spreading-out Graph。NSG围绕四个方向来改进:图的连通性,减少出度,缩短搜索路径,缩减图的大小。具体是通过建立导航点 (Navigation Point),特殊的选边策略,  深度遍历收回离散节点(Deep Traversal)等方法。

首先是 Navigation Point,在建图时,首先需要一张预先建立的 K-nearest-neighbor-graph (KNNG) 作为构图基准。随机选择一个点作为 Navigation Point,后续所有新插入的节点在选边时都会将Navigation Point加入候选。在建图过程中,逐渐会将子图都和 Navigation point 相连接,这样其他的节点只需保持很少的边即可,从而减少了图的大小。每次搜索从 Navigation Point 出发能够指向具体的子图,从而减少无效搜索,获得更好搜索性能。

NSG 使用的择边策略与 HNSW 类似,但是不同于 HNSW 只选择最短边为有效边,NSG 使用的择边策略如下图。以点r为例,当r与p建立连接时,以r和p为圆心,r和p的距离为半径,分别做圆,如果两个圆的交集内没有其他与p相连接的点,则r与p相连(见图3-B)。在连接点s时,由于以s和p距离为半径的交集圆内,已有点r与p相连,所以s和p不相连(见图3-C)。下图中最终与点p相连的点只有r, t 和 q(见图3-A)。

NSG 这样做的原因是考虑到由于边数一多,整个图就会变得稠密,最后在搜索时会浪费大量算力。但是减少边的数量,带来的坏处也比较明显,最后的图会是一张稀疏图,会使得有些节点难以被搜索到。不仅如此,NSG 的边还是单向边。在如此激进的策略下,图的连通性就会产生问题,这时 NSG 选择使用深度遍历来将离群的节点收回到图中。通过以上步骤,图的建立就完成了。

HNSW 和 NSG 的比较

至此,我们大致了解了 HNSW 以及 NSG 两种算法的基本思路。HNSW 从结构入手,利用分层图提高图的导航性减少无效计算从而降低搜索时间,达到优化的目的。而 NSG 选择将图的整体度数控制在尽可能小的情况下,提高导航性,缩短搜索路径来提高搜索效率。

下面我们从内存占用,搜索速度,精度等方面来比较 HNSW 和 NSG。HNSW 由于多层图的结构以及连边策略,导致搜索时内存占用量会大于 NSG,在内存受限场景下选择 NSG 会更好。但是 NSG 在建图过程中无论内存占用还是耗时都大于 HNSW。此外 HNSW 还拥有目前 NSG 不支持的特性,即增量索引,虽然耗时巨大。对比其他的索引类型,无论 NSG 还是 HNSW 在搜索时间和精度两个方面,都有巨大优势。目前在Milvus内部已经实现了 NSG 算法,并将 KNNG 计算放到了 GPU 上进行从而极大地加快了 NSG 图的构建。未来 Milvus 还会集成 HNSW,以适配更广泛的场景。

欢迎加入Milvus社区

Milvus 源码
github.com/milvus-io/milvus

Milvus 官网
milvus.io

Milvus Slack 社区
milvusio.slack.com

Milvus CSDN 博客
zilliz.blog.csdn.net

Milvus 线上交流群

关注 ZILLIZ 公众号 > 点击菜单「线上交流」 > 添加 ZILLIZ bot 入群

© 2020 ZILLIZ™

Milvus 揭秘| 向量索引算法HNSW和NSG的比较相关推荐

  1. 向量索引算法HNSW和NSG的比较

    https://zhuanlan.zhihu.com/p/105594786?utm_source=wechat_session

  2. 0304 直播报名|向量索引算法介绍与优化

    想做向量搜索确又不知道该选择什么索引吗? 怎么样可以又快又准又最不占内存?相信这个问题很多 Milvus 用户都非常想知道. 然而, 在不同的应用场景下该如何选择一种合适的索引并非显而易见,需要在资源 ...

  3. 【推荐系统】向量召回算法 HNSW

    在推荐和搜索场景下,召回recall是一个关键的步骤,这个步骤通常需要在海量的目标中,召回部分与用户特征相近的item,所以有一个快速,并且准去的算法是非常有必要的,HNSW(Hierarchical ...

  4. 13 种高维向量检索算法全解析!数据库顶会 VLDB 2021 论文作者干货分享

    编者按: 以图搜图.商品推荐.社交推荐等社会场景中潜藏了大量非结构化数据,这些数据被工程师们表达为具有隐式语义的高维向量.为了更好应对高维向量检索这一关键问题,杭州电子科技大学计算机专业硕士王梦召等人 ...

  5. 图像检索:OPQ索引与HNSW索引

    图像检索:OPQ索引与HNSW索引 http://yongyuan.name/blog/opq-and-hnsw.html 2018年07月15日  Image Retrieval  CBIR 字数: ...

  6. 负样本的艺术,再读Facebook双塔向量召回算法

    负样本的艺术,再读Facebook双塔向量召回算法 Facebook这篇Embedding召回的论文,之前已经有几篇文章涉及过了,分别是<Embeding-based Retrieval in ...

  7. annoy向量检索算法

    一:算法目标 annoy 算法的目标是建立一个数据结构能够在较短的时间内找到任何查询点的最近点,在精度允许的条件下通过牺牲准确率来换取比暴力搜索要快的多的搜索速度. 二:算法流程 1:建立索引 Ann ...

  8. 4.2.1 路由算法与路由协议概述(静态路由和动态路由---距离-向量路由算法---链路状态路由算法、层次路由)

    文章目录 0.思维导图 1.路由算法分类与路由表 2.静态路由和动态路由 3.动态路由的两种算法:链路状态路由算法和距离向量路由算法 4.层次路由 0.思维导图 1.路由算法分类与路由表 路由器转发分 ...

  9. 索引算法原理解析(B-tree以及磁盘存储原理)

    刚开始学习的时候,百度去查,但发现好多说得太复杂不好理解,结合各个文章总结一下(建议大概看文字,不理解不要紧,然后再看图的执行步骤然后在结合文字,这样一切就清晰好多) B-tree,B是balance ...

最新文章

  1. puppet 类、模块
  2. React中的唯一标识key(用index VS id)和key的选择
  3. 玩转oracle 11g(33):无监听程序
  4. 制作已编译的html帮助文件
  5. vue复选框默认被选中_vue .js绑定checkbox并获取、改变选中状态的实例
  6. 【算法】多路查找树 B树 B+树
  7. 【Clickhouse】mutation 操作
  8. logistic回归分析优点_7种主流数据分析软件比较及经典教材推荐
  9. 微信小程序点击图片放大
  10. vivo直播应用技术实践与探索
  11. 扫地机器人半湿拖布_居然能自己洗拖布?云鲸智能扫拖一体机帮你真正解放双手...
  12. php 高洛峰 正则,PHP 自定义 Smarty 模板引擎类 高洛峰 细说PHP
  13. 1周岁的宝宝营养食谱(3)
  14. vue配置开发、测试、生产环境(proxy中获取process.env.NODE_ENV)
  15. 学习c++的50条忠告(转自C++百度贴吧)
  16. git : 无法将“git”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试 一次。
  17. python模块-CV2
  18. 通用模型、全新框架,WavLM语音预训练模型全解
  19. 爬取各地天气预报,分析哪些地方的人可能中暑
  20. opengl 点精灵的使用

热门文章

  1. Spring Websocket 使用笔记
  2. 多米诺骨牌java_通过递归和回溯找到所有可能的多米诺骨牌链
  3. 银河麒麟操作系统添加新硬盘后流程
  4. 世界最大的数字优惠券​公司
  5. 《FaceBoxes: A CPU Real-time Face Detector with High Accuracy》论文笔记
  6. android stretchpanel控件,TableLayoutPanel 这个控件有没有替代的,而且可以动态Sizable,该如何解决...
  7. 山石岩读丨一文读懂区块链安全:区块链会带来哪些冲击?
  8. 全球与中国网络连接视频门铃对讲机系统市场深度研究分析报告势
  9. fx3u4ad一adp说明书_三菱PLC模块FX3U-4AD与FX3U-4AD-ADP的区别
  10. Excel - VBA的隔行拷贝功能