02-16 k近邻算法

[TOC]
更新、更全的《机器学习》的更新网站,更有python、go、数据结构与算法、爬虫、人工智能教学等着你:https://www.cnblogs.com/nickchen121/

k近邻算法

k近邻算法(k-nearest neighbors,KNN)是一种基本的分类和回归方法,本文只探讨分类问题中的k近邻算法,回归问题通常是得出最近的$k$个实例的标记值,然后取这$k$实例标记值的平均数或中位数。

k近邻算法经常被人们应用于生活当中,比如傅玄曾说过“近朱者赤近墨者黑”,还有人曾说过“如果要判断一个人的品性,只需要看看他身边朋友的品性即可”,这些都是用了k近邻算法的思想。

本文主要介绍k近邻算法的基本理论以及k近邻的扩展——限定半径最近邻算法和最近质心算法,之后会使用k近邻算法对鸢尾花数据进行分类,并讲解scikit-learn库中k近邻算法各个参数的使用。为了解决k近邻算法需要大量计算的问题在这之后会讲解kd树(KDTree)。

一、k近邻算法学习目标

  1. k近邻算法三要素
  2. 维数诅咒
  3. k近邻算法流程
  4. k近邻算法优缺点

二、k近邻算法引入

不知道同学们在看电影的时候有没有思考过你是如何判断一部电影是爱情片还是动作片的,你可以停下来想想这个问题再往下看看我的想法。

我说说我是如何判断一部电影是爱情片还是动作片的,首先绝对不是靠那些预告片,毕竟预告片太短了,爱情片的预告可能是动作片,动作片的预告可能是爱情片也说不定。

相比较预告片我用了一个很愚蠢很繁琐但很有效的方法。首先我用一部电影的接吻镜头的次数作为$x$轴,打斗的场景次数作为$y$轴生成了一个二维空间,即平面图,如下图所示。(注:以下电影的接吻镜头次数和打斗场景次数都是假设的)

# k近邻算法引入图例
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
%matplotlib inline
font = FontProperties(fname=‘/Library/Fonts/Heiti.ttc‘)

# 动作片
plt.scatter(2, 10, marker=‘o‘, c=‘r‘, s=50)
plt.text(2, 9, s=‘《战狼2》(2,10)‘, fontproperties=font, ha=‘center‘)
plt.scatter(4, 12, marker=‘o‘, c=‘r‘, s=50)
plt.text(4, 11, s=‘《复仇者联盟2》(4,12)‘, fontproperties=font, ha=‘center‘)
plt.scatter(2, 15, marker=‘o‘, c=‘r‘, s=50)
plt.text(2, 14, s=‘《猩球崛起》(2,15)‘, fontproperties=font, ha=‘center‘)

# 爱情片
plt.scatter(10, 4, marker=‘x‘, c=‘g‘, s=50)
plt.text(10, 3, s=‘《泰坦尼克号》(10,4)‘, fontproperties=font, ha=‘center‘)
plt.scatter(12, 2, marker=‘x‘, c=‘g‘, s=50)
plt.text(12, 1, s=‘《致我们终将逝去的青春》(12,2)‘, fontproperties=font, ha=‘center‘)
plt.scatter(15, 5, marker=‘x‘, c=‘g‘, s=50)
plt.text(15, 4, s=‘《谁的青春不迷茫》(15,5)‘, fontproperties=font, ha=‘center‘)

# 测试点
plt.scatter(5, 6, marker=‘s‘, c=‘k‘, s=50)
plt.text(5, 5, s=‘《未知类型的电影》(5,6)‘, fontproperties=font, ha=‘center‘)

plt.xlim(0, 18)
plt.ylim(0, 18)
plt.xlabel(‘接吻镜头(次)‘, fontproperties=font)
plt.ylabel(‘打斗场景(次)‘, fontproperties=font)
plt.title(‘k近邻算法引入图例‘, fontproperties=font, fontsize=20)
plt.show()

![png](http://www.chenyoude.com/ml/02-16 k近邻算法_6_0.png?x-oss-process=style/watermark)

通过上图我们可以发现动作片《战狼2》的打斗场景次数明显多于接吻镜头,而爱情片《泰坦尼克号》的接吻镜头明显多于打斗场景,并且其他的动作片和爱情片都有这样的规律,因此我做了一个总结:爱情片的接吻镜头次数会明显比打斗的场景次数多,而动作片反之。

通过上述的总结,如果我再去看一部新电影的时候,我会在心里默数这部电影的接吻镜头的次数和打斗场景,然后再去判断。这种方法看起来无懈可击,但是如果碰到了上述黑点《未知类型的电影》所在的位置,即当接吻镜头次数和打斗场景次数差不多的时候,往往很难判断它是爱情片还是动作片。

这个时候我们的主角k近邻算法就应该出场了,因为使用k近邻算法可以很好的解决《未知类型的电影》这种尴尬的情形。

  1. 假设我们把平面图中的每一个电影看成一个点,例如《战狼2》是$(2,10)\(、《未知类型的电影》是\)(5,6)\(、《泰坦尼克号》是\)(10,4)$……
  2. 我们使用k近邻的思想,通过欧几里得距离公式计算出每一部电影在平面图中到《未知类型的电影》的距离
  3. 然后假设$k=4$,即获取离《未知类型的电影》最近的$4$部电影
  4. 如果这$4$部电影中爱情片类型的电影多,则《未知类型的电影》是爱情片;如果动作片类型的电影多,则《未知类型的电影》是动作片;如果两种类型的电影数量一样多,则另选$k$值

上述整个过程其实就是k近邻算法实现的一个过程,接下来将从理论层面抽象的讲解k近邻算法。

三、k近邻算法详解

k近邻算法简而言之就是给定一个有$m$个实例的数据集$T={(x_1,y_1),(x_2,y_2),\cdots,(x_m,y_m)}$,计算出未来新样本到每个实例的距离,然后找到与未来新数据最近的$k$个实例,这$k$个实例哪个类别的实例多,则未来新样本属于哪个类别,基于这个解释可以给出k近邻算法的三个基本要素。

3.1 k近邻算法三要素

k近邻算法的三个基本要素分别是$k$值的选择、距离度量的方式和分类决策的规则,只要这三点确定了,则k近邻算法也就确定了。

3.1.1 k值的选择

k近邻算法对于$k$值的选择,一般没有一个固定的选择,对于不同的问题通常可能有不同的$k$值。但是需要注意的是如果$k$值取的越大,则离未来新样本的实例会越来越多,即较远的实例也会对结果造成影响,从而使得模型欠拟合,但是模型会变得简单;反之只有较少的实例会对结果造成影响,模型会变得复杂,同时会使得模型容易发生过拟合现象。并且需要注意的是$k$值一般小于20。

例如当$k$值取$m$的时候,模型会简单到无论未来新样本输入什么,预测结果都是训练集中实例最多的类。

3.1.2 最近邻算法

当$k=1$的时候,称为最近邻算法,即对于未来新样本,最近邻算法将训练集中与未来新样本最邻近点的类别作为未来新样本的类别。

3.1.3 距离度量的方式

k近邻算法对于距离度量的方式,有很多种方法可以选择,一般选择我们电影分类例子中讲到的欧几里得距离,也称作欧氏距离。同时还可能会使用曼哈顿距离或闵可夫斯基距离,这里统一给出它们的公式。

假设$n$维空间中有两个点$x_i$和$x_j$,其中$x_i = (x_i^{(1)},x_i^{(2)},\cdots,x_i^{(n)})$,\(x_j = (x_j^{(1)},x_j^{(2)},\cdots,x_j^{(n)})\)。

欧氏距离为

\[
d(x_i,x_j) = \sqrt{\sum_{l=1}^n(x_i^{(l)}-x_j^{(l)})^2}
\]

曼哈顿距离为

\[
d(x_i,x_j) = \sum_{l=1}^n|x_i^{(l)}-x_j^{(l)}|
\]

闵可夫斯基距离为

\[
d(x_i,x_j) = \sqrt[p]{\sum_{l=1}^n(|x_i^{(l)}-x_j^{(l)}|)^p}
\]

其中曼哈顿距离是闵可夫斯基距离$p=2$时的特例,而欧氏距离是闵可夫斯基距离$p=1$时的特例。

3.1.4 分类决策规则

k近邻算法对于分类决策规则,一般选择电影分类例子中讲到的多数表决法,即$k$个实例中拥有最多实例的类别即为未来新样本的类别。例如假设得到距离《未知类型的电影》最近的$10$部电影中,有$3$部属于$c_1$类;有$3$部属于$c_2$类;有$4$部是$c_3$类,则可以判断《未知类型的电影》属于$c_3$类。

值得注意的是使用k近邻算法解决回归问题时,分类决策的规则通常是对$k$个实例的标记值取平均值或中位数。例如距离未来新样本的最近的$3$个实例的标记值分别为${2.3,2.7,1.0}\(,则可以得到未来新样本的标记值为\){\frac{2.3+2.7+1.0}{3}}=2$。

3.2 维数诅咒

维数诅咒的意思是:当训练集特征维度越来越大的时候,特征空间越来越稀疏,通过距离度量的方式可以发现即使是最近的邻居在高维空间的距离也很远,以至于很难估计样本之间的距离。

一般情况下可以使用特征选择和降维等方法避免维数诅咒。

四、k近邻算法的拓展

4.1 限定半径k近邻算法

限定半径k近邻算法顾名思义就是限定一个距离范围搜索$k$个近邻,通过限定距离范围可以解决数据集中实例太少甚至少于$k$的问题,这样就不会把距离目标点较远的实例也划入$k$个实例当中。

4.2 最近质心算法

最近质心算法是将所有实例按照类别归类,归类后对$c_k$类的所有实例的$n$维特征的每一维特征求平均值,然后由每一维特征的平均值形成一个质心点,对于样本中的所有类别都会对应获得一个质心点。

每当未来新样本被输入时,则计算未来新样本到每一个类别对应质心点的距离,距离最近的则为该未来新样本的类别。

五、k近邻算法流程

5.1 输入

有$m$个实例$n$维特征的数据集

\[
T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_m,y_m)\}
\]

其中$x_i$是实例的特征向量即$({(1)},{(2)},\cdots,^{(n)})$,$y_i$是实例的类别,数据集有${c_1,c_2,\cdots,c_j}$共$j$个类别。

5.2 输出

未来新样本$(x_i,y_i), \quad (i=1,2,\cdots,m)$的类别$c_l, \quad (l=1,2,\cdots,j)$。

5.3 流程

  1. 根据给定的距离度量方式,计算出训练集$T$中与未来新样本$(x_i,y_i)$最邻近的$k$个实例
  2. 使用分类决策规则(如多数表决法)决定未来新样本$(x_i,y_i)$的类别为$c_l$;如果是回归问题,取$??$个近邻点的标记值的平均数或中位数即可。

六、k近邻算法优缺点

6.1 优点

  1. k近邻算法简单易懂,容易实现,可以做分类也可以做回归
  2. k近邻算法基于实例学习,对数据没有假设,不需要通过模型训练获得参数

6.2 缺点

  1. 计算复杂度高、空间复杂度高,例如当训练集有10000个样本的时候,需要计算5000万次,再加上实例的特征维度有时候也是极高的,这种计算量对于计算机而言也是很庞大的(如果样本数量过多则可能需要换算法换模型,如果特征过多可以使用降维算法)
  2. 无论哪一种距离度量方式都需要使用到特征值之间的差值,如果某些特征值之间的差值过大会掩盖差值较小特征对预测值的影响(一般使用数据预处理中的归一化方法处理特征值)
  3. 相比较决策树,解释型不强(客户真的想要解释性强的模型换个决策树试一试)

七、小结

除了我们讲的第一个古老的机器学习算法感知机,k近邻算法应该是目前工业上还会使用最为简单的算法,并且使用起来也很简单、方便,但是有个前提是数据量不能过大,更不能使用有维数诅咒的数据集。

k近邻遇到数据量大的数据集计算量是一个很难解决的问题,那么有没有什么好的方法能稍微减轻这个问题呢?有是一定有的,即下一篇——kd树。

原文地址:https://www.cnblogs.com/nickchen121/p/11686786.html

时间: 2024-10-10 07:39:03

02-16 k近邻算法的相关文章

机器学习实战笔记--k近邻算法

1 #encoding:utf-8 2 from numpy import * 3 import operator 4 import matplotlib 5 import matplotlib.pyplot as plt 6 7 from os import listdir 8 9 def makePhoto(returnMat,classLabelVector): #创建散点图 10 fig = plt.figure() 11 ax = fig.add_subplot(111) #例如参数为

用Python从零开始实现K近邻算法

K近邻算法 (或简称kNN)是易于理解和实现的算法,而且是你解决问题的强大工具. http://python.jobbole.com/87407/ 在本教程中,你将基于Python(2.7)从零开始实现kNN算法.该实现主要针对分类问题,将会用鸢尾花分类问题来演示. 这篇教程主要针对Python程序员,或者你可以快速上手Python,并且对如何从零实现kNN算法感兴趣. kNN算法图片,来自Wikipedia,保留所有权利 什么是kNN kNN算法的模型就是整个训练数据集.当需要对一个未知数据实

K近邻算法调参方法

//2019.08.02下午#机器学习算法中的超参数与模型参数1.超参数:是指机器学习算法运行之前需要指定的参数,是指对于不同机器学习算法属性的决定参数.通常来说,人们所说的调参就是指调节超参数.2.模型参数:是指算法在使用过程中需要学习得到的参数,即输入与输出之间映射函数中的参数,它需要通过对于训练数据集训练之后才可以得到.3.对于KNN算法,它是没有模型参数的,它的k参数就属于典型的超参数. 4.好的超参数的选择主要取决于三个方面:(1)领域知识(2)经验数值(3)实验搜索5.K近邻算法常用

『cs231n』作业1问题1选讲_通过代码理解K近邻算法&交叉验证选择超参数参数

通过K近邻算法探究numpy向量运算提速 茴香豆的"茴"字有... ... 使用三种计算图片距离的方式实现K近邻算法: 1.最为基础的双循环 2.利用numpy的broadca机制实现单循环 3.利用broadcast和矩阵的数学性质实现无循环 图片被拉伸为一维数组 X_train:(train_num, 一维数组) X:(test_num, 一维数组) 方法验证 import numpy as np a = np.array([[1,1,1],[2,2,2],[3,3,3]]) b

K 近邻算法

声明: 1,本篇为个人对<2012.李航.统计学习方法.pdf>的学习总结,不得用作商用,欢迎转载,但请注明出处(即:本帖地址). 2,因为本人在学习初始时有非常多数学知识都已忘记,所以为了弄懂当中的内容查阅了非常多资料.所以里面应该会有引用其它帖子的小部分内容,假设原作者看到能够私信我,我会将您的帖子的地址付到以下. 3.假设有内容错误或不准确欢迎大家指正. 4.假设能帮到你.那真是太好了. 描写叙述 给定一个训练数据集,对新的输入实例.在训练数据集中找到与该实例最邻近的K个实例,若这K个实

从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章待写:1.KD树:2.神经网络:3.编程艺术第28章.你看到,blog内的文章与你于别处所见的任何都不同.于是,等啊等,等一台电脑,只好等待..”.得益于田,借了我一台电脑(借他电脑的时候,我连表示感谢,他说“能找到工作全靠你的博客,这点儿小忙还说,不地道”,有的时候,稍许感受到受人信任也是一种压力,愿我不辜负大家对我的信任)

K近邻算法

1.1.什么是K近邻算法 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居.为何要找邻居?打个比方来说,假设你来到一个陌生的村庄,现在你要找到与你有着相似特征的人群融入他们,所谓入伙. 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属

K近邻算法-KNN

何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居.为何要找邻居?打个比方来说,假设你来到一个陌生的村庄,现在你要找到与你有着相似特征的人群融入他们,所谓入伙. 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个类,就把该输入实例分

k近邻算法理论(一)

时间 :2014.07.05 地点:基地 ----------------------------------------------------------------------------------- 一.简述 K近邻法(k-nearest neighbor,kNN)是一种基本分类与回归方法.k近邻的输入为实例的特征向量,对应特征空间中的点,输出为实例的类别.k近邻算法的基本思想是:给定训练数据集,实例类别已定,在对目标实例进行分类时,我们根据与目标实例k个最近邻居的训练实例的类别,通过

基本分类方法——KNN(K近邻)算法

在这篇文章 http://www.cnblogs.com/charlesblc/p/6193867.html 讲SVM的过程中,提到了KNN算法.有点熟悉,上网一查,居然就是K近邻算法,机器学习的入门算法. 参考内容如下:http://www.cnblogs.com/charlesblc/p/6193867.html 1.kNN算法又称为k近邻分类(k-nearest neighbor classification)算法. 最简单平凡的分类器也许是那种死记硬背式的分类器,记住所有的训练数据,对于