1 基本思想
所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个类,就把该输入实例分类到这个类中。
2 举例(借用大神们的图例)
如上图所示,有两种类型的数据三角形和距形,待测数据为原形,需要判断原型数据是属于哪种类型的数据。 我们常说,物以类聚,人以群分,判别一个人是一个什么样品质特征的人,常常可以从他/她身边的朋友入手,所谓观其友,而识其人。我们不是要判别上图中那个绿色的圆是属于哪一类数据么,好说,从它的邻居下手。但一次性看多少个邻居呢?从上图中,你还能看到:如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。于此我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。
3 理论支持
K近邻算法中通常采用多数表决的方法,即由输入实例的K个近邻的训练实例中的多数来决定输入实例的类别。
分类函数为:f:Rn—>{c1,c2,c3,...,ck}
误分类的概率是:P(Y!=f(x))=1-P(Y=f(x))
等价于:1/K*Sum(sign(yi!=ci))=1-1/K*Sum(sign(yi=ci))
要使误分类率最小,就要使Sum(sign(yi=ci))最大,故多数表决规则等价于经验风险最小化。
4 算法步骤
输入数据:T={(x1,y1),...,(xn,yn)}其中xi为实例特征向量,yi属于{c1,c2,...,ck}为实例类别,i=1,2,...,N;实例特征向量X;
输出:实例X属于类Y.
1) 根据给定的距离度量,在训练集中T找出与X最近的K个近邻,涵盖这K个点的邻域记作Nk(x);
2) 在Nk(x)中根据分类决策规则(多数表决)觉定X属于类别Y:
Y=argmaxSum(sign(yi=ci)),i=1,2,...,K
其中sign为指示函数,及当yi=ci时sign=1,否则sign=0。
5 实验matlab下实现KNN算法
实现KNN用了三个函数,K值的选取bestK,模型的训练trainknn,模型预测predictknn。
训练模型:
function [accuracy] = trainknn( train,trainlabel,test,testlabel,k)
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
[train_m,train_n]=size(train);
[test_m,test_n]=size(test);
[trainlabel_m,trainlabel_n]=size(trainlabel);
[testlabel_m,testlabel_n]=size(testlabel);
%距离矩阵dist(test_m,train_m)
for i=1:1:test_m
for j=1:1:train_m
dist(i,j)=(test(i,:)-train(j,:))*(test(i,:)-train(j,:))';
end
end
%对距离矩阵排序sortdist,记住train原有下标indexmatrix
for i=1:1:test_m
[temp,index]=sort(dist(i,:));
sortdis(i,:)=temp;
indexmatrix(i,:)=index;
end
%对每个测试数据投票表决前K个预测predictslabel
for i=1:1:test_m
sum1=0;sum2=0;sum3=0;
for j=1:1:k
if trainlabel(indexmatrix(i,j),1)==1
sum1=sum1+1;
else if trainlabel(indexmatrix(i,j),1)==2
sum2=sum2+1;
else
sum3=sum3+1;
end
end
end
temp1=[sum1,sum2,sum3];
[temp1,index1]=sort(temp1,'descend');
if index1(1,1)==1
predictlabel(i,:)=1;
else if index1(1,1)==2
predictlabel(i,:)=2;
else
predictlabel(i,:)=-1;
end
end
end
%判断准确率
sum=0;
for i=1:1:testlabel_m
if testlabel(i,1)==predictlabel(i,1)
sum=sum+1;
end
end
accuracy=sum/testlabel_m;
end
最佳K值的选取
function [ K ] = bestK( train,trainlabel,test,testlabel )
%UNTITLED3 Summary of this function goes here
% Detailed explanation goes here
[train_m,train_n]=size(train);
accuacy=0;
for k=1:1:train_m
temp=trainknn( train,trainlabel,test,testlabel,k);
if temp>accuacy
accuacy=temp;
K=k;
end
end
end
实验数据用的是heart_scale,200
个训练数据,
70
个测试样本。
最佳K值为21,此时的准确率为 0.8571。
6 优势和劣势
优势:方法简单,错误率在贝叶斯错误率和两倍贝叶斯错误率之间。
劣势:存储量和计算量大。K值的选取问题,K值过大容易造成噪声数据量大而降低分类的准确率,K值过小,得到的近邻数过少,会降低分类精度。如实验证明当K=21时有最大的准确率。
7主要应用场合
在分布式计算和并行处理方面的应用
8改进KDtree
针对如何快速搜索测试样本的K个近邻而提出。