在推荐和搜索场景下,召回recall是一个关键的步骤,这个步骤通常需要在海量的目标中,召回部分与用户特征相近的item,所以有一个快速,并且准去的算法是非常有必要的,HNSW(Hierarchical Navigable Small World)就是其中一种方法,当然HNSW也不止用于此。

对于召回的场景下,每个需要进行召回的item已经用户的特征都是多维的,在多个特征维度的空间中,找到与用户特征最相近的topK。所以召回的问题其实可以抽象化为在多维空间中,找到与某个点邻近的topK个点。

HNSW(Hierarchical Navigable Small World)翻译成中文为分级导航小世界,是基于图数据结构的搜索算法,将复杂问题转化成ANN,来解决此类问题。

ANN(Artificial Neural Network)人工神经网络。

NSW(Navigable Small World)

HNSW之前提出的NSW是HNSW的基础,这个算法解决了邻近点搜索的基本问题。

比如我们现在将问题就从多维简化为二维,并且推荐item和用户都的当成一个点的话,那么我们的问题就可以简化为,二维平面中存在海量的点,我们收集到一个用户的特征,就相当于二维空间中给用户找到了他的坐标,那么我们现在要在这些海量的点中找出离用户坐标最近的topK,这就是问召回也就是NSW和HNSW要做的。

构建索引结构

首先,在插入用户特征点之前,我们要做的,就是将所有点与其向邻近的“友点”进行连接。这可以看做是所有item的索引,我们的召回匹配,需要在这个索引上进行。这个索引被称为是Delaunay graph,这种结构的特征就是组成的基本模块都是三角形。

es向量检索 效率 ann向量检索召回_b树


NSW中,实现Delaunay graph的索引的构建:

  • 1.插入一个新点时,会先随机挑选一个节点,然后计算这个节点A和他“友点”到这个新节点的距离,并记录
  • 2.如果距离最短的节点是节点A,那么就可以根据m的数量(可以认为规定的topK)去连接相应的节点,如果友点数量不够,那么先连接节点A,然后将第二近的节点作为下一个节点,去计算距离,重复上面的过程,直到找到m的节点与新节点相连
高速公路

这样的连接其实是有一点小问题的,比如我们两个相距很远的节点A和E,因为插入的比较早,所以就算不是最近的,两点之间也有连线。

我们后面插入了新的节点在AE中间,P和Q,我们可以连接成A-P-C-E,如果没有A-E的话,我们随机点挑选在E,但是我们需要查找的点在A附近的话,我们需要从E-C-P-A要经过三次友点才能到达A,但是因为有AE的连线,我们可以直接从E到A,快速的找到A点附近,接近结果。

所以这个是构建必然会出现的一个情况,也是后续的一个缩短时间的一个工具。

构建索引的优化
  1. 最简单的就是每次遍历的时候,计算了两点间的距离,可以将两点的距离存起来,这样再遍历到这两点的时候就不用重复计算了。
  2. 可以并行的计算多个“友点”对目标点的距离,多线程优化

HNSW(Hierarchical Navigable Small World)

HNSW比NSW多了一个Hierarchical,也就是分级,这个分级我们看HNSW和跳表的结构就知道是个什么分级了

这个是HNSW的结构:

es向量检索 效率 ann向量检索召回_b树_02


这个是跳表 的结构

es向量检索 效率 ann向量检索召回_cs186_03


其实HNSW的优化就是分多层,每层都是下一层的索引层。而越往上层的节点数越少,所以接近目标节点的速度就越快。

所以在召回的时候,我们将一个用户特征的新点加入HNSW的随机一层Li,然后还是从最高层开始搜索每一层与新点的邻近点,然后逐层下降,直到Li层,然后分别连接各层的邻近点。