HNSW算法----Hierarchcal Navigable Small World graphs,第一贡献者:Y.Malkov(俄)
一.背景介绍
在浩渺的数据长河中做高效率相似性查找一直以来都是让人头疼的问题。比如,我在搜狗app上阅读了一篇文章,推荐系统就应当为我推送与这篇文章最相近的文章,数据库中所有文章是用向量表示的,所以我们要解决的问题就是“找到与这篇文章的向量最相近的几个向量”,然后把这些向量对应的文章推送出去。数据库中的文章千千万,所有用户每秒的请求也是千千万,我们需要又快又准又相对节约资源的办法来解决这个问题。
解决这个问题的方法有很多,PQ,Annoy,HNSW等等。篇幅有限,这篇文章只介绍HNSW算法。
二.朴素想法
朴素想法图
请大家把目光投向上面这张图。假设我们现在有13个2维数据向量,我们把这些向量放在了一个平面直角坐标系内,隐去坐标系刻度,它们的位置关系如上图所示。
朴素查找法:不少人脑子里都冒出过这样的朴素想法,把某些点和点之间连上线,构成一个查找图,存下来备用;当我想查找与粉色点最近的一点时,我从任意一个黑色点出发,计算它和粉色点的距离,与这个任意黑色点有连接关系的点我们称之为“友点”(直译),然后我要计算这个黑色点的所有“友点”与粉色点的距离,从所有“友点”中选出与粉色点最近的一个点,把这个点作为下一个进入点,继续按照上面的步骤查找下去。如果当前黑色点对粉色点的距离比所有“友点”都近,终止查找,这个黑色点就是我们要找的离粉色点最近的点。
如果你没看懂上面的文字描述,我们来举个例子。目标:我们要查找与粉色点最近的点。步骤:从任意一个黑色点出发,这里我们随便选个C点吧,计算一下C点和粉色点的距离,存下来备用,再计算C点的所有友点(A,I,B)与粉色点的距离(计算距离和度量的方式有多种,这里我们采用欧氏距离,就是二维物理空间上的“近和远”),我们计算得出B与粉色点的距离最近,而且B点距离粉色点的距离比C点距离粉色点的距离(前面算过)更近,所以我们下面用B点继续查找。B点距离粉色点的距离保存下来,B点的友点是E,A,C,I,H,分别计算它们与粉色点的距离,得到E点与粉色点距离最近,且E点比B点距离粉色点还要近,所以我们选择E点作为下一个查找点。E点的友点是J,B,D,G,这时我们发现J点的与粉色点的距离最近,但是,but,however,J点的距离粉色点的距离比E点还要远,所以满足了终止查找的条件,因此我们返回E点。
朴素想法之所以叫朴素想法就是因为它的缺点非常多。首先,我们发现图中的K点是无法被查询到的,因为K点没有友点,怎么办?。其次,如果我们要查找距离粉色点最近的两个点,而这两个近点之间如果没有连线,那么将大大影响效率(比如L和E点,如果L和E有连线,那么我们可以轻易用上述方法查出距离粉色点最近的两个点),怎么办?