机器学习——KNN算法简介

邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
  在这里插入图片描述
  上图中,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。
  KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成反比。
  
KNN算法的计算流程

  1. 计算已知类别数据集中的点与当前点之间的距离;
  2. 按照距离递增次序排序;
  3. 选取与当前点距离最小的k个点;
  4. 确定前k个点所在类别的出现频率;
  5. 返回前k个点所出现频率最高的类别作为当前点的预测分类。

python中的相关库

import numpy as np 
import operator
from os import listdir

numpy是python的数值计算扩展库,用numpy会使一些数组,向量类的计算更加简便。
operator是操作符扩展库
listdir提供了可以查看目录文件列表的函数

在kNN.py中,添加一个函数classify0作为kNN算法的核心函数,该函数的完整形式为:
def classify0(inX, dataSet, labels, k):
其中各个参数的含义如下:

  • inX - 用于要进行分类判别的数据(来自测试集)
  • dataSet - 用于训练的数据(训练集)
  • lables - 分类标签
  • k - kNN算法参数,选择距离最小的k个点

在上述参数列表中,dataSet为所有训练数据的集合,也就是表示所有已知类别数据集中的所有点,dataSet为一个矩阵,其中每一行表示已知类别数据集中的一个点。inX为一个向量,表示当前要判别分类的点。按照上述算法流程,我们首先应该计算inX这个要判别分类的点到dataSet中每个点之间的距离。dataSet中每个点也是用一个向量表示的,求两向量之间的距离。

欧氏距离,曼哈顿距离,切比雪夫距离,闵可夫斯基距离,标准化欧氏距离,马氏距离,夹角余弦,汉明距离,杰卡德距离& 杰卡德相似系数,信息熵

欧氏距离是最简单的距离计算方法
在这里插入图片描述
classify0的实现如下,使用numpy会使计算更加方便。

def classify0(inX, dataSet, labels, k):
    ### Start Code Here ###
    #返回dataSet的行数,即已知数据集中的所有点的数量
    #行向量方向上将inX复制m次,然后和dataSet矩阵做相减运算
    #减完后,对每个数做平方
    #平方后按行求和,axis=0表 示列相加,axis-1表示行相加
    #开方计算出欧式距离
    #对距离从小到大排序,注意argsort函数返回的是数组值从小到大的索引值2 
    #用于类别/次数的字典,key为类别, value为次数
    #取出第近的元素对应的类别
    #对类别次数进行累加
    #根据字典的值从大到小排序
    #返回次数最多的类别,即所要分类的类别
    ### End Code Here ###

具体实现方法:

import numpy as np
import operator
from os import listdir
def classify0(inX, dataSet, labels, k):
	m=dataSet.shape[0]  #返回dataSet的行数,即已知数据集中的所有点的数量
	diffMat=np.tile(inX,(m, 1))-dataSet #行向量方向上将inX复制m次,然后和dataSet矩阵做相减运算
	sqDiffMat = diffMat**2 #减完后,对每个数做平方
	sqDistances = sqDiffMat.sum(axis=1) #平方后按行求和,axis=0表 示列相加,axis-1表示行相加
	distances = sqDistances *0.5 #开方计算出欧式距离
	sortedDistIndices = distances.argsort() #对距离从小到大排序,注意argsort函数返回的是数组值从小到大的索引值2 
	classCount = {} #用于类别/次数的字典,key为类别, value为次数  
	for i in range(k):
		voteIlabel = labels[sortedDistIndices[i]] #取出第近的元素对应的类别
		classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #对类别次数进行累加
	sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #根据字典的值从大到小排序
	return sortedClassCount[0][0]  #返回次数最多的类别,即所要分类的类别

KNN算法的优点

  1. 简单,易于理解,易于实现,无需估计参数,无需训练;
  2. 适合对稀有事件进行分类;
  3. 特别适合于多分类问题, KNN比SVM的表现要好。

KNN算法的缺点

  1. 懒惰算法,对测试样本分类时的计算量大,内存开销大,评分慢;
  2. 当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数;
  3. 可解释性较差,无法给出决策树那样的规则。

KNN算法常见的问题
k值的设定
  k值选择过小,得到的近邻数过少,会降低分类精度,同时也会放大噪声数据的干扰;而如果k值选择过大,并且待分类样本属于训练集中包含数据数较少的类,那么在选择k个近邻的时候,实际上并不相似的数据亦被包含进来,造成噪声增加而导致分类效果的降低。
类别的判定方式
  投票法没有考虑近邻的距离的远近,距离更近的近邻也许更应该决定最终的分类,所以加权投票法更恰当一些。
距离度量方式的选择
  高维度对距离衡量的影响:众所周知当变量数越多,欧式距离的区分能力就越差。  
变量值域对距离的影响
  值域越大的变量常常会在距离计算中占据主导作用,因此应先对变量进行标准化。
性能问题
  kNN是一种懒惰算法,而懒惰的后果:构造模型很简单,但在对测试样本分类地的系统开销大,因为要扫描全部训练样本并计算距离。已经有一些方法提高计算的效率,例如压缩训练样本量等。

参考:
1.哈林顿,李锐. 机器学习实战 : Machine learning in action[M]. 人民邮电出版社, 2013.
2.周志华. 机器学习:Machine learning[M]. 清华大学出版社, 2016.
3.百度百科

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值