k-近邻算法的原理:给定训练样本及对应的标签,然后计算输入样本和训练样本的欧式距离,进行升序排列,找出前k个距离最小的点,然后确定各类别出现的频数,把频数最大的那个类别当做当前输入样本的预测类。
伪代码如下:
(1)计算输入样本与训练样本之间的距离;
(2)按照距离进行升序排列;
(3)选取距离最小的前k个点;
(4)确定前k个点中,类别出现的频数;
(5)返回前k个点钟频数最高的类别当做对输入样本的预测类。
Python3.5写的代码如下:
注意:在Python3.5中,sorted的第一个参数应该用.items(),在Python2中用.iteritems()
iteritems()
返回的是一个能遍历所有键值对的生成器
items()
返回的是整个列表中的键值对的拷贝,在你的dict比较大的情况下会消耗大量内存
性能没比较过,你自己试试?(我猜生成器性能更好)
python3里面的items()
改成了iteritems()
的行为然后删除了iteritems()
from numpy import * import operator#建立训练样本和相应的标签def createDataSet(): group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) labels=['A','A','B','B'] return group, labels#inX:要进行分类的输入向量#dataSet:训练样本集#labels:标签向量#k:选择近邻的数目def classify0(inX,dataSet,labels,k): dataSetSize=dataSet.shape[0] #得到数组的行数,即有几个训练数据 diffMat=tile(inX,(dataSetSize,1))-dataSet #求差值。tile将要分类的向量变成一个dataSetSize行,1列的向量 sqDiffMat=diffMat**2 #各元素的平方 sqDistances=sqDiffMat.sum(axis=1) #把每一行相加,得到每一个距离的平方 distances=sqDistances**0.5 #开方,得到距离 sortedDistIndicies=distances.argsort() #升序排列,返回的是下标 #存放最终的分类结果及相应的结果投票数 classCount={} #投票过程,就是统计前k个最近的样本所属类别包含的样本个数 for i in range(k): voteIlabel=labels[sortedDistIndicies[i]] #样本对应的分类结果 classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 #返回所在类别的频率,如果字典中有该键值,则返回对应的值;若没有,则返回0;最后加1得到频率 #从最大到最小排序,返回得票数最多的分类结果 sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #items()返回由元组组成的列表;key接收一个参数,itemgetter是operator的属性,从列表中提取关键字进行比较,reverse为true,表示升序排列。 return sortedClassCount[0][0]group,labels=createDataSet()b=classify0([0,0],group,labels,3)print(b) #输出为B