最近邻分类器及MATLAB实现

来源:互联网 发布:上门安装windows系统 编辑:程序博客网 时间:2024/06/06 15:52

应用背景:在前面一些图像处理相关的文章中,已经说到图像的特征提取,在选择好一些主要特征之后,那么我们用这些特征做什么用呢,我们的主要目的是利用这些特征对图像进行分类。接下来的问题是怎么分类,这里介绍最近邻分类,它是一种最简单的分类方法。

基本思想:最近邻分类,顾名思义,距邻居最近,则与邻居同类。也就是说,一个待分类的单个样本A,放入已分好类的多个样本群Q中,从Q中选择kA的邻居,通过计算A与邻居之间的某种关系后得出A与这k个邻居最相似,那么就把A分为这k个邻居中出现次数最多的类,因此最近邻分类也称k最近邻分类(k  nearest  neighbor,  KNN)。这种分类方法基本分类3步:1、找待分类样本与已分类样本之间的关系,这里指计算它们之间的距离;2、找距离最近的k个已分类的样本;3、分类,从这k个样本中找出出现次数最多的类,那么待分类样本属于该类。

数学原理:在特征空间中,把每个类的所有样本的平均值表示为该类,则第i类样本的均值为:

                                                                                                          (1)

其中,Ni为第i类样本的样本数目,Wi为第i类样本集合,W为总类别数目。

样本之间的距离取欧氏距离,当对一个未知模式 x 进行分类时,需要分别计算 x 与各个类的欧氏距离,如下式所示

                                                                                                     (2)

其中,|| x-mi ||=((x-mi)^T(x-mi))^1/2,表示欧几里得范数,即向量的模。

MATLAB实现

算法伪代码如下

        initialize  Di(x)=max

        for   i=1:w

                  Di(x)=|| x-mi ||

        end

        find k neighbors of  x

        find  max_Di(x) in k neighbors of  x      

        for   i=1:w

                  if  Di(x)<max_Di(x)

                  i is the neighbors of  x

        end

        count the number of classes in the k nearest neighbors

MATLAB代码如下

二维平面两类分类问题:

clear;k=9;       % 最近邻居的数目num_po=100;            x11=rand(num_po,1);x12=rand(num_po,1);x1=[x11 x12];  y1=ones(num_po,1);     num_ne=100;            x21=rand(num_ne,1)+1;x22=rand(num_ne,1);    x2=[x21 x22];y2=-1*ones(num_ne,1);   x=[x1;x2];y=[y1;y2];ClassLabel=unique(y);num_t=20;                    % 测试样本test1=rand(num_t,1)+0.5;test2=rand(num_t,1);test=[test1 test2];        for num=1:num_t    for i=1:(num_po+num_ne)        dis(i)=norm(test(num,:)-x(i,:));    end    [dis_s,index]=sort(dis);    cnt=zeros(1,2);    for j=1:k        ind=find(ClassLabel==y(index(j)));        cnt(ind)=cnt(ind)+1;    end    [m,ind]=max(cnt);    y_test(num)=ClassLabel(ind);% 测试样本的标记endfor i=1:(num_po+num_ne)         % 训练样本图示    if y(i)>0        plot(x(i,1),x(i,2),'r+');        hold on    else        plot(x(i,1),x(i,2),'b.');        hold on    endendfor i=1:num_t                   % 测试样样本图示    if y_test(i)>0        plot(test(i,1),test(i,2),'g+');        title('K-最近邻分类器');        hold on    else        plot(test(i,1),test(i,2),'y.');        hold on    endend

运行结果如下



对于二维平面两类分类问题,每个训练样本都有一个距离必须度量,数据计算量过大,耗费大量时间。

下面的例子使用样本数据的均值来代表类

%鸢尾花属植物数据集%花萼长度 花萼宽度 花瓣长度 花瓣宽度 属种yuanwei_data=[5.1,3.5,1.4,0.2,14.9,3.0,1.4,0.2,14.7,3.2,1.3,0.2,14.6,3.1,1.5,0.2,15.0,3.6,1.4,0.2,15.4,3.9,1.7,0.4,14.6,3.4,1.4,0.3,15.0,3.4,1.5,0.2,14.4,2.9,1.4,0.2,14.9,3.1,1.5,0.1,15.4,3.7,1.5,0.2,14.8,3.4,1.6,0.2,14.8,3.0,1.4,0.1,14.3,3.0,1.1,0.1,15.8,4.0,1.2,0.2,15.7,4.4,1.5,0.4,15.4,3.9,1.3,0.4,15.1,3.5,1.4,0.3,15.7,3.8,1.7,0.3,15.1,3.8,1.5,0.3,15.4,3.4,1.7,0.2,15.1,3.7,1.5,0.4,14.6,3.6,1.0,0.2,15.1,3.3,1.7,0.5,14.8,3.4,1.9,0.2,15.0,3.0,1.6,0.2,15.0,3.4,1.6,0.4,15.2,3.5,1.5,0.2,15.2,3.4,1.4,0.2,14.7,3.2,1.6,0.2,14.8,3.1,1.6,0.2,15.4,3.4,1.5,0.4,15.2,4.1,1.5,0.1,15.5,4.2,1.4,0.2,14.9,3.1,1.5,0.2,15.0,3.2,1.2,0.2,15.5,3.5,1.3,0.2,14.9,3.6,1.4,0.1,14.4,3.0,1.3,0.2,15.1,3.4,1.5,0.2,15.0,3.5,1.3,0.3,14.5,2.3,1.3,0.3,14.4,3.2,1.3,0.2,15.0,3.5,1.6,0.6,15.1,3.8,1.9,0.4,14.8,3.0,1.4,0.3,15.1,3.8,1.6,0.2,14.6,3.2,1.4,0.2,15.3,3.7,1.5,0.2,15.0,3.3,1.4,0.2,17.0,3.2,4.7,1.4,26.4,3.2,4.5,1.5,26.9,3.1,4.9,1.5,25.5,2.3,4.0,1.3,26.5,2.8,4.6,1.5,25.7,2.8,4.5,1.3,26.3,3.3,4.7,1.6,24.9,2.4,3.3,1.0,26.6,2.9,4.6,1.3,25.2,2.7,3.9,1.4,25.0,2.0,3.5,1.0,25.9,3.0,4.2,1.5,26.0,2.2,4.0,1.0,26.1,2.9,4.7,1.4,25.6,2.9,3.6,1.3,26.7,3.1,4.4,1.4,25.6,3.0,4.5,1.5,25.8,2.7,4.1,1.0,26.2,2.2,4.5,1.5,25.6,2.5,3.9,1.1,25.9,3.2,4.8,1.8,26.1,2.8,4.0,1.3,26.3,2.5,4.9,1.5,26.1,2.8,4.7,1.2,26.4,2.9,4.3,1.3,26.6,3.0,4.4,1.4,26.8,2.8,4.8,1.4,26.7,3.0,5.0,1.7,26.0,2.9,4.5,1.5,25.7,2.6,3.5,1.0,25.5,2.4,3.8,1.1,25.5,2.4,3.7,1.0,25.8,2.7,3.9,1.2,26.0,2.7,5.1,1.6,25.4,3.0,4.5,1.5,26.0,3.4,4.5,1.6,26.7,3.1,4.7,1.5,26.3,2.3,4.4,1.3,25.6,3.0,4.1,1.3,25.5,2.5,4.0,1.3,25.5,2.6,4.4,1.2,26.1,3.0,4.6,1.4,25.8,2.6,4.0,1.2,25.0,2.3,3.3,1.0,25.6,2.7,4.2,1.3,25.7,3.0,4.2,1.2,25.7,2.9,4.2,1.3,26.2,2.9,4.3,1.3,25.1,2.5,3.0,1.1,25.7,2.8,4.1,1.3,26.3,3.3,6.0,2.5,35.8,2.7,5.1,1.9,37.1,3.0,5.9,2.1,36.3,2.9,5.6,1.8,36.5,3.0,5.8,2.2,37.6,3.0,6.6,2.1,34.9,2.5,4.5,1.7,37.3,2.9,6.3,1.8,36.7,2.5,5.8,1.8,37.2,3.6,6.1,2.5,36.5,3.2,5.1,2.0,36.4,2.7,5.3,1.9,36.8,3.0,5.5,2.1,35.7,2.5,5.0,2.0,35.8,2.8,5.1,2.4,36.4,3.2,5.3,2.3,36.5,3.0,5.5,1.8,37.7,3.8,6.7,2.2,37.7,2.6,6.9,2.3,36.0,2.2,5.0,1.5,36.9,3.2,5.7,2.3,35.6,2.8,4.9,2.0,37.7,2.8,6.7,2.0,36.3,2.7,4.9,1.8,36.7,3.3,5.7,2.1,37.2,3.2,6.0,1.8,36.2,2.8,4.8,1.8,36.1,3.0,4.9,1.8,36.4,2.8,5.6,2.1,37.2,3.0,5.8,1.6,37.4,2.8,6.1,1.9,37.9,3.8,6.4,2.0,36.4,2.8,5.6,2.2,36.3,2.8,5.1,1.5,36.1,2.6,5.6,1.4,37.7,3.0,6.1,2.3,36.3,3.4,5.6,2.4,36.4,3.1,5.5,1.8,36.0,3.0,4.8,1.8,36.9,3.1,5.4,2.1,36.7,3.1,5.6,2.4,36.9,3.1,5.1,2.3,35.8,2.7,5.1,1.9,36.8,3.2,5.9,2.3,36.7,3.3,5.7,2.5,36.7,3.0,5.2,2.3,36.3,2.5,5.0,1.9,36.5,3.0,5.2,2.0,36.2,3.4,5.4,2.3,35.9,3.0,5.1,1.8,3];% 每类的前40个样本的均值用于代表该类,后10个作为独立的测试样本m1 = mean(yuanwei_data(1:40, 1:4) ); %第1类的前40个样本的平均向量m2 = mean( yuanwei_data(51:90, 1:4) ); %第2类的前40个样本的平均向量m3 = mean( yuanwei_data(101:140, 1:4) ); %第3类的前40个样本的平均向量% 测试样本集Test = [yuanwei_data(41:50, :); yuanwei_data(91:100, :); yuanwei_data(141:150, :)];% 测试样本集对应的类别标签classLabel =Test (:,5 )';% 利用最近邻分类器分类测试样本class = zeros(1, 30); %类标签for ii = 1:size(Test, 1)%待分类样本有3个邻居,且邻居分别为不同的类的样本均值   d(1) = norm(Test(ii, 1:4) - m1); %与第1类的距离   d(2) = norm(Test(ii, 1:4) - m2); %与第2类的距离   d(3) = norm(Test(ii, 1:4) - m3); %与第3类的距离     [minVal class(ii)] = min(d); %计算最小距离并将距离样本最短的类赋给类标签数组 classend% 测试最近邻分类器的识别率nErr = sum(class ~= classLabel);rate = 1 - nErr / length(class);classLabelclassstrOut = ['识别率为', num2str(rate*100), '%']


程序运行结果如下图


从运行结果看,只有第3类的第3个测试样本分类错误,被分为第2类。

0 0
原创粉丝点击