kNN算法的伪代码如下:
- 计算当前点与已知类别的数据集的每个点的距离 距离公式为d=[(x-x₀)²+(y-y₀)²]½
- 按照求得的距离按递增排序 argsort() 排序
- 选取与当前点距离最小的k个点
- 确定选取的这k个点所在类别的出现频率
- 返回这k个点出现频率最高的类别作为当前点的预测分类
1. 其python代码具体如下:
# coding=utf-8 from numpy import * import operator def kNNclassify(currpoint,dataSet,labels,k): #currpoint为当前点的坐标转换成的数组,dataset为已知类别的数据集,label类别标签,k为最近点的数目 dataSetSize=dataSet.shape[0] #得到数据集的行数 diffMat=tile(currpoint,(dataSetSize,1))-dataSet #tile函数把当前点的数组扩充为与数据集相同行数、相同列数的数组,以便做差 sqDiffMat=diffMat**2 #对做完差之后的数组进行每个元素的平方,比如[1,2]**2=[1,4] sqDistances=sqDiffMat.sum(axis=1) #把数组按列相加,比如[[2,4],[2,3]]---->[[6],[5]] distance=sqDistances**0.5 #把得到的结果开方 sortedDisIndicies=distance.argsort() #argsort()按从大到小排列后,返回的结果是元素的序号,sortedDisIndicies是一个列表 classCount={} #定义一个空的字典,保存选取的k个临近点的类别,其中“键”是这k个点的类别,“值”是类别出现的数目 for i in range(k): #循环,取出这k个临近点 votelabel=labels[sortedDisIndicies[i]] #把这k个点的类别存到votelabel列表中,votelabel列表保存的全是类别名 classCount[votelabel]=classCount.get(votelabel,0)+1 #字典中的get函数判断该字典中有没有“键”votelabe,①如果没有,把这个键存到字典中,该“键”对应的值赋值为0,括号里面的0只是初始化,尔后无作用,②如果有这个“键”,那么返回该键对应的“值” sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #classCount.items()将classCount字典分解为元组列表,operator.itemgetter(1)按照第二个元素的次序对元组进行排序,reverse=True是逆序,即按照从大到小的顺序排列,sortedClassCount是元组构成的列表 return sortedClassCount[0][0] #返回出现次数最多的类别
2. 实例应用:判断一部电影是爱情片还是动作片,这里我们把爱情片用'A'表示,‘B'用动作片表示
每部电影的打斗镜头数、接吻镜头数及电影评估类型 电影名称 打斗镜头数 接吻镜头数 电影类型 乡村爱情故事 3 104 爱情片(A) 来自星星的你 2 100 爱情片(A) 太阳的后裔 1 81 爱情片(A) 战狼 101 10 动作片(B) 碟中谍 99 5 动作片(B) 复仇者联盟 98 2 动作片(B) 同桌的你 18 90 ?
3. 根据表格创造出数据集及标签向量:
def creatDataSet(): dataSet=array([[3,104],[2,100],[1,81],[101,10],[99,5],[98,2]]) labels=array(['A','A','A','B','B','B']) currpoint=array([18,90]) #当前点 return dataSet,labels,currpoint
4. 函数调用即实例化
dataSet,labels,currpoint=creatDataSet() result=kNNclassify(currpoint,dataSet,labels,3) print(result)
5. 输出结果
C:\Users\Anaconda3\python.exe C:/Users/PycharmProjects/machine_learning/快速数据分析/测试.py A Process finished with exit code 0
从结果来看,该电影属于A类别,也就是属于爱情片。