介绍
kNN全称为k-nearest neighbors,是模式识别中比较简单的一种算法,可以用于分类和回归。使用时,输入的训练样本带有标签,输出根据是用于分类还是回归:
分类:
分类问题的输出为:找出K个和要预测对象最近邻的样本,这K个样本中,“大多数”属于哪一类即为预测对象的分类标签。
回归:
回归问题的输出为:找出k个和回归对象最邻近的样本,这k个样本的标签的”平均值“即为要回归对象的标签。
算法
算法的训练样本为一个带有标签的样本集合,输入新的数据后,将新的数据和集合中每个样本进行对比,找出前k个最邻近的样本,这k个最近邻的样本中,出现次数最多的标签即为新数据的标签(或标签平均值即为回归数据的新标签)。
近邻准则
对于样本间的“距离”,不同类型数据有不同准则。例如连续数据常常采用欧式距离,二进制编码的数据常常采用汉明距离。机器学习中,数据间“距离”度量可以按考漫谈:机器学习中距离和相似性度量方法。
归一化
对于不同的特征,量化后的数值大小可能不一样。如果直接使用量化后的数值,可能会对结果造成影响,为了使不同特征对结果影响“公平”,要对数据进行归一化。可以将输入数据限定的某一范围,例如[-1, 1]或[0, 1]。例如将数据量化为[0, 1]之间:
如果不对所有特征“一视同仁”,可以给特征加权重。
如何选择k的大小
k值得大小直接影响算法效果。如果k值比较小,相当于只是用了样本中较少的数据进行了“训练”,容易产生过拟合,误差过大。如果k值比较大,相当于和估计数据不相近的样本也参与了预测,造成模型偏差过大。维基百科给出的参考为Hyperparameter optimization,其具体例子为交叉验证。一个经验为:k一般低于训练样本数的平方根。
kNN优缺点
优点
1、knn算法比较简答, 易于理解,且容易实现。
2、适合多类分类问题。
缺点
1、计算量比较大,对于每一次预测,都要计算所有样本的距离。
2、样本不均衡,预测结果不准确。
kNN实现
《机器学习实战》中给出了Python的实现,不同需求,特征量化、实现不同,但是原理一样。
inX为输入数据,dataSet为训练样本,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
sortedDistIndicies = distances.argsort() #argsort(0返回数组从小到大的索引
classCount={} //用字典来计数标签个数
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]//找到标签
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#标签个数+1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)//标签个数重新排序,并reverse,此时排在最前头的即为出现次数最多的
return sortedClassCount[0][0]