一。工作原理
存在一个样本数据集合,也称作训练样本数据集,并且样本集中每个数据都存在标签,机我们知道样本集中每一个数据所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般呢来说,我们只选择样本数据集中前k个最相似 的数据,选择k个最相似数据中出现次数最多的分类,作为新数据的分类,
二。概述(伪代码)
(1)计算已知类别数据集中的点与当前点之间的距离
(2)按照距离递增次序排序
(3)选取与当前点距离最小的k个点
(4)确定前k个点所在 的类别的出现的频率
(5)返回前k个点出现频率最高的类别作为当前点的类别
三。KNN注意事项
1.k的值应当根据实际情况进行取值。如果K过大可能导致计算机运行时间过长,并且可能导致欠拟合的情况;如果K的值过小,可能导致过拟合。
2.计算样本之间的距离可以使用不同的函数,例如欧式距离,曼哈顿距离等等。
欧式距离:
曼哈顿距离:
四。KNN基础代码
1.引用库
from numpy import *
import operator
import numpy as np
2.创建训练集
def createDataSet():
group=array([[1.0,1.1],[1.0,1.1],[0,0],[0,0.1]])
#创建二维数组,表示点在坐标系上的距离
labels = ['A','A','B','B']
#表示不同点代表的不同类别
return group,labels
3.KNN算法
def classify0(inx,dataSet,labels,k):
#本次使用了欧式距离计算了点之间的距离
dataSetSize=dataSet.shape[0]
#获取dataSet的行数
diffMax=np.tile(inx,(dataSetSize,1))-dataSet
#tile函数的作用是将输入的数组或矩阵沿指定的轴进行重复拓展。其中,(dataSetSize, 1)表示将inx进行重复的次数。在这里,inx是一个一维数组,(dataSetSize, 1)表示将inx在行方向上重复 dataSetSize 次,在列方向上重复 1 次。
#diffMax计算了 inx 与 dataSet 中每个样本的差异,即将inx扩展为和dataSet相同尺寸的数组,并逐元素相减,得到差异矩阵。
sqDiffMat=diffMax**2
#差异矩阵的平方
sqDistances=sqDiffMat.sum(axis=1)
#sqDiffMat.sum(axis=1) 将对 sqDiffMat 中的每一行进行求和,生成一个新的一维数组 sqDistances,该数组的长度与 sqDiffMat 的行数相同。
#这一步的目的是计算每个样本与输入向量 inx 之间的差异的平方和,即沿着列方向求和。
distances=sqDistances**0.5
#平方根
sortedDistIndicies=distances.argsort()
#argsort()函数是对distances进行排序,并返回排序后的索引值即【2,3,0,1】
classCount={}
#字典
for i in range (k):
voteIlabel=labels[sortedDistIndicies[i]]
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
#classCount为字典,voteIlabel作为键值,classCount.get(voteIlabel,0)是一个字典的方法,用于获取字典中以voteIlabel作为键的对应值。如果键存在,则返回对应的值,如果键不存在则创建该键并返回默认值0
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#classCount.items() 返回一个由字典的键值对组成的可迭代对象。
#sorted() 是 Python 内置函数,用于对可迭代对象进行排序。通过指定 key=operator.itemgetter(1),表示按照每个键值对的第二个元素(即值)进行排序。
#reverse=True 表示按照降序排列。
return sortedClassCount[0][0]
4.调用KNN进行实验
#开始调用KNN算法
group,labels=createDataSet()
print("(0,0)点的类别为"+classify0([0,0],group,labels,3))
5.调用KNN的过程中的数据验算(可以不看)
根据给定的代码,当调用 print(classify0([0,0],group,labels,3))
时
步骤如下:
-
根据
createDataSet()
函数,得到group
和labels
的值,分别为[[1.0, 1.1], [1.0, 1.1], [0, 0], [0, 0.1]]
和['A', 'A', 'B', 'B']
。 -
在
classify0()
函数中,输入向量inx
为[0, 0]
,数据集dataSet
为group
。 -
计算
diffMax
,即np.tile(inx, (dataSetSize, 1)) - dataSet
,其结果为[[[-1.0, -1.1]], [[-1.0, -1.1]], [[0, 0]], [[0, -0.1]]]
。 -
计算
sqDiffMat
,即diffMax**2
,其结果为[[[1.0, 1.21]], [[1.0, 1.21]], [[0, 0]], [[0, 0.01]]]
。 -
沿着轴1求和,即
sqDiffMat.sum(axis=1)
,其结果为[2.21, 2.21, 0, 0.01]
。 -
计算平方根,即
sqDistances**0.5
,其结果为[1.486, 1.486, 0.0, 0.1]
。 -
对
distances
进行排序,并返回排序后的索引,即distances.argsort()
,其结果为[2, 3, 0, 1]
。 -
根据参数
k=3
,统计前k
个最近邻样本的标签,并记录它们出现的次数,结果为{'B': 2, 'A': 1}
。