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

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()

通过上图我们可以发现动作片《战狼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\)是实例的特征向量即\(({x_i}^{(1)},{x_i}^{(2)},\cdots,{x_i}^{(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\);如果是回归问题,取\(

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

    1. 02机器学习实战之K近邻算法

      第2章 k-近邻算法 KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法是一种基本分类与回归方法,我们这里只讨论分类问题中的 k-近邻算法. 一句话总结:近朱者赤近墨者黑! k ...

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

      KNN算法的定义: KNN通过测量不同样本的特征值之间的距离进行分类.它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别.K通 ...

    3. 1.K近邻算法

      (一)K近邻算法基础 K近邻(KNN)算法优点 思想极度简单 应用数学知识少(近乎为0) 效果好 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 图解K近邻算法 上图是以 ...

    4. 第四十六篇 入门机器学习——kNN - k近邻算法(k-Nearest Neighbors)

      No.1. k-近邻算法的特点 No.2. 准备工作,导入类库,准备测试数据 No.3. 构建训练集 No.4. 简单查看一下训练数据集大概是什么样子,借助散点图 No.5. kNN算法的目的是,假如 ...

    5. 2.在约会网站上使用k近邻算法

      在约会网站上使用k近邻算法 思路步骤: 1. 收集数据:提供文本文件.2. 准备数据:使用Python解析文本文件.3. 分析数据:使用Matplotlib画二维扩散图.4. 训练算法:此步骤不适用于 ...

    6. GridSearchCV网格搜索得到最佳超参数, 在K近邻算法中的应用

      最近在学习机器学习中的K近邻算法, KNeighborsClassifier 看似简单实则里面有很多的参数配置, 这些参数直接影响到预测的准确率. 很自然的问题就是如何找到最优参数配置? 这就需要用到 ...

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

      #encoding:utf-8 from numpy import * import operator import matplotlib import matplotlib.pyplot as pl ...

    8. k近邻算法的Java实现

      k近邻算法是机器学习算法中最简单的算法之一,工作原理是:存在一个样本数据集合,即训练样本集,并且样本集中的每个数据都存在标签,即我们知道样本集中每一数据和所属分类的对应关系.输入没有标签的新数据之后, ...

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

      在这篇文章 http://www.cnblogs.com/charlesblc/p/6193867.html 讲SVM的过程中,提到了KNN算法.有点熟悉,上网一查,居然就是K近邻算法,机器学习的入门 ...

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

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

    随机推荐

    1. Java Web总结(二)-- 上传和下载

        在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接 ...

    2. PyTorch在笔记本上实现CUDA加速

      最近刚开始学习深度学习,参考了一篇深度学习的入门文章,原文链接:https://medium.freecodecamp.org/everything-you-need-to-know-to-maste ...

    3. Docker在IDEA中的使用以及如何部署到服务器

      IDEA中实现一键部署到服务器 点击运行自动部署到服务器: 服务器上安装docker 1,添加yum源 # yum install epel-release –y# yum clean all# yu ...

    4. git windows 安装 - Github同步 / Vscode源代码管理:Git 安装操作

      github上创建立一个项目 登录github网站,在github首页,点击页面右下角"New Repository" 最后点击"Create Repository&qu ...

    5. Alibaba Cloud Toolkit 一键部署插件使用入门

      一.前言 Cloud Toolkit官方介绍文档:https://www.aliyun.com/product/cloudtoolkit Cloud Toolkit 是针对 IDE 平台为开发者提供的 ...

    6. 【linux】【elasticsearch】解决docker pull error pulling image configuration: Get https://d2iks1dkcwqcbx.cloudfront.net/

      网络原因导致的问题: error pulling image configuration: Get https://d2iks1dkcwqcbx.cloudfront.net/docker/regis ...

    7. WebStorm2017.3.4版本 注册码

      http://idea.singee77.com http://im.js.cn:8888

    8. 浅谈 Vector

      目录 浅谈Vector 1.容器基本操作 2.vector 初始化 3.vector的赋值与swap 4.vector的增删改除 1.增加元素 2.访问元素 3.删除元素 4.元素的大小 浅谈Vect ...

    9. 如何更规范化编写Java 代码

      如何更规范化编写Java 代码 Many of the happiest people are those who own the least. But are we really so happy ...

    10. 快速整理代码(c#)

      今天写代码发现有些代码行参差不齐,空行又多,整理看起来丑的不行,于是上网搜了下代码整理的快捷方式以作记录 这是整理之前,乱糟糟的(故意打乱为了节目效果) 第一步:Ctrl+a  (全选代码) 第二部: ...