笔者本人是个初入机器学习的小白,主要是想把学习过程中的大概知识和自己的一些经验写下来跟大家分享,也可以加强自己的记忆,有不足的地方还望小伙伴们批评指正,点赞评论走起来~

1.k-近邻算法概述

k-近邻(k-nearest neighbor, k-NN)算法是一种基本分类与回归方法,这里只讨论分类问题中的k-NN。

k-NN算法:假设给定一个训练数据集,其中的实例类别已定(即有标签的训练数据集,属于有监督学习问题),分类时,对新的输入实例,在训练数据集中找到与该实例距离最近的k个实例,这k个实例的多数属于某个类,就把该输入实例分为这个类。

因此,k-NN不具有显式的学习过程。该算法实际上是利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。

k-NN的特点

  • 优点:精度高、对异常值不敏感、无数据输入假定;(优点的第三点不是特别理解,欢迎知道的小伙伴留言指教~)
  • 缺点:计算复杂度高、空间复杂度高;
  • 适用数据范围:数值型、标称型

k-NN使用的模型实际上对应于特征空间的划分。模型由距离度量、k值、分类决策规则这三个基本要素决定,下面对k-NN模型这三个基本要素进行简单介绍。

1.1 距离度量

特征空间中两个实例点的距离是两个实例点相似程度的反映。k-NN使用的距离是欧氏距离,也可以是其他距离,如更一般的LpL_pLp​距离或Minkowski距离。

设特征空间χ\chiχ是n维实数向量空间RnR^nRn,xi,xj∈χx_i,x_j\in\chixi​,xj​∈χ,xi=(xi(1),xi(2),...,xi(n))Tx_i = (x_{i}^{(1)},x_{i}^{(2)},...,x_{i}^{(n)})^Txi​=(xi(1)​,xi(2)​,...,xi(n)​)T,xj=(xj(1),xj(2),...,xj(n))Tx_j= (x_{j}^{(1)},x_{j}^{(2)},...,x_{j}^{(n)})^Txj​=(xj(1)​,xj(2)​,...,xj(n)​)T,xi,xjx_i,x_jxi​,xj​的LpL_pLp​距离定义为:

Lp(xi,xj)=(∑l=1n∣xi(l)−xj(l)∣p)1p(p≥1)L_p(x_i,x_j)=(\sum_{l=1}^{n}|x_{i}^{(l)}-x_{j}^{(l)}|^p)^{\frac{1}{p}}(p\ge1)Lp​(xi​,xj​)=(l=1∑n​∣xi(l)​−xj(l)​∣p)p1​(p≥1)

  • 当p=2时,为欧氏距离(Euclidean distance),即L2(xi,xj)=(∑l=1n∣xi(l)−xj(l)∣2)12L_2(x_i,x_j)=(\sum_{l=1}^{n}|x_{i}^{(l)}-x_{j}^{(l)}|^2)^{\frac{1}{2}}L2​(xi​,xj​)=(∑l=1n​∣xi(l)​−xj(l)​∣2)21​,或者我们更为熟悉的形式:L2(xi,xj)=∑l=1n(xi(l)−xj(l))2L_2(x_i,x_j)=\sqrt{\sum_{l=1}^{n}(x_{i}^{(l)}-x_{j}^{(l)})^2}L2​(xi​,xj​)=l=1∑n​(xi(l)​−xj(l)​)2​
  • 当p=1时,称为曼哈顿距离(Manhattan distance),即L1(xi,xj)=∑l=1n∣xi(l)−xj(l)∣L_1(x_i,x_j)=\sum_{l=1}^{n}|x_{i}^{(l)}-x_{j}^{(l)}|L1​(xi​,xj​)=l=1∑n​∣xi(l)​−xj(l)​∣
  • 当p=∞\infty∞时,它是各个坐标距离的最大值,即L∞(xi,xj)=maxl∣xi(l)−xj(l)∣L_\infty(x_i,x_j)=max_{l}|x_{i}^{(l)}-x_{j}^{(l)}|L∞​(xi​,xj​)=maxl​∣xi(l)​−xj(l)​∣

1.2 k值的选择

k值的选择会对k-NN法的结果产生重大影响。

若选择较小的k值,就相当于用较小的领域中的训练实例进行预测。

  • 优点:学习的近似误差(approximation error)会减小,只有与输入实例距离较近(相似)的训练实例才会对预测结果有影响;
  • 缺点:学习的估计误差(estimation error)会增大,预测结果会对近邻的实例点非常敏感。这时如果邻近的实例点恰巧是噪声,预测就会出错。

k值的减小意味着整体模型变得复杂,容易发生过拟合。

若选择较大的k值,就相当于用较大邻域中的训练实例进行预测。

  • 优点:学习的估计误差会减小
  • 缺点:学习的近似误差会增大。这时与输入实例距离较远(不相似)的训练实例也会对预测结果有影响,使预测发生错误。

k值的增大意味着整体模型变得简单,容易欠拟合。

在实际应用中,k值一般取一个比较小的数值。通常采用交叉验证法来选取最优的k值。

1.3 分类决策规则

k-NN中的分类决策规则通常是多数表决,即由与输入实例距离最近的k个训练实例中的多数类决定输入实例的类。

2.k-近邻算法实现

2.1 实现方法

实现k-近邻法时,主要考虑的问题是如何对训练数据进行快速k近邻搜索。这点在特征空间的维数较大及训练数据容量较大时尤其重要。

下面主要介绍k-近邻法的两种实现方法:

线性搜索(linear scan)法:

  • 优点:这是k近邻法最简单的实现方法
  • 缺点:要计算输入实例与每一个训练实例的距离。当训练集很大时,计算非常耗时,这种方法不太可行。

kd树(也称k决策树):

为了提高k近邻搜索的效率,可以考虑使用特殊的结构存储训练数据,以减少计算距离的次数。具体方法有很多,其中方法之一就是kd树方法。可以节省大量的计算开销。

2.2 k-近邻法python3.6实现

本节主要介绍基于欧式距离、多数表决规则,实现方法采用线性搜索法,实现k-近邻法。开发环境为python3.6。

对于kd树的实现,现在暂时没有了解代码实现,后期再补上。

2.2.1 k-近邻法实现程序

from numpy import *
import operator ## k-近邻法实现
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
# 计算距离
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5
# 选择距离最小的k个点
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 对字典排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
# Python3中不再支持iteritems(),将iteritems()改成items()
return sortedClassCount[0][0]

2.2.2 classify0(inX, dataSet, labels, k)中部分方法注释

  • classify0函数中参数说明

     inX:测试实例,n维行向量(n为实例的特征数)
    dataSet:训练实例数据集,m*n的NumPy矩阵(m为训练实例数,n为实例的特征数)
    labels:m维行向量(m为训练实例总个数)
  • 数组的维度

     例子:x = array([[[1,2,3],[4,5,6]],[[7,8,9],[0,1,2]],[[3,4,5],[6,7,8]]])
    print(x.shape) #(3,2,3)
    可以看到x是一个包含了3个两行三列的二维数组的三维数组:
    x.shape[0]代表包含二维数组的个数,x.shape[1]表示二维数组的行数,x.shape[2]表示二维数组的列数。
  • tile(A, res)

     功能:重复A的各个维度
    参数类型:
    A: Array类的都可以
    rep:A沿着各个维度重复的次数
    例子:
    print(tile([1,2],(2,2,3)))
    重复顺序为: [1,2] => [[1,2] , [1,2]] => [[[1,2],[1,2]] , [[1,2],[1,2]]] => [[[1,2,1,2,1,2],[1,2,1,2,1,2]] , [[1,2,1,2,1,2],[1,2,1,2,1,2]]]
  • sum()

     在numpy中数组都有着[]标记,则axis=0对应着最外层的[],axis=1对应第二外层的[],以此类推。
    例子:
    a= array([[1,2],[3,4]])
    a.sum(axis = 0)
    a有两层[],最外层[]里的最大单位块分别为[1,2],[3,4],对这两个单位块做块与块之间的运算,[1,2]+[3,4] = [4, 6];
    做完加法后本应是[[4, 6]],但是移除最外层[]后,原来的两层[]变成一层[],所以返回结果为 [4, 6]。
  • argsort()函数

     x.argsort():将x中的元素从小到大排列,提取其对应的index(索引)
  • dict.items()

     作用:可以将字典中的所有项,以列表方式返回。因为字典是无序的,所以用items方法返回字典的所有项,也是没有顺序的。
  • operator.itemgetter()

     operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号。

2.2.3 如何测试分类器

这里用错误率来评估分类器在某个数据集上的执行效果:

错误率=分类器给出错误结果的次数测试执行的总数错误率=\frac{分类器给出错误结果的次数}{测试执行的总数}错误率=测试执行的总数分类器给出错误结果的次数​

参考资料:

  • 《机器学习实战》第二章
  • 《统计学习方法》第三章

【机器学习实战学习笔记(1-1)】k-近邻算法原理及python实现的更多相关文章

  1. 【机器学习实战学习笔记(1-2)】k-近邻算法应用实例python代码

    文章目录 1.改进约会网站匹配效果 1.1 准备数据:从文本文件中解析数据 1.2 分析数据:使用Matplotlib创建散点图 1.3 准备数据:归一化特征 1.4 测试算法:作为完整程序验证分类器 ...

  2. 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...

  3. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  4. 《机实战》第2章 K近邻算法实战(KNN)

    1.准备:使用Python导入数据 1.创建kNN.py文件,并在其中增加下面的代码: from numpy import * #导入科学计算包 import operator #运算符模块,k近邻算 ...

  5. 【机器学习实战学习笔记(2-2)】决策树python3.6实现及简单应用

    文章目录 1.ID3及C4.5算法基础 1.1 计算香农熵 1.2 按照给定特征划分数据集 1.3 选择最优特征 1.4 多数表决实现 2.基于ID3.C4.5生成算法创建决策树 3.使用决策树进行分 ...

  6. 机器学习学习笔记之一:K最近邻算法(KNN)

    算法 假定数据有M个特征,则这些数据相当于在M维空间内的点 \[X = \begin{pmatrix} x_{11} & x_{12} & ... & x_{1M} \\ x_ ...

  7. 【转载】 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    原文地址: https://www.cnblogs.com/steven-yang/p/5686473.html ------------------------------------------- ...

  8. (数据科学学习手札13)K-medoids聚类算法原理简介&Python与R的实现

    前几篇我们较为详细地介绍了K-means聚类法的实现方法和具体实战,这种方法虽然快速高效,是大规模数据聚类分析中首选的方法,但是它也有一些短板,比如在数据集中有脏数据时,由于其对每一个类的准则函数为平 ...

  9. 02-16 k近邻算法

    目录 k近邻算法 一.k近邻算法学习目标 二.k近邻算法引入 三.k近邻算法详解 3.1 k近邻算法三要素 3.1.1 k值的选择 3.1.2 最近邻算法 3.1.3 距离度量的方式 3.1.4 分类 ...

随机推荐

  1. C++服务器与java进行socket通信案例

    分类: [java]2012-10-08 12:03 14539人阅读 评论(46) 收藏 举报 注:本代码版权所有!!!转载时请声明源地址:http://blog.csdn.net/nuptboyz ...

  2. Myeclipse项目出现红叉解决方案

    1.右键点击你的项目.选中properties 2.选中MyEclipse下的Project Facets里面的java 此时的版本号为1.5,修改 3.选中MyEclipse下的Project Fa ...

  3. matlab安装matconvnet出错总结

    在安装过程中出现两种错误: mex -settup C 出错 mex -setup C 之后, vl_complilenn出错 matconv库需要autoNN和mcnExtraLayers两个库支持 ...

  4. Wpa_supplicant 调试故障原因分析

    背景 在使用Wpa_supplicant 工具调试Linux的wifi的时候,发现有一些问题.特此记录一下.有些问题是遇到的并已经有了解决方法,一些问题比较发杂,只能作为思路. 问题以及解决办法 1. ...

  5. 小程序通过web-view实现与h5页面之间的交互

    在小程序端使用web-view内嵌网页,通过 src 携带参数,通过 @message 接收h5传回的数据 <template> <view> <web-view :sr ...

  6. docker 为镜像添加ssh服务-使用Dockerfile 创建

    首先,基于要添加内容的镜像ubuntu:18.04运行一个容器, 在宿主机(下面步骤是在容器中创建的,应该在宿主机创建进行以下步骤) 一.创建一个工作目录 二.创建Dockerfile 和脚本run. ...

  7. Http与Https协议规范

    HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1.0的第 ...

  8. .net 4.0 : Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.****'

    解决办法,添加 MicroSoft.CSharp 的引用.

  9. ORACLE添加新用户并配置权限 添加其他用户的表权限

    添加用户配置权限 1.查出表空间所在位置 ,file_name from dba_data_files order by file_id; 2.根据步骤1查出的路径.将路径替换掉并指定用户名 路径:D ...

  10. python_os 的知识点

    1. os.getcwd() #获得当前路径 2. os.listdir(path) #列出path路径下的所有目录名和文件名包括后缀 3. os.mkdir(path) #在path创建一个目录 4 ...