knn算法即为k邻近算法,是一种监督式的机器学习算法,且它是用来进行分类的。注意此算法需要和
k-means算法进行区别,因为都有个k。
工作原理是:存在一个样本数据集合,也称作训练样本集,且样本集中每个数据都存在标签,知道样本集中与所属分类的对应关系。输入没有定义的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般而言,只选取样本数据集中前k个最相似的数据,然后选择此k个最相似数据中出现次数最多的分类,作为新数据的分类。因为用于训练的数据已经具有分类,此处称为标签,所以称为“监督式学习”。
那么计算最近邻的方法一般采用欧式距离方法,也就是直接计算两个特征之间的距离,即:
A = (a1,a2),B=(b1,b2),distance = [(a1 - b1)^2+(a2-b2)^2]^0.5 这里有错误,应该是:[(a1 - a2)^2+(b1-b2)^2]^0.5 也就是两个距离的平方和的平方根。非常好用,然后将需要进行分类的数据与所有已经带有标签的训练数据一一进行距离计算,挑选出前k个距离最小的点作为与需要对测试集进行分类的点的最相似的k个数据。那么对于knn算法的核心实现,用python代码如下所示:
- def knnclassify(inX,dataSet,labels,k):
- #inX输入的分类向量,dataSet是输入的训练样本集,labels标签向量,k是选择的最近邻居的数目
- dataSetSize = dataSet.shape[0] #shape[0]表示的是行数,这里是求训练集大小
- #print dataSet.shape[1],dataSet.shape[0] #shape[1]表示的是列数
- diffMat = tile(inX,(dataSetSize,1)) - dataSet #tile用于将数组往x,y...轴扩展,比如这里因为dataSetSize为4,所以tile(inX,(dataSetSize,1))表示将inX 行扩展4次,列扩展1次,得到矩阵如下:
-
- ([0,0],
- [0,0],
- [0,0],
- [0,0])
- 将待分类向量扩展到与训练集相同的矩阵后再求
- 先往X轴扩展一倍,也就是没扩展,然后再往Y轴扩展4倍,得到如下的矩阵[[0,0],[0,0],[0,0],[0,0]]
- sqDiffMat = diffMat**2 #将每一行数组对应的差值进行平方处理
- sqDistances = sqDiffMat.sum(axis=1) #将每一行中的差值平方后进行求和处理
- distances = sqDistances**0.5 #再将每一行的平方和取平方根
- #print distances
- sortedDistIndicies = distances.argsort() #对数组按从小到大进行排序,然后按照顺序返回数据对应的下标
- classCount={}
- for i in range(k):
- voteIlabel = labels[sortedDistIndicies[i]]
- #print voteIlabel
- classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #这两行是取出与待分类样本欧式距离最小的训练集样本中的前k个样本,并统计其对应的label个数,并存储在字典classcount中。
- #print classCount.get(voteIlabel,0)
- #print classCount[voteIlabel]
- #print classCount
- sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #根据classCount的值进行排序,按照从小到大排,然后再逆序输出
- #print sortedClassCount
- return sortedClassCount[0][0] #表示取字典中的第一对键值对的值
但是在调用上述knn算法的python接口时,还需要对相关的训练数据进行预处理,主要包括要将普通文本保存的数据转化成matrix格式,即以矩阵的形式保存;然后是对数据进行规范化处理,某些不存在的数据需要用拉格朗日插值法进行添加;同时最主要的是需要将所有特征(属性)的量纲统一,能够保证所有属性在训练的时候的权重是一样的,而不会因为某些特征的值比较大,而引起因为量纲不统一所带来的问题。一般我们用
newvalue = (oldvalue - min) / (max - min)
使得所有特征值均在0-1之间,保证所有特征的权重一致。然后就可以对测试数据进行分类了,同时一般用原始数据的一部分作为训练数据,另一部分作为测试数据,然后用测试数据用训练模型进行分类,分完类后的结果和测试数据的真实结果进行对比,称之为错误率。在《机器学习实战》一书中,第二章中的关于约会数据的分类处理的模型正好是对knn算法进行归纳的一个亮点。