KNN算法


基本思想

        所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个类,就把该输入实例分类到这个类中


举例(借用大神们的图例)

   


        如上图所示,有两种类型的数据三角形和距形,待测数据为原形,需要判断原型数据是属于哪种类型的数据。 我们常说,物以类聚,人以群分,判别一个人是一个什么样品质特征的人,常常可以从他/她身边的朋友入手,所谓观其友,而识其人。我们不是要判别上图中那个绿色的圆是属于哪一类数据么,好说,从它的邻居下手。但一次性看多少个邻居呢?从上图中,你还能看到:如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。于此我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。


理论支持

   K近邻算法中通常采用多数表决的方法,即由输入实例的K个近邻的训练实例中的多数来决定输入实例的类别。

   分类函数为:fRn>{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))最大,故多数表决规则等价于经验风险最小化。


算法步骤

      输入数据: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=cisign=1,否则sign=0



实验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



优势和劣势

优势:方法简单,错误率在贝叶斯错误率和两倍贝叶斯错误率之间。

劣势:存储量和计算量大。K值的选取问题,K值过大容易造成噪声数据量大而降低分类的准确率,K值过小,得到的近邻数过少,会降低分类精度。如实验证明当K=21时有最大的准确率。



7主要应用场合

在分布式计算和并行处理方面的应用



8改进KDtree

针对如何快速搜索测试样本的K个近邻而提出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值