k近邻是一种常用的监督学习方法,其工作机制非常简单:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个邻居的信息来进行预测。通常在分类任务中可以使用投票法,即选择这k个样本中出现最多的类别标记作为预测结果,在回归任务中可以使用平均法,即将这个k个样本的实值输出标记的平均值作为预测结构,还可以基于距离远近进行加权平均或加权投票,距离越近的样本权重越大。
K近邻没有显式的训练过程,是懒惰学习的著名代表,此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为0,待收到测试样本之后再进行处理,相应的,那些在训练阶段就对样本进行学习处理的方法称为急切学习。
k=1时,为最近邻算法。
k值得选择会对k近邻的结果产生重大的影响。
如果选择较小的k值,相当于用较小的领域中的训练实例进行预测,“学习”的近似误差会减小,只有与输入实例较近的训练实例才会对结果起作用,但缺点是学习的估计误差会增大,预测结果会对近邻的实例点非常敏感。如果近邻的实例点恰巧是噪声,预测就会出错。k值得减小意味着整体模型边的复杂,容易发生过拟合。
如果选择较大的k值,就相当于用较大领域中的训练实例进行预测,其优点是可以减小学习中的估计误差,但是学习的近似误差会增大,这是与输入实例较远(不相似)的训练实例也会对预测结果起作用,使得预测发生错误,k值得增大就意味着整体的模型变得简单。
k值一般选取一个比较小的数值,通常采用交叉验证法来选取最优的k值。
代码实现如下:
# 代码主要来自于机器学习实战一书,https://github.com/AnnDWang/MachineLearning/blob/master/thirdbook/ch2/kNN.py
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
def classify0(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1)
distances=sqDistances**0.5
sortedDistIndices=distances.argsort()
classCount={}
for i in range (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]
# group,labels=createDataSet()
# classify0([0,0],group,labels,3)
# 将文本记录转换为Numpy的解析程序
def file2matrix(filename):
fr=open(filename)
arrayOLines=fr.readlines()
numberOfLines=len(arrayOLines)
returnMat=zeros((numberOfLines,3))
classLabelVector=[]
index=0
for line in arrayOLines:
line=line.strip()
listFromLine=line.split('\t')
features=[float(i) for i in listFromLine[0:3]]
returnMat[index,:]=features
classLabelVector.append(int(listFromLine[-1]))
index+=1
return returnMat,classLabelVector
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')