k近邻算法概念:是常见的用于监督学习的算法。
k近邻算法的原理:给定测试样本,基于某种距离找到训练集中与其最近的 K 个训练样本,然后基于这 K 个邻居的信息来预测。
K值的选择:
①如果选择较小的K值,就相当于用较小的领域中的训练实例进行预测,“学习”近似误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是“学习”的估计误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
②如果选择较大的K值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
③K=N,则完全不足取,因为此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的累,模型过于简单,忽略了训练实例中大量有用信息。
但是在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法(简单来说,就是一部分样本做训练集,一部分做测试集)设定不同的K来做多次测试,从而来选择最优的K值。
k-近邻算法的一般流程:
①收集数据:可以使用任何方法。
②准备数据:距离计算所需要的数值,最好是结构化的数据格式。
③分析数据:可以使用任何方法。
④训练算法:此步骤不适用于k-近邻算法。
⑤测试算法:计算错误率。
⑥使用算法:首先需要输入样本数据和结构化输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。
k近邻算法的应用:
①KNN可以用于分类问题:投票法,选择K个邻居中出现次数最多的类别作为预测结果。
②可以用于回归问题:可使用平均法,即将K个邻居的标记的平均值作为预测输出。也可以使用基于距离的加权平均,比如把距离的倒数作为权重进行加权运算。
knn算法的实现:
knn算法实现的大概步骤:
(1)分别计算已知类别数据的点到当前点(未知类别)之间的距离,通常选用欧式距离,当然也可以使用其他距离来进行计算。
(2)按照距离将已知类别的点进行从小到大排序。
(3)选取距离当前点最近的前k个点,并统计前k个点中各个类别出现的频率。
(4)返回前k个点中出现频率最高的类别,以此作为当前点的预测类别。
实现代码:
from numpy import *
import operator
import matplotlib.pyplot as plt"""
函数说明:创建数据集
"""
def createDataSet():
group=array([[1,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group, labels"""
函数说明:knn分类器,找到距离inX最近的前k个样本
"""
def classify(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(inX,(dataSetSize,1))-dataSet #tile,用于计算出已知点到当前点的距离
sqDiffMat=diffMat2
sqDistances=sqDiffMat.sum(axis=1) #横向求和
distances=sqDistances0.5
sortedDistIndices=distances.argsort() #从小到大进行排序
classCount={}
for i in range(k): #统计前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]if name == 'main':
group,labels=createDataSet()
print("group:\n",group,'\n',"labels:\n",labels)
#绘制图像
fig=plt.figure() #创建画布
ax=fig.add_subplot(111) #添加子图,并获取坐标轴
ax.scatter(group[:,0],group[:,1],c='b',marker='o') #通过坐标轴添加散点图
ax.scatter(0,0,c="r",marker='*')
plt.show() #显示图像
result = classify([0,0],group,labels,3)
print("预测结果为:",result)
实现效果:
总结:
优点
1.可以处理分类问题,算法简单易懂
2.可以免去训练过程
3.knn还可以处理回归问题,也就是预测
缺点
1.效率低,每一次分类都要对训练数据进行计算
2.对训练数据依赖度特别大,过拟合、欠拟合问题难以权衡
3.存在维数灾难问题