一、KNN算法

KNN(K-NearestNeighbor)算法既可以用于分类,也可用于回归。这里介绍他的分类用法。

训练集:一堆拥有标签的m维数据,可以表示为:

其中  是标签,即所属类别。

目标:一个测试数据x,预测其所属类别。

算法:

  1. 计算测试点x与训练集中每一个数据的“距离”
  2. 将所求的距离进行升序排序,选择前K个
  3. 在上一步中所得到的K个数据中,根据决策规则(如多数表决)决定x的类别预测结果

虽然KNN算法用短短的三步就能概括,但是大有文章可做

1、“距离”是啥距离?

话不多说,先摆个公式压压惊

上式表示的是:m维数据的距离就是这么求的。

当p=2时,这个距离就称为欧式距离,是不是很熟悉?

当p=1时,称为曼哈顿距离

根据数据特性的不同,我们可以选择不同的距离来度量。

2、K值如何选择

我们一直在谈KNN,那这个K我们该如何选择呢?

K值太小,预测结果会对近邻的训练数据十分敏感,模型过于复杂,易发生过拟合

K值太大,会导致分类结果模糊,模型过于简单。

对于k值的选择有这么几种方法:交叉验证、贝叶斯方法、bootstrap。

一般是取个较小值,采用交叉验证法来选取最优的K值。

3、决策规则是啥?

一般是选用多数表决规则,即在K个数据中,哪种类别出现的次数最多,这个类别就是x的预测类别。

二、kd树

以上说完,我们就要进入实现环节了。那么问题来了,我们上面说的是计算测试点和训练集中的每一个数据的距离,然后进行排序。数据量少的时候完全问题,可是当数据量大的时候,臣妾做不到啊!!!

这时候,我们聪明的前辈就提出了kd树(k-dimensional tree)。这是一颗什么样的树呢?

kd树可以帮助我们在很快地找到与测试点最邻近的K个训练点。不再需要计算测试点和训练集中的每一个数据的距离。

kd树是二叉树的一种,是对k维空间的一种分割,不断地用垂直于坐标轴的超平面将k维空间切分,形成k维超矩形区域,kd树的每一个结点对应于一个k维超矩形区域。

注意:这里的k维的k表示的是数据的维度,上文中我们称为m维数据。(不要理解为K个训练点的K,你看我甚至把训练点的K大写,维度的k小写

kd树的构造

首先我们需要构造kd数,构造方法如下:

  1. 选取为坐标轴,以训练集中的所有数据坐标中的中位数作为切分点,将超矩形区域切割成两个子区域。将该切分点作为根结点,由根结点生出深度为1的左右子结点,左节点对应坐标小于切分点,右结点对应坐标大于切分点
  2. 对深度为j的结点,选择为切分坐标轴,,以该结点区域中训练数据坐标的中位数作为切分点,将区域分为两个子区域,且生成深度为j+1的左、右子结点。左节点对应坐标小于切分点,右结点对应坐标大于切分点
  3. 重复2,直到两个子区域没有数据时停止。

是不是现在还是懵懵懂懂的,甚至上面的构造方法只是一眼扫过。

不慌,有句话叫无图言X,接下来就是关门放图的时候。

我们用图像来走算法!

我们有二维数据集

将他们在坐标系中表示如下:

开始:选择为坐标轴,中位数为6,即(6,5)为切分点,切分整个区域

          

再次划分区域

为坐标轴,选择中位数,可知左边区域为-3,右边区域为-12。所以左边区域切分点为(1,-3),右边区域切分点坐标为(17,-12)

再次对区域进行切分,同上步,我们可以得到切分点,切分结果如下:

最后分割的小区域内只剩下一个点或者没有点。我们得到最终的kd树如下图

kd树完成K近邻的搜索

当我们完成了kd树的构造之后,我们就要想怎么利用kd树完成K近邻的搜索呢???

接下来,又是抛出算法的时候了

为了方便说明,我们采用二维数据的栗子。假设现在要寻找p点的K个近邻点(p点坐标为(a,b)),也就是离p点最近的K个点。设S是存放这K个点的一个容器。

新鲜的算法来了:

  1. 根据p的坐标和kd树的结点向下进行搜索(如果树的结点是以来切分的,那么如果p的坐标小于c,则走左子结点,否则走右子结点)
  2. 到达叶子结点时,将其标记为已访问。如果S中不足k个点,则将该结点加入到S中;如果S不空且当前结点与p点的距离小于S中最长的距离,则用当前结点替换S中离p最远的点
  3. 如果当前结点不是根节点,执行(a);否则,结束算法

(a)回退到当前结点的父结点,此时的结点为当前结点(回退之后的结点)。将当前结点标记为已访问,执行(b)和(c);如果当前结点已经被访过,再次执行(a)。

(b)如果此时S中不足k个点,则将当前结点加入到S中;如果S中已有k个点,且当前结点与p点的距离小于S中最长距离,则用当前结点替换S中距离最远的点。

(c)计算p点和当前结点切分线的距离。如果该距离大于等于S中距离p最远的距离并且S中已有k个点,执行3;如果该距离小于S中最远的距离或S中没有k个点,从当前结点的另一子节点开始执行1;如果当前结点没有另一子结点,执行3。

以上的1,2,3我们会称为算法中的1,算法中的2,算法中的3

老规矩,上图!

为了方便描述,我对结点进行了命名,如下图。

蓝色斜线表示该结点标记为已访问,红色下划线表示在此步确定的下一要访问的结点

我们现在就计算p(-1,-5)的3个邻近点。

我们拿着(-1,-5)寻找kd树的叶子结点。

执行算法中的1。

  • p点的-1与结点A的x轴坐标6比较,-1<6,向左走。
  • p点的-5与结点B的y轴坐标-3比较,较小,往左走。
  • 因为结点C只有一个子结点,所以不需要进行比较,直接走到结点H。

进行算法中的2,标记结点H已访问,将结点H加入到S中。

此时                                                                          

执行算法中的3,当前结点H不是根结点

  • 执行(a),回退到父结点C,我们将结点C标记为已访问
  • 执行(b),S中不足3个点,将结点C加入到S中
  • 执行(c)计算p点和结点C切分线的距离,可是结点C没有另一个分支,我们开始执行算法中的3。

当前结点C不是根结点

  • 执行(a),回退到父结点B,我们将结点B标记为已访问
  • 执行(b),S中不足3个点,将结点B加入到S中
  • 执行(c)计算p点和结点B切分线的距离,两者距离为小于S中的最大距离。(S中的三个点与p的距离分别为)。所以我们需要从结点B的另一子节点D开始算法中的1。

从结点D开始算法中的1

  • p点的-1与结点D的x轴坐标-2比较,-1 >  -2,向右走。
  • 找到了叶子结点J,标记为已访问。

开始算法中的2

  • S不空,计算当前结点J与p点的距离,为18.2,大于S中的最长距离
  • 所以我们不将结点J放入S中

执行算法中的3,当前结点J不为根结点

  • 执行(a),回退到父结点D,标记为已访问。
  • 执行(b),S中已经有3个点,当前结点D与p点距离为,小于S中的最长距离(结点H与p点的距离),将结点D替换结点H。
  • 执行(c),计算p点和结点D切分线的距离,两者距离为1,小于S中最长距离,所以我们需要从结点D的另一子节点I开始算法中的1。

从结点I开始算法中的1,结点I已经是叶子结点

直接进行到算法中的2

  • 标记结点I为已访问
  • 计算当前结点I和p点的距离为,大于S中最长距离,不进行替换。

执行算法中的3.

当前结点I不是根结点

  • 执行(a),回退到父结点D,但当前结点D已经被访问过。
  • 再次执行(a),回退到结点D的父结点B,也标记为访问过
  • 再次执行(a),回退到结点B的父结点A,结点A未被访问过,标记为已访问。
  • 执行(b),结点A和p点的距离为,大于S中的最长距离,不进行替换
  • 执行(c),p点和结点A切分线的距离为7,大于S中的最长距离,不进行替换

执行算法中的3,发现当前结点A是根结点,结束算法。

得到p点的3个邻近点,为(-6,-5)、(1,-3)、(-2,-1)

kd树就这么的完成了他的任务。

总的来说,就是以下几步

1、找到叶子结点,看能不能加入到S中

2、回退到父结点,看父结点能不能加入到S中

3、看目标点和回退到的父结点切分线的距离,判断另一子结点能不能加入到S中

有错误之处还请大家帮忙指正!

参考:

https://cloud.tencent.com/developer/news/212042

https://zhuanlan.zhihu.com/p/23966698

KNN算法和kd树详解(例子+图示)相关推荐

  1. K近邻算法和KD树详细介绍及其原理详解

    相关文章 K近邻算法和KD树详细介绍及其原理详解 朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解 决策树算法和CART决策树算法详细介绍及其原理详解 线性回归算法和逻辑斯谛回归算法详细介绍及其原理详 ...

  2. 机器学习算法(二十五):KD树详解及KD树最近邻算法

    目录 1 KD树 1.1 什么是KD树 1.2 KD树的构建 1.3 KD树的插入 1.4 KD树的删除 1.5 KD树的最近邻搜索算法 1.5.1 举例:查询点(2.1,3.1) 1.5.2 举例: ...

  3. 最清晰易懂的MinMax算法和Alpha-Beta剪枝详解

    最清晰易懂的MinMax算法和Alpha-Beta剪枝详解 参考文章 http://web.cs.ucla.edu/~rosen/161/notes/alphabeta.html https://ww ...

  4. open3d中的kd树详解

    文章目录 open3d实现 原理 k-d树是一种点云划分方法,其基本思路是,对方差最差的维度进行二分分割,从而得到两个子集,再对这两个子集进行相同的操作,直到所有子集的元素个数低于设定值. 考虑到大部 ...

  5. KD树详解及KD树最近邻算法

    参考:http://blog.csdn.net/app_12062011/article/details/51986805 http://www.cnblogs.com/snake-hand/arch ...

  6. A算法和A*算法详解

    字太多了 直接放笔记的图片吧,如有不对请指正 A算法和A*算法都适用 1.用初始节点初始化搜索图G (动态变化),将初始节点放入open表(还没有扩展的节点)中,然后初试closed(已经扩展完成的节 ...

  7. Dijkstra算法和Floyd算法详解(MATLAB代码)

    一.Dijkstra算法 1.算法简介 Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法.算法解决的是有 ...

  8. 最小生成树———prim算法和kruskal算法详解

    最小生成树之prim算法(转载出处) 边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用: ...

  9. 多目标跟踪算法中之图匹配——匈牙利算法和KM算法详解

    目录 一.匈牙利算法 1.算法背景及思想 2.最大匹配 3.最优匹配/完美匹配 4.增广路径 5.代码实现 6.匈牙利算法总结 6.1.深度优先 6.2. 广度优先 二.KM算法思想及局限性 代码示例 ...

  10. KNN算法与Kd树(转载+代码详细解释)

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

最新文章

  1. ​从800个GPU训练几十天到单个GPU几小时,看神经架构搜索如何进化
  2. LeetCode 289. Game of Life--Java,Python解法
  3. python nltk lemmatizer_Python聊天机器人–使用NLTK和Keras构建第一个聊天机器人
  4. 天猫首页迷思之-jquery实现左侧广告牌图片轮播
  5. Redis 实践笔记1---基础知识
  6. VIO-slam 系统构建
  7. Linux监控服务并主动重启
  8. [BZOJ1877][SDOI2009]SuperGCD
  9. mysql盲注ascii中文_[翻译]关于通过对8bit的ascii做右位移提高mysql盲注效率
  10. 微信分享ios 不显示图片和简介问题总结
  11. 各个排序算法(^_^)
  12. 子目录和子域名哪个好?子目录和子域名如何利用seo优化?
  13. C语言学习笔记---字符处理函数getc()和getchar()函数
  14. 群控进化史,黑产攻击效率提升带来的防守困境
  15. 【转】怎样评价寒武纪的芯片1P 1M和MLU100?能够叫板英伟达吗?
  16. Linux htop命令
  17. ios8在通用设置中文键盘无效的解决方法(中文键盘设置)
  18. conda环境opencv报错cv2.error:
  19. 硬件描述语言实验五:四位加法器实验
  20. 基于蓝牙模块ROK101 007/1的小区监控系统设计

热门文章

  1. 图书销售系统可行性分析报告
  2. kudu之tablet设计原理
  3. 东芝服务器报错误代码维修,东芝复印机维修故障代码
  4. 文件保险柜 v2.6 官网
  5. 这样的文件操作有点玄——文件流学习 ( 二 )
  6. SAP 工单报工批次确定自动带出批次并拆分
  7. leapftp怎么上传,小编教你leapftp怎么上传文件
  8. 理性看待SDN(软件定义网络)
  9. android基于xposed框架,基于Xposed框架的模块:Android EagleEye
  10. 太空工程师-脚本-库存整理