KD树最近邻搜索如何工作?

时间:2010-12-11 19:14:25

标签: python machine-learning nearest-neighbor kdtree

我正在查看KD树的维基百科页面。作为一个例子,我在python中实现了用于构建列出的kd树的算法。

然而,使用KD树进行KNN搜索的算法切换语言并不完全清楚。英语解释开始有意义,但它的一部分(例如它们“展开递归”以检查其他叶子节点的区域)对我来说并没有任何意义。

这是如何工作的,如何在python中使用KD树进行KNN搜索?这不是一个"send me the code!"类型的问题,我不希望如此。请简单解释一下:)

3 个答案:

答案 0 :(得分:14)

book introduction,第3页:

  

给定d维空间中的一组n个点,构造kd树   递归如下。首先,找到第i个值的中值   点的坐标(最初,i = 1)。也就是说,计算值M,   这样至少50%的点的第i个坐标大于或等于   到M,而至少50%的点的第i个坐标更小   大于或等于M.存储x的值,并对集合P进行分区   进入PL和PR,其中PL仅包含具有第i个坐标的点   小于或等于M,| PR | = | PL |±1。然后重复该过程   递归地在PL和PR上,i替换为i + 1(或1,如果i = d)。   当节点上的点集具有大小为1时,递归停止。

以下段落讨论了它在解决最近邻居时的用法。

或者,这是original 1975 paper by Jon Bentley

编辑:我应该补充一点,SciPy有一个kdtree实现:

答案 1 :(得分:9)

我自己花了一些时间来解释算法的Wikipedia描述,并提出了以下可能有用的Python实现:https://gist.github.com/863301

closest_point的第一阶段是一个简单的深度优先搜索,以找到最匹配的叶节点。

不是简单地返回找到备份调用堆栈的最佳节点,而是在第二阶段检查“离开”端是否有更近的节点:( ASCII art diagram)

            n     current node
 b          |     best match so far
 |      p   |     point we're looking for
 |<    >|   |     error
        |< >|     distance to "away" side
        |<  | >|  error "sphere" extends to "away" side
            | x   possible better match on the "away" side

当前节点n沿着一条线分割空间,因此如果点p和最佳匹配{{1}之间的“错误”,我们只需要查看“离开”侧}}大于距离点bp之间的距离。如果是,那么我们检查“离开”一侧是否有更近的点。

因为我们的最佳匹配节点被传递到第二个测试中,所以它不必对分支进行完全遍历,并且如果它位于错误的轨道上将会很快停止(仅向下朝向“近”子节点,直到它击中一片叶子。)

要计算点n与通过节点p分割空间的线之间的距离,我们可以通过将适当的坐标复制为轴来简单地将点“投影”到轴上都是正交的(水平或垂直)。

答案 2 :(得分:0)

让我们来看一个例子,为简单起见,请考虑d = 2,Kd树的结果如下所示

enter image description here

您的查询点是Q,您想找出k最近的邻居 enter image description here

上面的树代表kd-tree
我们将搜索该树以落入其中一个区域。在kd树中,每个区域都由一个点表示。

然后我们将找出该点与查询点之间的距离

然后,我们将绘制一个半径为该距离的圆,以确保是否存在更靠近查询点的点。

然后落入该圆圈区域的轴,我们回溯到该轴并找到附近的点