KNN算法
KNN(k-nearest-neighbour)是数据挖掘领域的基本算法之一,原理比较简单,在各类别均衡、样本容量比较大的情况下比较实用。
算法原理
算法以样本间的距离作为相似性测度。在同一测量空间中以测试样本为中心,检测一定范围内的k个样本类别,用“投票法”得出测试样本的类别。
#设k为离测试样本最近的样本数,d为数据集
for 数据集中的每条数据 do
计算其余所有点与样本点距离
对距离从小到大排序,取前k个
计算k个样本中出现最多的类别,将它赋给测试样本
end for
有必要关注的地方有三点:
距离的量度
欧式距离很常用,但是它忽略了量纲的影响。两点之间的欧式距离与测量单位有关,所以当不同分量的量纲不同时需要进行标准化处理。
明氏距离是对欧式距离的扩展,当p=2时二者相同。
马氏距离考虑了量纲的影响,据此得出的距离与测量单位无关。
根据实际情况可以针对不同类别样本对测试样本距离的影响赋予不同的权值,这样可以减少错误率。对于文本数据挖掘,常用夹角余弦作为相似性测度。
k的取值
因为样本类别由k个样本决定,所以k的取值在算法中显得十分重要。当k较小时样本点太少,容易受到噪声的影响。当k较大时分类精度会下降,错分的概率上升。
根据经验,k低于训练样本数的平方根。
效率
由于需要对每一个点进行全数据集的检索,本算法的效率比较低,k越大,数据量越大越是如此。当然在一些比如说数据集是一个稀疏矩阵的情况下可以改进数据存储算法,相对于暴力求解距离,可以采用kd树或者ball树来改进提高检索效率。
特点
该算法属于消极学习法,是基于实例的学习。优点在于易于理解,无需建模。缺点在于花费较大,不像决策树那样可解释性不强。
实现
下面是用R的简单实现,采用暴力求解:
#KNN
#x is train data,k is the number of neighbors
#return the labels of testdata
KNN <- function(x,testdata,k) {
nearestNeighbor <- matrix(NA,nrow = k,ncol = 3,byrow = T,
dimnames = list(1:k,c("index","label","distance")))
distance<-0
label<-0
for(i in seq(testdata[,1])) {
for(j in seq(x[,1])) {
tempDistance <- sqrt(sum((testdata[i,] - x[j,-1])^2))
distance<-c(distance,tempDistance)
}
distance<-distance[-1]#得到第i个记录与其他所有记录的距离
for(g in seq(k)) {#找到最近的k个变量,按距离从小到大排列
nearestNeighbor[g,]<-c(which.min(distance),x[which.min(distance),1],distance[which.min(distance)])
distance<-distance[-which.min(distance)]
}
label<-c(label,names(which.max( table(nearestNeighbor[,2]) )))
distance<-0
}
label<-label[-1]
}
参考
【1】【欧式距离与马氏距离区别】
http://blog.csdn.net/u010167269/article/details/51627338?_t_t_t=0.0028043033089488745
【2】【模式识别相似性测度距离】
http://blog.csdn.net/whu_zcj/article/details/50772750
【3】《数据挖掘导论》
【4】【kd树算法思路】
http://www.360doc.com/content/16/1003/00/36492363_595405515.shtml