来自于https://zhuanlan.zhihu.com/p/23966698

构造 kd 树的例子

上面抽象的定义和算法确实是很不好理解,举一个例子会清楚很多。首先随机在 中随机生成 13 个点作为我们的数据集。起始的切分轴;这里 对应 xx 轴,而 对应 y 轴。

首先先沿 x 坐标进行切分,我们选出 x 坐标的中位点,获取最根部节点的坐标

并且按照该点的x坐标将空间进行切分,所有 x 坐标小于 6.27 的数据用于构建左枝,x坐标大于 6.27 的点用于构建右枝。

在下一步中 对应 y 轴,左右两边再按照 y 轴的排序进行切分,中位点记载于左右枝的节点。得到下面的树,左边的 x 是指这该层的节点都是沿 x 轴进行分割的。

空间的切分如下

下一步中 r≡1+1≡0 mod 2,对应 x 轴,所以下面再按照 x 坐标进行排序和切分,有

最后每一部分都只剩一个点,将他们记在最底部的节点中。因为不再有未被记录的点,所以不再进行切分。

就此完成了 kd 树的构造。

kd 树上的 kNN 算法

给定一个构建于一个样本集的 kd 树,下面的算法可以寻找距离某个点 p 最近的 k 个样本。

零、设 L 为一个有 k 个空位的列表,用于保存已搜寻到的最近点。
一、根据 p 的坐标值和每个节点的切分向下搜索(也就是说,如果树的节点是照 进行切分,并且 p 的 r 坐标小于 a,则向左枝进行搜索;反之则走右枝)。
二、当达到一个底部节点时,将其标记为访问过。如果 L 里不足 k 个点,则将当前节点的特征坐标加入 L ;如果 L 不为空并且当前节点的特征与 p 的距离小于 L 里最长的距离,则用当前特征替换掉 L 中离 p 最远的点。
三、如果当前节点不是整棵树最顶端节点,执行 (a);反之,输出 L,算法完成。
a. 向上爬一个节点。如果当前(向上爬之后的)节点未曾被访问过,将其标记为被访问过,然后执行 (1) 和 (2);如果当前节点被访问过,再次执行 (a)。
1. 如果此时 L 里不足 kk 个点,则将节点特征加入 L;如果 L 中已满 k 个点,且当前节点与 p 的距离小于 L 里最长的距离,则用节点特征替换掉 L 中离最远的点。
2.
计算 p 和当前节点切分线的距离。如果该距离大于等于 L 中距离 p 最远的距离并且 L 中已有 k
个点,则在切分线另一边不会有更近的点,执行 (三);如果该距离小于 L 中最远的距离或者 L 中不足 k
个点,则切分线另一边可能有更近的点,因此在当前节点的另一个枝从 (一) 开始执行。

啊呃… 被这算法噎住了,赶紧喝一口下面的例子

设我们想查询的点为 p=(−1,−5),设距离函数是普通的 距离,我们想找距离问题点最近的 k=3 个点。如下:

首先执行 (一),我们按照切分找到最底部节点。首先,我们在顶部开始

和这个节点的 x 轴比较一下,
p 的 x 轴更小。因此我们向左枝进行搜索:
这次对比 y 轴,

p 的 y 值更小,因此向左枝进行搜索:

这个节点只有一个子枝,就不需要对比了。由此找到了最底部的节点 (−4.6,−10.55)。
在二维图上是

此时我们执行 (二)。将当前结点标记为访问过,并记录下 L=[(−4.6,−10.55)]。啊,访问过的节点就在二叉树上显示为被划掉的好了。

然后执行 (三),嗯,不是最顶端节点。好,执行 (a),我爬。上面的是 (−6.88,−5.4)。

执行
(1),因为我们记录下的点只有一个,小于 k=3,所以也将当前节点记录下,有
L=[(−4.6,−10.55),(−6.88,−5.4)].再执行 (2),因为当前节点的左枝是空的,所以直接跳过,回到步骤 (三)。(三)
看了一眼,好,不是顶部,交给你了,(a)。于是乎 (a) 又往上爬了一节。

(1) 说,由于还是不够三个点,于是将当前点也记录下,有 L=[(−4.6,−10.55),(−6.88,−5.4),(1.24,−2.86)]。当然,当前结点变为被访问过的。

(2) 又发现,当前节点有其他的分枝,并且经计算得出 p 点和 L 中的三个点的距离分别是 6.62,5.89,3.10,但是 p 和当前节点的分割线的距离只有 2.14,小于与 L 的最大距离:

因此,在分割线的另一端可能有更近的点。于是我们在当前结点的另一个分枝从头执行 (一)。好,我们在红线这里:

要用 p 和这个节点比较 x 坐标:

p 的 x 坐标更大,因此探索右枝 (1.75,12.26),并且发现右枝已经是最底部节点,因此启动 (二)。
经计算,(1.75,12.26) 与 p 的距离是 17.48,要大于 p 与 L 的距离,因此我们不将其放入记录中。

然后 (三) 判断出不是顶端节点,呼出 (a),爬。

(1) 出来一算,这个节点与 p 的距离是 4.91,要小于 p 与 L 的最大距离 6.62。

因此,我们用这个新的节点替代 L 中离 p 最远的 (−4.6,−10.55)。

然后 (2) 又来了,我们比对 p 和当前节点的分割线的距离

这个距离小于 L 与 p 的最小距离,因此我们要到当前节点的另一个枝执行 (一)。当然,那个枝只有一个点,直接到 (二)。

计算距离发现这个点离 p 比 L 更远,因此不进行替代。

(三) 发现不是顶点,所以呼出 (a)。我们向上爬,

这个是已经访问过的了,所以再来(a),

好,(a)再爬,

啊!到顶点了。所以完了吗?当然不,还没轮到 (三) 呢。现在是 (1) 的回合。

我们进行计算比对发现顶端节点与p的距离比L还要更远,因此不进行更新。

然后是 (2),计算 p 和分割线的距离发现也是更远。

因此也不需要检查另一个分枝。

然后执行 (三),判断当前节点是顶点,因此计算完成!输出距离 p 最近的三个样本是 L=[(−6.88,−5.4),(1.24,−2.86),(−2.96,−2.5)]。

结语

kd
树的 kNN
算法节约了很大的计算量(虽然这点在少量数据上很难体现),但在理解上偏于复杂,希望本篇中的实例可以让读者清晰地理解这个算法。喜欢动手的读者可以尝试自己用代码实现
kd 树算法,但也可以用现成的机器学习包 scikit-learn 来进行计算。量化课堂的下一篇文章就将讲解如何用 scikit-learn 进行 kNN 分类。

KD-树(下)的更多相关文章

  1. 利用KD树进行异常检测

    软件安全课程的一次实验,整理之后发出来共享. 什么是KD树 要说KD树,我们得先说一下什么是KNN算法. KNN是k-NearestNeighbor的简称,原理很简单:当你有一堆已经标注好的数据时,你 ...

  2. 2016 ICPC青岛站---k题 Finding Hotels(K-D树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...

  3. PCL点云库:Kd树

    Kd树按空间划分生成叶子节点,各个叶子节点里存放点数据,其可以按半径搜索或邻区搜索.PCL中的Kd tree的基础数据结构使用了FLANN以便可以快速的进行邻区搜索.FLANN is a librar ...

  4. KNN算法与Kd树

    最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知 ...

  5. k临近法的实现:kd树

    # coding:utf-8 import numpy as np import matplotlib.pyplot as plt T = [[2, 3], [5, 4], [9, 6], [4, 7 ...

  6. 从K近邻算法谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/v_july_v/article/details/8203674 ,感谢july的辛勤劳动 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章 ...

  7. bzoj 3489: A simple rmq problem k-d树思想大暴力

    3489: A simple rmq problem Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 551  Solved: 170[Submit][ ...

  8. k近邻法的C++实现:kd树

    1.k近邻算法的思想 给定一个训练集,对于新的输入实例,在训练集中找到与该实例最近的k个实例,这k个实例中的多数属于某个类,就把该输入实例分为这个类. 因为要找到最近的k个实例,所以计算输入实例与训练 ...

  9. kd树的构建以及搜索

    构建算法 k-d树是一个二叉树,每个节点表示一个空间范围.表1给出的是k-d树每个节点中主要包含的数据结构. 表1 k-d树中每个节点的数据类型 域名 数据类型 描述 Node-data 数据矢量 数 ...

  10. KD树小结

    很久之前我就想过怎么快速在二维平面上查找一个区域的信息,思考许久无果,只能想到几种优秀一点的暴力. Kd树就是干上面那件事的. 别的不多说,赶紧把自己的理解写下来,免得凉了. KD树的组成 以维护k维 ...

随机推荐

  1. springboot+mockito 异常解决方案

    系统启动的异常日志如下 javax.net.ssl.* java.lang.IllegalStateException: Failed to load ApplicationContext at or ...

  2. mmap映射区和shm共享内存的区别总结

    [转载]原文链接:https://blog.csdn.net/hj605635529/article/details/73163513 linux中的两种共享内存.一种是我们的IPC通信System ...

  3. html5 + vue

    偶然与巧合 舞动了蝶翼 谁的心头风起 前赴而后继 万千人追寻 荒漠唯一菩提 似擦肩相遇 或擦肩而去 命运犹如险棋 无数时间线 无数可能性 终于交织向你

  4. (转)SQLServer查询数据库各种历史记录

    原文地址https://www.cnblogs.com/seusoftware/p/4826958.html 在SQL Server数据库中,从登陆开始,然后做了什么操作,以及数据库里发生了什么,大多 ...

  5. @Bean 的用法

    @Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里.添加的bean的id为方法名 定义bean 下面是@Configuratio ...

  6. PyCharm下的pywin32安装及使用

    转载http://www.mamicode.com/info-detail-2145088.html

  7. Error creating bean with name 'transactionManager'

    查看数据库是否连通,看错误的具体信息 看ssm配置文件是否被正确加载,上次我的错误是beans之类的错误,就是spring文件没有被加载,因为 而文件是applicationConfig.xml

  8. python excel 像 Excel 一样使用 python 进行数据分析

    https://www.jb51.net/article/63216.htm 像 Excel 一样使用 python 进行数据分析 :  https://www.cnblogs.com/nxld/p/ ...

  9. tomcat 部署swagger 请求到后端乱码

    问题: @ApiOperation(value = "", notes = "查看关键词列表") @ResponseBody @RequestMapping(v ...

  10. leetcode448

    public class Solution { public IList<int> FindDisappearedNumbers(int[] nums) { Dictionary<i ...