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

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. 前端学习笔记系列一:13new Date()的参数

    前两天发现手机页面的倒计时在Android上正常显示,在iPhone却不能显示. 后来又发现在ff和ie里也不显示.(以前只在chrome里看过,显示正常). 后来同事改了new Date()里字符串 ...

  2. 【富文本、JS】将接口传来的全部纯URL替换为富文本插件能识别到的img标签

    replaceURLWithImage (text) { var a = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0 ...

  3. 做一个php登陆页面,用pc登陆和用手机登陆弹出来的登陆页面不一样。

    <?phpheader('Content-Type:text/html; charset=UTF-8');//定义页面编码为utf8$is_pc = (strpos($agent, 'windo ...

  4. 多元线性回归算法的python底层代码编写实现

    1.对于多元线性回归算法,它对于数据集具有较好的可解释性,我们可以对比不过特征参数的输出系数的大小来判断它对数据的影响权重,进而对其中隐含的参数进行扩展和收集,提高整体训练数据的准确性. 2.多元回归 ...

  5. 记一次菜鸡的低级折腾--WordPress get Webshell(后台文件编辑插马)

    挺简单的一个测试站,开始思路错了,一直去网上找WordPress的漏洞,看有没有什么能利用的,未果,因为这个测试站有些地方并不完善,有的漏洞利用不了,菜鸡的我连弱口令都没猜对,没知识就是这么悲哀. 下 ...

  6. Ternsorflow 学习:005-MNIST入门 实现模型

    前言 在上一讲中,我们通过分析选用了softmax模型,并用tf创建之.本讲的内容就是为了训练这个模型以便于测试. 训练模型 为了训练我们的模型,我们首先需要定义一个指标来评估这个模型是好的.其实,在 ...

  7. Timetable CodeForces - 946D (预处理+背包)

    题意:n天m节课,最多可以逃k节课,每天在学校待的时间为该天上的第一节课到最后一节课持续的时间.问怎样逃课可以使这n天在学校待的时间最短,输出最短的时间. 分析: 1.预处理出每天逃j节课时在学校待的 ...

  8. 008.Oracle数据库 , 判断字段内容是否为空

    /*Oracle数据库查询日期在两者之间*/ SELECT PKID, OCCUR_DATE, ATA FROM LM_FAULT WHERE ( ( OCCUR_DATE >= to_date ...

  9. Word 写论文的一些教训和经验

    参考文献 写正文时就在引用位置添加参考文献的title,写完后,在百度学术或谷歌学术中搜索参考文献获取GB/T 7714的参考格式,在参考文献的章节为文献编号,在引用位置插入交叉引用. 插图 可以先在 ...

  10. ListView的DrawSubItem时间添加边框,字体变粗问题

    procedure TFrmrdp.ListView1AdvancedCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubIt ...