kNN(k-Nearest Neighbours)原理详解

  • 1 kNN简介
  • 2 图解kNN基本原理
    • 1)k近邻算法中k的选取
    • 2)距离函数
    • 3)归一化处理
    • 4)概率kNN
  • 3 kNN算法总结

1 kNN简介

  kNN(k- Nearest Neighbor)法即k最邻近法,最初由 Cover和Hart于1968年提出,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一,它的适用面很广,并且在样本量足够大的情况下准确度很高,多年来得到了很多的关注和研究。
  它的工作原理是:存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

2 图解kNN基本原理

  假设有三种兔子,第一种兔子叫作绿兔(Green),它们的平均身高是 50厘米,平均体重 5公斤。选取100个样本,分别测量它们的身高和体重,画在坐标图上,用绿色方块表示。

  第二种兔子叫蓝兔(blue),它们体型比较小,平均身高是 30厘米,平均体重是 4公斤。同样,选取100个样本,分别测量它们的身高和体重,并将它们画在同一个坐标图上,用蓝色三角表示。

  最后一种兔子叫黄兔(yellow),它们的平均身高45厘米,但体重较轻,平均只有2.5公斤。100只黄兔的数据用黄色圆圈表示。

  在这些数据中,(身高,体重)的二元组叫做特征(features),兔子的品种则是分类标签(class label)。我们想解决的问题是,给定一个未知分类的新样本的所有特征,通过已知数据来判断它的类别。

  现在假设有一只兔子R,想要确定它属于绿兔、蓝兔和黄兔中的哪一类,应该怎么做呢?按照最普通的直觉,应该在已知数据里找出几个和我们想探究的兔子最相似的几个点,然后看看那些兔子都是什么个情况;如果它们当中大多数都属于某一类别,那么兔子R大概率也就是那个类别了。

  为了确定兔子R属于哪一类,首先测量出其身长为 40 厘米,体重 2.7 公斤,为了直观展示,将其画在上述同一坐标系中,用红色五角星表示。

  现在预设一个整数k,寻找距离兔子R最近的k个数据样本进行分析。kNN 算法如何对这次观测进行分类要取决于k的大小。直觉告诉我们兔子R像是一只黄兔,因为除了最近的蓝色三角外,附近其他都是黄色圆圈。的确,如果设 k = 15,算法会判断这只兔子是一只黄兔。但是如果设 k = 1,那么由于距离最近的是蓝色三角,会判断兔子R是一只蓝兔。

  如果按照15NN和1NN的方法对这个二维空间上的每一个点进行分类,会形成以下的分割:

  在两组分类中,1NN 的分类边界明显更“崎岖”,但是对历史样本没有误判;而 15NN 的分类边界更平滑,但是对历史样本有发生误判的现象。选择k的大小取决于对偏差和方差之间的权衡。

1)k近邻算法中k的选取

  如果我们选取较小的k值,那么就会意味着我们的整体模型会变得复杂,容易发生过拟合!假设我们选取k=1这个极端情况,并且有训练数据和待分类点如下图:

  上图中有俩类,一个是黑色的圆点,一个是蓝色的长方形,现在我们的待分类点是红色的五边形。根据我们的k近邻算法步骤来决定待分类点应该归为哪一类。我们由图中可以得到,五边形离黑色的圆点最近,k又等于1,因此,我们最终判定待分类点是黑色的圆点。

  由这个处理过程我们很容易能够感觉出问题了,如果k太小了,比如等于1,那么模型就太复杂了,我们很容易学习到噪声,也就非常容易判定为噪声类别,而在上图,如果,k大一点,k等于8,把长方形都包括进来,我们很容易得到我们正确的分类应该是蓝色的长方形!如下图:

  所谓的过拟合就是在训练集上准确率非常高,而在测试集上准确率低,经过上例,我们可以得到k太小会导致过拟合,很容易将一些噪声(如上图离五边形很近的黑色圆点)学习到模型中,而忽略了数据真实的分布!

  如果我们选取较大的k值,就相当于用较大邻域中的训练数据进行预测,这时与输入实例较远的(不相似)训练实例也会对预测起作用,使预测发生错误,k值的增大意味着整体模型变得简单。

  我们想,如果k=N(N为训练样本的个数),那么无论输入实例是什么,都将简单地预测它属于在训练实例中最多的类。这时,模型是不是非常简单,这相当于你压根就没有训练模型呀!直接拿训练数据统计了一下各个数据的类别,找最大的而已!这好像下图所示:

  我们统计了黑色圆形是8个,长方形个数是7个,那么,如果k=N,我就得出结论了,红色五边形是属于黑色圆形的。这个时候,模型过于简单,完全忽略训练数据实例中的大量有用信息,是不可取的。

  综上分析,k值既不能过大,也不能过小,在我举的这个例子中,我们k值的选择,在下图红色圆边界之间这个范围是最好的,如下图:
  注:这里只是为了更好让大家理解,真实例子中不可能只有两维特征,但是原理是一样的,我们就是想找到较好的k值大小。那么我们一般怎么选取呢?常用的方法是从k=1开始,使用检验集估计分类器的误差率。重复该过程,每次K增值1,允许增加一个近邻。选取产生最小误差率的K。一般k的取值不超过20,上限是 nnn的开方,随着数据集的增大,K的值也要增大。(李航博士书上讲到,我们一般选取一个较小的数值,通常采取交叉验证法来选取最优的k值。也就是说,选取k值很重要的关键是实验调参,类似于神经网络选取多少层这种,通过调整超参数来得到一个较好的结果)。

2)距离函数

  我们在上面的例子中把一个很重要的概念隐藏了起来,选择一个数量k 还只是小问题,更重要的是距离的计算方法。毕竟,当我们说“最近的k个点”时,这个“近”是怎么衡量的?

  在数学中,一个空间上距离的严格定义如下:
  设 MMM为一个空间,MMM上的一个距离函数d:M×M→Rd : M × M → \mathbb{R}d:M×M→R,满足:
  ∙∙∙ d(x,y)≥0d(x,y)≥0d(x,y)≥0  ∀x,y∈M∀x,y∈M∀x,y∈M
  ∙∙∙ d(x,y)=0⟺x=yd(x,y)=0 ⟺ x=yd(x,y)=0⟺x=y
  ∙∙∙ d(x,y)=d(y,x)∀x,y∈Md(x,y)=d(y,x)  ∀x,y∈Md(x,y)=d(y,x) ∀x,y∈M
  ∙∙∙ d(x,z)≤d(x,y)+d(y,z)∀x,y,z∈Md(x,z)≤d(x,y)+d(y,z)  ∀x,y,z∈Md(x,z)≤d(x,y)+d(y,z) ∀x,y,z∈M
  两个点x,yx,yx,y 之间的距离就是 d(x,y)d(x,y)d(x,y)。
  我们一般最常用的距离函数是欧氏距离,也称作L2L_{2}L2​距离。如果x=(x1,x2,…,xn)x=(x_{1},x_{2},…,x_{n})x=(x1​,x2​,…,xn​)和y=(y1,y2,…,yn)y=(y_{1},y_{2},…,y_{n})y=(y1​,y2​,…,yn​)是nnn维欧式空间Rn\mathbb{R}^{n}Rn上的两个点,那它们之间的L2L_{2}L2​距离是:
d2(x,y)=∑i=1n(xi−yi)2(1)d_{2}(x,y)=\sqrt{\sum_{i=1}^{n}(x_{i}-y_{i})^{2}} \tag{1} d2​(x,y)=i=1∑n​(xi​−yi​)2​(1)
  L2L_{2}L2​是更普遍的LpL_{p}Lp​距离在 p=2p = 2p=2 时的特例。LpL_{p}Lp​距离的函数dpd_{p}dp​定义如下:对于1≤p<∞1\leq p< \infty1≤p<∞,有:
dp(x,y)=(∑i=1n∣xi−yi∣p)1p(2)d_{p}(x,y)=\left(\sum_{i=1}^{n}|x_{i}-y_{i}|^{p}\right)^{\frac{1}{p}} \tag{2} dp​(x,y)=(i=1∑n​∣xi​−yi​∣p)p1​(2)
  还有L∞L_{\infty }L∞​距离:
d∞(x,y)=maxi=1,2...,n∣xi−yi∣(3)d_{\infty }(x,y)=\underset{i=1,2...,n}{max}|x_{i}-y_{i}| \tag{3} d∞​(x,y)=i=1,2...,nmax​∣xi​−yi​∣(3)
  在实际应用中,距离函数的选择应该根据数据的特性和分析的需要而定,本篇就不进行更深入的探讨,一般情况下使用最常用的 L2L_{2}L2​函数即可。

3)归一化处理

  【注意】使用 kNN 时需要根据特征数据的取值区间来调整坐标轴的比例,这个做法叫作标准化或者归一化。为什么要这么做呢?拿上面的例子来说,一只兔子的身长(cm)数值平均是它的体重(kg)的 10倍左右,如果我们在这组数值上直接使用L2L_{2}L2​距离函数的话就会导致横轴的距离比重明显放大,分类结果也不合理,如下图所示:


  如果把坐标轴成其他的单位,比如毫米和吨,并用相应的新数值来计算距离,又会得到完全不同的分类标准。甚至,在极端情况下,如果身高用纳米并且体重用吨计量,那么相比之下身高的数值会奇高无比,以至于两点之间的距离是完全由身高决定的,体重则没有任何权重。为了解决这个问题,我们应该在计算距离时把所有坐标轴进行归一化。
  在之前的例子中,由于横轴数值大约是竖轴的 10 倍左右,所以我们将横轴(身高)的数值压缩 10倍,即计算距离时使用:
d((x1,x2),(y1,y2))=(x110−y110)2+(x2−y2)2(4)d((x_{1},x_{2}),(y_{1},y_{2}))=\sqrt{(\frac{x_{1}}{10}-\frac{y_{1}}{10})^{2}+(x_{2}-y_{2})^{2}} \tag{4} d((x1​,x2​),(y1​,y2​))=(10x1​​−10y1​​)2+(x2​−y2​)2​(4)
就可以得出合理的 kNN 分类。
  一般来说,假设进行 kNN 分类使用的样本的特征是{(xi1,xi2,...,xin)}i=1m\left \{ \left ( x_{i1},x_{i2},...,x_{in} \right ) \right \}_{i=1}^{m}{(xi1​,xi2​,...,xin​)}i=1m​,取每一轴上的最大值减最小值:
Mj=maxi=1,2,...,m(xij)−mini=1,2,...,m(xij)(5)M_{j}=\underset{i=1,2,...,m}{max}\left ( x_{ij} \right )-\underset{i=1,2,...,m}{min}\left ( x_{ij} \right ) \tag{5} Mj​=i=1,2,...,mmax​(xij​)−i=1,2,...,mmin​(xij​)(5)
并且,在计算距离时将每一个坐标轴除以相应的 M_{j}以进行归一化,即:
d((y1,...,yn),(z1,...,zn))=∑j=1n(yjMj−zjMj)2(6)d((y_{1},...,y_{n}),(z_{1},...,z_{n}))=\sqrt{\sum_{j=1}^{n}\left ( \frac{y_{j}}{M_{j}}-\frac{z_{j}}{M_{j}} \right )^{2}} \tag{6} d((y1​,...,yn​),(z1​,...,zn​))=j=1∑n​(Mj​yj​​−Mj​zj​​)2​(6)
便可以规避坐标轴比例失衡的问题。

4)概率kNN

  上面的kNN算法返回的是对一组特征的绝对分类,告诉我们这只兔子被判断为哪一个类别。可有时我们并不想知道一个确切地分类,而想知道它属于某个分类的概率是多大。比如我们发现一只身长 37厘米,体重 4.84公斤的小兔兔,在下图五角星的位置。

  这只兔子的特征数据在绿兔和蓝兔的分界处,机器不论判断它属于哪个类别都很有可能是错的。这时,类似“它有一半可能性是绿兔,一半可能性是蓝兔”的反馈会更有意义。
  为了这个目的,我们同样找出距离问题特征最近的kkk个样本,但与其寻找数量最多的分类,我们统计其中每个类别的分别有多少个,再除以kkk得到一个属于每一个类别概率值。比如在上面的图里,距离五角星最近的 15个样本中,有 8只绿兔和 7 只蓝兔,由此判断:它有 53% 的可能性是绿兔,47% 的可能性是蓝兔,0%的可能性是黄兔。
  在整个二维空间中的每一个点上进行概率 kNN 算法,可以得到每个特征点是属于某个类别的概率热力图,图中颜色越深代表概率越大。

15NN 绿兔的概率
15NN 蓝兔的概率

15NN 黄兔的概率

  相比于绝对的分类,这些概率的计算会给我们更有效的表述以及更多的应用空间。

3 kNN算法总结

  根据上述对kNN算法原理的解析,可以总结出其实现主要包含以下几个步骤:
  对于一组训练样本以及一个测试样本,
  (1)计算已知类别数据集中的点与当前点之间的距离;
  (2)按照距离递增次序排序;
  (3)选取与当前点距离最小的k个点;
  (4)确定前k个点所在类别的出现频率;
  (5)返回前k个点出现频率最高的类别作为当前点的预测分类。
  kNN算法作为一种较简单的算法,它的不足之处在于:
  (1)没有明显的训练过程,它是“懒惰学习”的典型代表,它在训练阶段所做的仅仅是将样本保存起来,如果训练集很大,必须使用大量的存储空间,训练时间开销为零;
  (2)必须对数据集中每个数据计算距离值,实际中可能非常耗时。
  由于上述的不足,为了提高kNN搜索的速度,可以利用特殊的数据存储形式来减少计算距离的次数。kd树就是一种以二叉树的形式存储数据的方法。kd树就是对k维空间的一个划分。构造kd树相当于不断用垂直于坐标轴的超平面将k维空间切分,构成一系列k维超矩阵区域。kd树的每一个节点对应一个超矩阵区域。后续文章讲详细介绍kd树的原理及算法实现。

参考资料
https://www.joinquant.com/view/community/detail/a98b7021e7391c62f6369207242700b2
https://zhuanlan.zhihu.com/p/25994179

kNN(k-Nearest Neighbours)原理详解相关推荐

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

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

  2. EMD算法之Hilbert-Huang Transform原理详解和案例分析

    目录 Hilbert-Huang Transform 希尔伯特-黄变换 Section I 人物简介 Section II Hilbert-Huang的应用领域 Section III Hilbert ...

  3. SVM分类器原理详解

    SVM分类器原理详解 标签: svm文本分类java 2015-08-21 11:51 2399人阅读 评论(0) 收藏 举报  分类: 数据挖掘 文本处理(16)  机器学习 分类算法(10)  目 ...

  4. 操作系统:基于页面置换算法的缓存原理详解(下)

    概述: 在上一篇<操作系统:基于页面置换算法的缓存原理详解(上)>中,我们主要阐述了FIFO.LRU和Clock页面置换算法.接着上一篇说到的,本文也有三个核心算法要讲解.分别是LFU(L ...

  5. Java HashMap的实现原理详解

    HashMap是Java Map类型的集合类中最常使用的,本文基于Java1.8,对于HashMap的实现原理做一下详细讲解. (Java1.8源码:http://docs.oracle.com/ja ...

  6. Java ArrayList的实现原理详解

    ArrayList是Java List类型的集合类中最常使用的,本文基于Java1.8,对于ArrayList的实现原理做一下详细讲解. (Java1.8源码:http://docs.oracle.c ...

  7. 主成分分析(PCA)原理详解 2016/12/17 · IT技术 · 主成分分析, 数学 分享到: 21 原文出处: 中科春哥 一、PCA简介 1. 相关背景 主成分分析(Principa

    主成分分析(PCA)原理详解 2016/12/17 · IT技术 · 主成分分析, 数学 分享到:21 原文出处: 中科春哥    一.PCA简介 1. 相关背景 主成分分析(Principal Co ...

  8. Vondrak滤波原理详解及Matlab实现

    Vondrak滤波原理详解及Matlab实现 一.Vondrak基本思想: 二.Vondrak平滑法的原理: 三.Vondrak滤波平滑公式: 四.Vondrak滤波应用 五.Matlab实现 一.V ...

  9. 蓝牙:CRC原理详解(附crc16校验代码)

    CRC原理详解(附crc16校验代码) 参考链接: https://www.cnblogs.com/esestt/archive/2007/08/09/848856.html Cyclic Redun ...

最新文章

  1. 再学 GDI+[25]: TGPPen - 宽度、颜色与线帽
  2. 文件格式用Latex排版论文(1)如何将Visio画图文件转换成Latex支持的.eps文件
  3. linux进程--进程组、会话、守护进程(八)
  4. Spring七中传播行为详解
  5. post提交,WPF,Silverlight(加深记忆写一遍)
  6. [Quatsch]Quantum Or Optics
  7. 【java】SpringBoot新特性 节省百分之95﹪内存占用
  8. 编程杂谈---vb,vb.net,java数据类型区分
  9. vue判断列表中包含某一项_判断字符串中是否包含某个字符串
  10. 【EMC】电压暂降、短时中断和电压变化
  11. 使用PS创造非凡动物形象
  12. 中年失业是一种什么体验
  13. Java面试复习体系总结(2021版,持续更新)
  14. 2016年不可错过的21个深度学习视频、教程和课程
  15. Latex 字体调整-斜体-下划线-加粗-罗马数字
  16. 西安邮电考研计算机复试线,2020西安邮电大学考研复试分数线已公布
  17. Nginx代理百度地图,实现内网访问百度地图
  18. 纵向时间线html,51个css时间轴
  19. Redis 基本命令和五大基础数据类型
  20. pandas与csv的用法笔记

热门文章

  1. 姨妈来了照样当夏日C位 TAMPAX丹碧丝联手聚划算欢乐谷动感开浪
  2. 基于电容电流前馈与电网电压全前馈的单相LCL并网逆变器谐波抑制MATLAB仿真(电压比例反馈及一二次微分反馈)
  3. springboot 连接sqlite
  4. RSA--维纳攻击--代码和题目分析
  5. 闲扯WPS Office 2005
  6. 042-云E办_(小问题:)更新用户后,应根据用户权限,显示菜单
  7. 数据集--load_boston()函数
  8. 关于 axios 取消重复请求的分析
  9. win10系统复制粘贴功能失效解决方法步骤
  10. Q1业绩稳健,达达集团展开价值的“稳定三角”