1 前言  

  Kjin邻法(k-nearest neighbors,KNN)是一种基本的机器学*方法,采用类似“物以类聚,人以群分”的思想。比如,判断一个人的人品,只需观察他来往最密切的几个人的人品好坏就可以得出。这里就运用了KNN的思想。KNN方法可以做分类,也可以做回归,这点和决策树算法相同。

  KNN做回归和分类的主要区别在于做预测时候的决策方式不同。

  KNN做分类预测时,一般是选择多数表决法,即训练集里和预测的样本特征最jin的K个样本,预测为里面有最多类别数的类别。
  KNN做回归时,一般是选择平均法,即最jin的K个样本的样本输出的平均值作为回归预测值。

2 KNN算法原理  

  给定一个训练集,对新输入的实例,在训练集中找到与该实例最邻jin的k个实例,这k个实例的多数属于某个类,我们就把该输入实例分为这个类。

2.1 算法描述

  输入:训练数据集$T={(x_1,y_1),(x_2,y_2),...,(x_N,y_N)}$,其中$x_i\in{\chi}$为实例的特征向量,$y_i\in{\{c_1,c_2,...,c_m\}}$为实例的类别,实例特征向量x。
  输出:实例 x 所属的类别 y。
  1.根据给定的距离度量方式,在训练集T中找到与x最邻jin的k个点,涵盖着k个点的x的领域记住$N_k(x)$。
  2.在$N_k(x)$中根据分类决策规则决定x的类别y
    $y=argmax_{c_j}\sum_{x_i\in{N_k(x)}}I(y_i=c_j)$
  其中$I(y_i=c_j)$为指示函数,当$y_i=c_j$的时候$I=1$,后者$I=0$ 。

3. KNN的基本要素

  对于一个确定的训练集,确定距离度量、k值和分类决策规则,就能对任何一个新的实例,确定它的分类。

3.1 距离度量

  距离度量是描述特征空间中两个实例的距离,也是这两个实例的相似程度。在n维实数向量空间中,我们主要使用的距离度量方式是欧式距离,但也可以使用更加一般化$L_p$距离(闵可夫斯基距离)。
  在特征空间中,取出两个特征$x_i$,$x_j$,它们分别是n维的特征向量。
  Lp距离(闵可夫斯基距离)
    $L_p(x_i,x_j)=(\sum_{l=1}^n|x_i^l-x_j^l|^p)^{\frac{1}{p}}$
  欧氏距离
    $L_2(x_i,x_j)=(\sum_{l=1}^n|x_i^l-x_j^l|^2)^{\frac{1}{2}}$
  曼哈顿距离
    $L_1(x_i,x_j)=\sum_{l=1}^n|x_i^l-x_j^l|$
  $L_{\infty}$距离
    $L_{\infty}(x_i-x_j)=\max_{l}|x_i^l-x_j^l|$

3.2 k值的选择

  对于k值的选择,没有一个固定的经验,一般根据样本的分布,选择一个较小的值,然后通过交叉验证选择一个合适的k值。
  • 如果选择较小的K值
    • “学*”的jin似误差(aproximation eror)会减小,但 “学*”的估计误差(estimation eror) 会增大。
    • 噪声敏感。
    • K值的减小就意味着整体模型变得复杂,容易发生过 拟合。
  • 如果选择较大的K值,
    •减少学*的估计误差,但缺点是学*的jin似误差增大。
    •K值的增大 就意味着整体的模型变得简单。
  一个极端是k等于样本数m,则完全没有分类,此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单。

3.3 分类决策规则

  对于分类决策规则,一般都是使用前面提到的多数表决法。

4. kd树  

  KNN算法最简单的实现方式:计算输入实例和所有训练实例的距离,进行排序,取前k个,进行分类。当训练集特别大的时候,非常耗时。
  下面介绍kd树的方式,kd树通过减少输入实例和训练实例的计算次数来达到优化的目的。
  kd树是一种对K维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。
  kd树是二叉树,表示对K维空间的一个划分。构造Kd树相当于不断地用垂直于坐标轴的超平面将k维空间切分,构成一 系列的k维超矩形区域。Kd树的每个结点对应于一个k维超矩形区域.
  kd树算法包括三步,第一步是建树,第二步是搜索最jin邻,最后一步是预测。

  

4.2 kd树搜索最jin邻居

  当我们生成kd树以后,就可以去预测测试集里面的样本目标点了。预测的过程如下:
  1、对于一个目标点,我们首先在kd树里面找到包含目标点的叶子节点。以目标点为圆心,以目标点到叶子节点样本实例的距离为半径,得到一个超球体,最jin邻的点一定在这个超球体内部。
  2、然后返回叶子节点的父节点,检查另一个子节点包含的超矩形体是否和超球体相交,如果相交就到这个子节点寻找是否有更加jin的jin邻,有的话就更新最jin邻,并且更新超球体。如果不相交那就简单了,我们直接返回父节点的父节点,在另一个子树继续搜索最jin邻。
  3、当回溯到根节点时,算法结束,此时保存的最jin邻节点就是最终的最jin邻。
  从上面的描述可以看出,kd树划分后可以大大减少无效的最jin邻搜索,很多样本点由于所在的超矩形体和超球体不相交,根本不需要计算距离。大大节省了计算时间。
  搜索过程,大致如下:

4.3 kd树预测

  有了kd树搜索最jin邻的办法,kd树的预测就很简单了,在kd树搜索最jin邻的基础上,我们选择到了第一个最jin邻样本,就把它置为已选。在第二轮中,我们忽略置为已选的样本,重新选择最jin邻,这样跑k次,就得到了目标的k个最jin邻。然后根据多数表决法,如果是KNN分类,预测为k个最jin邻里面有最多类别数的类别。如果是KNN回归,用k个最jin邻样本输出的平均值作为回归预测值。

4.4 示例:使用k-jin邻算法进行分类

from sklearn.datasets import make_blobs
# 生成数据
"""
代码中,生成60个训练样本,这60个样本分布在以centers参数指定中心点周围。cluster_std是标准差,用来指明生成的点分布的松散程度。
生成的训练数据集放在变量X里面,数据集的类别标记放在y里面。
make_blobs函数是为聚类产生数据集
产生一个数据集和相应的标签
n_samples:表示数据样本点个数,默认值100
n_features:表示数据的维度,默认值是2
centers:产生数据的中心点,默认值3
cluster_std:数据集的标准差,浮点数或者浮点数序列,默认值1.0
center_box:中心确定之后的数据边界,默认值(-10.0, 10.0)
shuffle :洗乱,默认值是True
random_state:官网解释是随机生成器的种子
"""
centers = [[-2,2], [2,2], [0,4]]
X, y = make_blobs(n_samples=100,centers=centers,random_state=6, cluster_std=0.60)
print(X) #坐标点
print(y) #类别
# 画出数据
"""
这些点的分布情况在坐标轴上一目了然,其中三角形的点即各个类别的中心节点。
"""
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(16,10), dpi=144)
c = np.array(centers)
# 画出样本
plt.scatter(X[:,0], X[:,1], c=y, s=100, cmap='cool')
# 画出中心点
plt.scatter(c[:,0], c[:,1], s=100, marker='^',c='orange')
plt.savefig('knn_centers.png')
plt.show() # 使用KNeighborsClassifier对算法进行训练,我们选择参数k=5
from sklearn.neighbors import KNeighborsClassifier
# 模型训练
k = 5
clf = KNeighborsClassifier(n_neighbors = k)
clf.fit(X, y)
# 对一个新样本进行预测:
# 进行预测
"""
我们要预测的样本是[0, 2],使用kneighbors()方法,把这个样本周围距离最*的5个点取出来。
取出来的点是训练样本X里的索引,从0开始计算。
"""
X_sample = np.array([[0, 2]])
y_sample = clf.predict(X_sample)
neighbors = clf.kneighbors(X_sample, return_distance=False) # 把待预测的样本以及和其最*的5个样本在图上标记出来。
# 画出示意图
plt.figure(figsize=(16,10), dpi=144)
c = np.array(centers)
plt.scatter(X[:,0], X[:,1], c=y, s=100, cmap='cool') # 出样本
plt.scatter(c[:,0], c[:,1], s=100, marker='^',c='k') # 中心点
plt.scatter(X_sample[0][0], X_sample[0][1], marker="x",
s=100, cmap='cool') # 待预测的点
for i in neighbors[0]:
plt.plot([X[i][0], X_sample[0][0]], [X[i][1], X_sample[0][1]],
'k--', linewidth=0.6) # 预测点与距离最*的5个样本的连线
plt.savefig('knn_predict.png')
plt.show()

机器学*——K*邻算法(KNN)的更多相关文章

  1. 【机器学*与R语言】2-懒惰学*K*邻(kNN)

    目录 1.理解使用KNN进行分类 KNN特点 KNN步骤 1)计算距离 2)选择合适的K 3)数据准备 2.用KNN诊断乳腺癌 1)收集数据 2)探索和准备数据 3)训练模型 4)评估模型的性能 5) ...

  2. 【机器学*】k*邻算法-02

    k邻*算法具体应用:2-2约会网站配对 心得体会: 1.对所有特征值进行归一化处理:将特征值单位带来的距离影响消除,使所有特征同权重--然后对不同的特征进行加权2.对于相互独立的特征,可以通过建立(特 ...

  3. 【机器学*】k-*邻算法(kNN) 学*笔记

    [机器学*]k-*邻算法(kNN) 学*笔记 标签(空格分隔): 机器学* kNN简介 kNN算法是做分类问题的.思想如下: KNN算法的思想总结一下:就是在训练集中数据和标签已知的情况下,输入测试数 ...

  4. k近邻算法(KNN)

    k近邻算法(KNN) 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别. from sklearn.model_selection ...

  5. 什么是机器学习的分类算法?【K-近邻算法(KNN)、交叉验证、朴素贝叶斯算法、决策树、随机森林】

    1.K-近邻算法(KNN) 1.1 定义 (KNN,K-NearestNeighbor) 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类 ...

  6. 【机器学*】k*邻算法-03

    心得体会: 需要思考如何将现实对象转化为特征向量,设置特征向量时记住鸭子定律1 鸭子定律1 如果走路像鸭子.说话像鸭子.长得像鸭子.啄食也像鸭子,那它肯定就是一只鸭子 事物的外在特征就是事物本质的表现 ...

  7. 【机器学*】k*邻算法-01

    k临*算法(解决分类问题): 已知数据集,以及该数据对应类型 给出一个数据x,在已知数据集中选择最接*x的k条数据,根据这k条数据的类型判断x的类型 具体实现: from numpy import * ...

  8. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

  9. K-近邻算法kNN

    K-近邻算法(k-Nearest Neighbor,简称kNN)采用测量不同特征值之间的距离方法进行分类,是一种常用的监督学习方法,其工作机制很简单:给定测试样本,基于某种距离亮度找出训练集中与其靠近 ...

随机推荐

  1. 树莓派远程连接工具VNC使用教程

    树莓派远程连接工具VNC使用教程 背景故事 树莓派作为一款迷你小主机,大部分的使用场景都会用到远程调试,远程调试用到最多的方式一般就是VNC和SSH,VNC是远程桌面型的远程方式,简单来说就是用Win ...

  2. Mybatis源码解析2—— 实例搭建

    大家好,我是可乐. 上篇文章给大家撸了一遍用 JDBC 直接操作数据库的实例,还只是简单写了一个查询的接口,其代码量就已经很大了,并且可乐还给大家分析了直接使用 JDBC 带来的一些问题,总之是一种反 ...

  3. SpringBoot开发十五-发布帖子

    需求介绍 使用 AJAX 异步通信实现网页能够增量的更新呈现到页面上而不需要刷新整个页面. 现在基本上都是服务器返回 JSON 字符串来解析 代码实现 使用 JQuery 发送 AJAX 请求. 首先 ...

  4. stm32 connot enter debug mode

    dap 可以发现设备,stlink jlink 均无法发现设备,但是都不能下载.connot enter debug mode ,发现是vdda 未连接

  5. dubbo-admin管理控制台安装

    拉项目切换分支到master git clone https://github.com/apache/dubbo-admin.git /var/tmp/dubbo-admin 打开项目修改配置 dub ...

  6. liunx系统mysql全量备份和增量备份

    前提 ​ 在互联网项目中最终还是读数据进行操作,都离不开曾删改查,那么数据是重中之重,数据库的备份就显得格外重要. ​ 但是每次都直接导出整个数据库的sql文件,显然是不现实的.对数据库的性能影响比较 ...

  7. CentOS7 yum方式安装MySQL5.7 + 远程连接

    1 下载并安装MySQL官方的 Yum Repository [root@localhost ~]# wget -i -c http://dev.mysql.com/get/mysql57-commu ...

  8. offsetof宏---个人笔记

    标准库里面提供的offsetof(t,m)宏,用来计算两个变量在内存中的地址偏移量 #include <stdio.h>//原型: #define offsetof(TYPE, MEMBE ...

  9. java基本数据类型和包装类之间的转换(装箱,拆箱)

    1.装箱:把基本数据类型转换成包装类 1.1自动装箱 int t1=2; Integer t2 =t1; 1.2手动装箱 Integer t3 = new Integer(t1); 2.拆箱:把包装类 ...

  10. Go依赖包管理--间接依赖

    目录 1.indirect含义 1.2 直接依赖未启用 Go module 1.2 直接依赖 go.mod 文件不完整 2.总结 1.indirect含义 在使用 Go module 过程中,随着引入 ...