2020-11-09 19:44:40
近邻搜索算法浅析
随着深度学习的发展和普及,非结构数据(如图像、文本等)被表示为高维向量,并通过近邻搜索来查找相似项,满足了人脸识别、图片搜索、商品推荐等多种场景的检索需求。随着数据量的爆发式增长,如何在海量数据中精准高效地完成搜索成为一个研究热点。本文将简要介绍当前比较常见的近邻搜索算法。
一、主要算法概览
当前常见的近邻搜索算法主要包括Kd-Tree、Hierarchical k-means trees、LSH(Locality-Sensitive Hashing)、PQ(Product Quantization)以及HNSW等。这些算法各有特点,适用于不同的场景和数据集。

二、Kd-Tree算法
Kd-Tree是一种基于二叉树结构的近邻搜索算法,适用于k维空间中的数据点。其构建过程包括确定split域的值、Node-data的域值、左右子空间,并递归构造左右子空间。查询过程则包括二叉搜索找到叶子结点、回溯搜索路径进入其他候选节点的子空间查询距离更近的点,直到搜索路径为空。
理想情况下,Kd-Tree的复杂度是O(K log(N)),但在最坏情况下(如查询点的邻域与分割超平面两侧的空间都产生交集时),复杂度会大大增加。特别是当维度比较大时,Kd-Tree的性能会急剧下降,几乎接近线性扫描。因此,对于高维数据,Kd-Tree的适用性受到限制。
为了改进Kd-Tree的性能,提出了Best-Bin-First和Randomized Kd tree等算法。Best-Bin-First通过设置优先级档启队列和运行超时限定来获取近似的最近邻,有效地减少回溯的次数。Randomized Kd tree则通过构建多个不同方向上的Kd tree,在各个Kd tree上并行搜索部分数量的节点来提升搜索性能。
三、Hierarchical k-means trees算法
Hierarchical k-means trees通过聚类的方法来建立一个二叉树,使得每个点的查找时间复杂度是O(log n)。其构建过程包括随机选择两个点执行k为2的聚类、在划分的子空间内进行递归迭代继续划分直到每个子空间最多仿笑只剩下K个数据节点、最终形成一个二叉树结构。搜索过程则从根节点开始比较找到叶子节点,同时将路径上的节点记录到优先级队列中,执行回溯并从优先级队列中选取节点重新执行查找,直到遍历节点的数目达到指定阈值时终止搜索。
Hierarchical k-means trees的搜索性能不是特别稳定,在某些数据集上表现很好,在有些数据集上则有些差。此外,构建树的时间比较长,可以通过设置kmeans的迭代次数来优化。
四、LSH算法
LSH是一种基于哈希的近邻搜索算法。其基本原理是:如果高维空间中的两点距离很近,那么它们的哈希值有很大概率是一样的;如果两点之间的距离较远,那么它们的哈希值相同的概率会很小。LSH算法会根据具体的需求来选择满足条件的hash函数,并通过构建哈希表来完成索引的建立。在线查找时,将查询向量通过哈希函数映射到哈希表中,取出相应的向量进行线性查找,返回与查询向量最相似的向量。
LSH算法的查询耗时主要包括计算查询向量的hash值和计算查询向量与哈希表中点的距离。由于损失了大量原始信息,LSH算法的检索精度会降低。
五、PQ算法
PQ算法是一种基于量化的近邻搜索算法。它将原来的向量空间分解为若干个低维向量空间的笛卡尔积,并对分解得到的低维向量空间分别做量化。这样,每个向量就能由多个低维空间的量化code组合表示。PQ算法通常使用k-means算法进行量化。
在查询过程中,将搜索query划分子向量,计算子向量和对应段的所有簇心的距离,得到距离表。然后遍历样本库中的向量,根据距离表计算每个样本与查询向量的距离,并返回k个距离最接近的样本。
PQ算法的距离计算方法包括SDC(对称的距离行大如计算方法)和ADC(非对称的距离计算方案)。SDC方法会对query向量和样本库中的向量都进行PQ量化,通过查表减少计算过程但放大了误差。ADC方法则只对样本库中的向量进行PQ量化,每次对查询向量实时计算,增加计算开销但误差小。
为了进一步优化PQ算法的性能,提出了IVFPQ算法。IVFPQ算法在PQ算法的基础上增加了粗量化阶段,对样本进行聚类划分为较小的region,减少候选集数据量。
六、HNSW算法
HNSW是一种基于图的近邻搜索算法。它在NSW算法的基础上进行改进,使用分层的结构,并在每层通过启发式方法来选择某节点的邻居以保证全局连通性。HNSW算法通过构建一张连通的图来加速近邻搜索的过程。
HNSW算法的建图流程包括计算节点的最大层次、随机选择初始入口点、在当前层找到距离待插节点最近的节点作为下一层的输入、在待插层找到距离待插元素最近的ef个节点并从中选出M个与待插节点连接等步骤。查询流程则从顶层到倒数第二层循环执行在当前层寻找距离查询节点最近的一个节点放入候选集中等操作,并从候选集中选取出topk。
HNSW算法具有高效、准确的特点,适用于大规模数据集上的近邻搜索任务。
七、实现与优化
当前有比较成熟的库实现了各种主流的近邻搜索算法。其中,faiss库由Facebook开源,支持不同算法的同时还支持在超大规模数据集上构建k近邻搜索以及支持GPU来加速索引构建和查询。faiss库社区活跃,是构建近邻检索服务的比较好的选择。
在优化方面,可以结合业务需求和数据特点选择合适的算法和参数配置。例如,对于高维数据可以选择HNSW等适用于高维数据的算法;对于大规模数据集可以选择支持分布式计算和GPU加速的算法和库等。
八、总结
本文展示了当前比较常见的几种近邻搜索算法,并简要分析了各算法的原理和特点。随着深度学习的不断发展,不同场景对近邻搜索的需求越来越多,必定会有新的算法不断涌现。在选择不同算法时需要结合业务需求、数据量大小、召回效果、性能以及资源消耗等各方面的因素进行综合考虑。通过了解不同算法的实现原理和特点,可以选择更适合当前业务的算法来构建近邻检索服务。