一.KNN算法介绍
KNN,全称k-NearestNeighbor。
KNN算法的核心思想是:未标记样本的类别由距离其最近的K个邻居投票来决定。KNN算法可解决分类或者回归问题。由其思想可以看出,KNN是通过计算不同特征值之间的距离进行分类,而且在决策样本类别时,只参考样本周围k个“邻居”样本的所属类别。因此比较适合处理样本集存在较多重叠的场景,KNN算法主要用于聚类分析、预测分析、文本分类、降维等,也常被认为是简单数据挖掘算法的分类技术之一。
1、算法原理
k-近邻算法基于某种距离度量来找到输入样本在训练集中的k个最近邻居,并且根据这k个邻居的属性来预测输入样本的属性。
比如我们的输入样本是图中的蓝色,那么k个近邻就是距离绿色小圆最近的k个邻居,然后在这k个邻居中,若黑色小圆的数量多于红色小圆,那么输入样本的属性就与蓝黑色小圆相同,反之则与红色小圆的属性相同,这就是k-近邻算法的算法思想。
2. 分析:K 值的影响
如果k值比较小,相当于我们用较小的领域内的训练样本对实例进行预测。这时,算法的近似误差(Approximate Error)会比较小,因为只有与输入实例相近的训练样本才会对预测结果起作用。但是,它也有明显的缺点:算法的估计误差比较大,预测结果会对近邻点十分敏感,也就是说,如果近邻点是噪声点的话,预测就会出错。因此,k值过小容易导致KNN算法的过拟合。
同理,如果k值选择较大的话,距离较远的训练样本也能够对实例预测结果产生影响。这时候,模型相对比较鲁棒,不会因为个别噪声点对最终预测结果产生影响。但是缺点也十分明显:算法的近邻误差会偏大,距离较远的点(与预测实例不相似)也会同样对预测结果产生影响,使得预测结果产生较大偏差,此时模型容易发生 欠拟合。
因此,在实际工程实践中,我们一般采用交叉验证的方式选取 k 值(以下第三节会介绍)。通过以上分析可知,一般 k 值选得比较小,我们会在较小范围内选取 k 值,同时把测试集上准确率最高的那个确定为最终的算法超参数 k 。
3、算法优缺点
优点:
- 准确度较高:K近邻算法准确度较高为它可以适应不同的数据分布。
- 适用性广泛:K近邻算法可用于分类和回归问题,同时也支持多分类和多回归问题。
- 实现简单:K近邻算法的实现非常简单,特别适用于初学者学习模式识别的入门算法
缺点:
- 计算复杂度高:当数据集很大时,计算距离的时间和空间开销都会很大,影响算法执行效率。
- 受样本分布影响大:K近邻算法对训练集中样本的密度很敏感,对于密度相差很大的数据集,分类精度会受到较大影响。
- 数据不平衡问题:当训练集中某些类别的样本数目远远大于其他类别的样本数目时,K近邻算法的准确度会明显下降。
-
二、python代码实现
备注:数据集使用sklearn中的鸢尾花数据集
-
# -*-coding:utf8 -*-
'''
author:RongGong
'''
from sklearn import datasets
import numpy as np
import operator
#设置随机种子,不设置的话默认是按系统时间作为参数,
#因此每次调用随机模块时产生的随机数都不一样设置后每次产生的一样
np.random.seed(0)#1.导入鸢尾花的数据集
iris = datasets.load_iris()
#样本数据150*4二维数据,代表150个样本,
#每个样本4个属性分别为花瓣和花萼的长、宽
iris_x = iris.data
#长150的一维数组,样本数据的标签
iris_y = iris.target
#permutation接收一个数作为参数(150),产生一个0-149一维数组,
#只不过是随机打乱的,
#当然也可以接收一个一维数组作为参数,结果是直接对这个数组打乱
indices = np.random.permutation(len(iris_x))#选取140个数据作为训练集
iris_x_train = iris_x[indices[:-10]]
iris_y_train = iris_y[indices[:-10]]#选择10个数据作为测试集
iris_x_test = iris_x[indices[-10:]]
iris_y_test = iris_y[indices[-10:]]def classfy0(inX,dataSet,labels,k):
dataSetSize = dataSet.shape[0]
diffMat = np.tile(inX,(dataSetSize,1))-dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount={}
for i in range(k):
voteLabel = labels[sortedDistIndicies[i]]
classCount[voteLabel] = classCount.get(voteLabel,0)+1
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]#调用classfy0()进行预测
errorCount = 0
print("预测结果:")
for i in range(10):
predictRes = classfy0(iris_x_test[i],iris_x_train,iris_y_train,3)
print(predictRes)
if (predictRes != iris_y_test[i]): errorCount += 1print("真实分类结果:")
print(iris_y_test)print("准确率:")
print(1-errorCount/len(iris_y_test)) -
-
三、实验结果分析
KNN是一种基于实例的学习算法,它根据训练样本的特征和对应的类别标签,通过计算测试样本与训练样本之间的距离来进行分类预测。本次实验使我们了解了K近邻算法的基本原理,概念模型以及算法流程,学会了如何使用KNN算法来解决一些简单的分类问题,