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. Abp vNext 基础篇丨分层架构

    介绍 本章节对 ABP 框架进行一个简单的介绍,摘自ABP官方,后面会在使用过程中对各个知识点进行细致的讲解. 领域驱动设计 领域驱动设计(简称:DDD)是一种针对复杂需求的软件开发方法.将软件实现与 ...

  2. CVE-2021-25646:Apache Druid远程命令执行漏洞复现

    漏洞概述 Apache Druid 是一个分布式的数据处理系统.Apache Druid包括执行用户提供的JavaScript的功能嵌入在各种类型请求中的代码.在Druid 0.20.0及更低版本中, ...

  3. .NET Core 新特性:发布单文件可执行程序

    一.前言 .NET Core 3.0中新增加了一个特性:Publishing Single EXEs,可以通过dotnet publish 命令将整个.net core应用发布为一个可执行文件. 二. ...

  4. WPF原理剖析——路由事件

    一.路由事件与传统事件传统事件的触发者和处理者是紧密相连的,而路由事件则不是,路由事件允许一个元素的事件有另外的元素触发.也即就是说路由事件的拥有者和响应者之间没有显示的订阅关系.事件的拥有者只负责激 ...

  5. Mybatis的分页工具

    配置拦截器插件 特别注意,新版拦截器是 com.github.pagehelper.PageInterceptor. com.github.pagehelper.PageHelper 现在是一个特殊的 ...

  6. [ASP.NET MVC]@Html.ActionLik重载

    一 Html.ActionLink("linkText","actionName") 该重载的第一个参数是该链接要显示的文字,第二个参数是对应的控制器的方法, ...

  7. (1)hadoop之----linux配置jdk环境

    首先Linux中应有jdk包 运用flashFXP上传文件,xshell连接linux系统 我一般将文件放在个人目录下softwear目录 ,软件装在个人目录下app目录 cd software    ...

  8. android Handler消息通信

    1 package com.example.testhandler; 2 3 import android.os.Bundle; 4 import android.os.Handler; 5 impo ...

  9. 回忆java输入输出流,走出误区

    input read 将一个XXX读入(input)---从输入流中读取数据的下一个字节(code操作的).output write 将一个类型的数据写入此流(code操作的)---然后把XXX输出( ...

  10. 理解Flink中的Task和SUBTASK

    1.概念 Task(任务):Task是一个阶段多个功能相同的subTask 的集合,类似于Spark中的TaskSet. subTask(子任务):subTask是Flink中任务最小执行单元,是一个 ...