SVM图像识别 含源码

需要源码的可以联系我 QQ [email protected]

支持向量机图像识别
一 实验目的
掌握利用支持向量机进行图像识别的基本方法,通过实验加深对基本概念的理解
二 实验原理
支持向量机方法是建立在统计学习理论的VC维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度,Accuracy)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折衷,以期获得最好的推广能力(或称泛化能力)。
  所谓VC维是对函数类的一种度量,可以简单的理解为问题的复杂程度,VC维越高,一个问题就越复杂。正是因为SVM关注的是VC维,后面我们可以看到,SVM解决问题的时候,和样本的维数是无关的(甚至样本是上万维的都可以,这使得SVM很适合用来解决文本分类的问题,当然,有这样的能力也因为引入了核函数)。机器学习本质上就是一种对问题真实模型的逼近。最直观的想法就是使用分类器在样本数据上的分类的结果与真实结果(因为样本是已经标注过的数据,是准确的数据)之间的差值来表示。这个差值叫做经验风险Remp(w)。以前的机器学习方法都把经验风险最小化作为努力的目标,但后来发现很多分类函数能够在样本集上轻易达到100%的正确率,在真实分类时却一塌糊涂(即所谓的推广能力差,或泛化能力差)。此时的情况便是选择了一个足够复杂的分类函数(它的VC维很高),能够精确的记住每一个样本,但对样本之外的数据一律分类错误。回头看看经验风险最小化原则我们就会发现,此原则适用的大前提是经验风险要确实能够逼近真实风险才行但实际上能逼近么?答案是不能,因为样本数相对于现实世界要分类的文本数来说简直九牛一毛,经验风险最小化原则只在这占很小比例的样本上做到没有误差,当然不能保证在更大比例的真实文本上也没有误差。
非线性,是指SVM擅长应付样本数据线性不可分的情况,主要通过松弛变量和核函数技术来实现。

高维模式识别是指样本维数很高,例如文本的向量表示,出现几万维的情况很正常,其他算法基本就没有能力应付了,SVM却可以,主要是因为SVM 产生的分类器很简洁,用到的样本信息很少(仅仅用到那些称之为“支持向量”的样本,此为后话),使得即使样本维数很高,也不会给存储和计算带来大麻烦(相对照而言,kNN算法在分类时就要用到所有样本,样本数巨大,每个样本维数再一高,这日子就没法过了……)。
实际上,一个线性函数是一个实值函数(即函数的值是连续的实数),而我们的分类问题(例如这里的二元分类问题——回答一个样本属于还是不属于一个类别的问题)需要离散的输出值,例如用1表示某个样本属于类别C1,而用0表示不属于(不属于C1也就意味着属于C2),这时候只需要简单的在实值函数的基础上附加一个阈值即可,通过分类函数执行时得到的值大于还是小于这个阈值来确定类别归属   SVM在解决小样本、非线性及高维模式识别问题中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中。SVM的求解最后转化成二次规划问题的求解,因此SVM的解是全局唯一的最优解。线性分类器是利用训练样本集建立线性判别函数 或者广义线性判别函数 。
    SVM 是从线性可分情况下的最优分类面发展而来的, 基本思想可用下图的两维情况说明. 图中, 方形点和圆形点代表两类样本, H为分类线,H1, H2分别为过各类中离分类线最近的样本且平行于分类线的直线, 它们之间的距离叫做分类间隔(margin),红蓝样本称为支持向量。 所谓最优分类线就是要求分类线不但能将两类正确分开(训练错误率为0),而且使分类间隔最大.推广到高维空间,最优分类线就变为最优分类面。 


 
图2-1 线性可分情况下的最优分类线
    最优判别函数为
 
    该式只包含待分类样本与训练样本中的支持向量的内积运算,可见,要解决一个特征空间中的最优线性分类问题,我们只需要知道这个空间中的内积运算即可。
   对非线性问题, 可以通过非线性变换转化为某个高维空间中的线性问题, 在变换空间求最优分类面. 这种变换可能比较复杂, 因此这种思路在一般情况下不易实现.非线性SVM将样本点升维,即映射到高维甚至无穷维空间,再在高维空间中采用线性问题的处理方法。
 
图2-2 样本点升维
     设非线性映射 表示将输入空间样本 映射到高维特征空间H中(即样本点升维),由最优化求解过程可见,训练算法只用到特征空间H 中的点积运算 因此若能找到一个函数K,使得 ,那么


在高维空间中实际只需要进行内积运算,甚至不必知道变换 的形式。
    只要函数 满足Mercer条件,其就对应某一变换空间中的内积。使用函数K进行非线性变换,不会增加计算复杂度。
判别函数的形式变为
  
   选择满足Mercer条件的核函数,即可构建非线性支持向量机。
三 实验步骤及程序
  1 实验步骤
要实现支持向量机的多类分类,首先要实现两类分类。支持向量机分类算法包括两部分,支持向量机的训练和支持向量机分类。然后,对支持向量机进行训练对图像进行识别分割。
 1 支持向量机训练的步骤
(1)输入训练样品向量 ,类别号分别 , 。如果 ,则 ;  ,则 。
(2)指定核函数类型。
(3)求解目标函数式(4.8)的最优解,得到最优Lagrange乘子 。
(4)利用样本库中的一个支持向量机 ,带入式(4.9)。左值 为其类别值(-1或1),可得到偏差值 。
 2 支持向量机分类的步骤
(1)输入待测样品。
(2)利用训练好的Lagrange乘子 、偏差值 和核函数,求解判别函数 。
(3)根据 的值,输出类别。
 3 对目标图像进行分割识别步骤
(1)输入待测样品。
(2)选取不同RGB值代表不同的区域。
(3)训练得到支持向量分类机。
(4)根据训练得到的支持向量机对图像不同像素点进行分类。
(5)输出分割识别后图片。

2 程序源代码
(1)支持向量机编程代码:
function DiscriminantMethods
fig = figure('defaultuicontrolunits','normalized','name','判别方法比较',...
'numbertitle','off','menubar','none');%主界面,返回主界面句柄fig
UiButtonGroupH = uibuttongroup('Position',[0.55 0.08 0.40 0.85],'title',...
'判别方法','fontsize',12,'fontname','隶书','units','normalized',...
'backgroundcolor',[0.9 0.8 0.7],'bordertype','etchedin',...
'ForegroundColor',[1 0 0],'ShadowColor',[0 1 1]);%群组对象,并返回句柄
DistanceH = uicontrol('Style','Radio','String','距离判别法','fontsize',12,...
'pos',[0.05 0.73 0.9 0.15],'backgroundcolor',[0.9 0.8 0.7],...
'parent',UiButtonGroupH);%距离判别法的选项
BayesH = uicontrol('Style','Radio','String','Bayes判别法','fontsize',12,...
'pos',[0.05 0.32 0.9 0.15],'backgroundcolor',[0.9 0.8 0.7],...
'parent',UiButtonGroupH);%Bayes判别法的选项
%下面几行建立相关按钮控件。各菜单以及按钮点击时候的回调函数(写在下面)
PrepareH = uicontrol(fig,'style','pushbutton','Pos',[0.15,0.68,0.2,0.08],...
'string','判别前准备','fontsize',12,'callback',@Prepare);
StartDiscriminantH = uicontrol(fig,'style','pushbutton','Pos',...
[0.15,0.38,0.2,0.08],'string','开始判别','fontsize',12,...
 'callback',@StartDiscriminant);
%=================================================
%function:Prepare,判别前准备按钮的回调函数
%=================================================


function Prepare(hObject,eventdata)
   [filename, pathname, flag] = uigetfile( '*.xls',...
     '当前选定的判别法的训练样本数据(*.xls)','*.xls');%弹出提示对话框
  if ~flag
        return;%flag为0,用户取消选择,返回;
   end
   [feature,class] = xlsread([pathname,filename]);%读入训练样本数据
   lf = size(feature,1);%训练样本个数
   Uclass = unique(class);%得出训练样本的类别信息(即分属于哪几类)
     lUc = length(Uclass);%类别数目
        Cfeature = cell(lUc,1);
        for k = 1:lUc
            %训练样本中每一类特征归到一起
            Cfeature{k} = feature(strcmp(class,Uclass{k}),:);
        end        
WhichDisc=get(findobj(UiButtonGroupH,'style','radio','value',1),...
 'string');%当前界面中选择的是哪种判别法
      switch WhichDisc
          case '距离判别法'
          %用来存储每一类的各特征平均值
          MeanCfeature = zeros(lUc,size(Cfeature{1},2));
          InvSigma = cell(lUc,1);%用来存储每一类的协方差矩阵的逆
             for ii = 1:lUc
             %得到每一类的各特征平均值
              MeanCfeature(ii,:) = mean(Cfeature{ii});
               %得到每一类的协方差矩阵的逆
               InvSigma{ii} = inv(cov(Cfeature{ii}));
                end
        SampleInfo.MeanCfeature = MeanCfeature;
        

        SampleInfo.InvSigma = InvSigma;
        SampleInfo.Uclass = Uclass;
           setappdata(DistanceH,'SampleInfo',SampleInfo);                
        case 'Bayes判别法'
        %用来存储每一类的各特征平均值
          MeanCfeature = zeros(lUc,size(Cfeature{1},2));
          Sigma = cell(lUc,1);%用来存储每一类的协方差矩阵
          InvSigma = cell(lUc,1);%用来存储每一类的协方差矩阵的逆
          PrioP = zeros(lUc);%用来存储先验概率
          for ii = 1:lUc
          %得到每一类的各特征平均值
          MeanCfeature(ii,:) = mean(Cfeature{ii});
          Sigma{ii} = cov(Cfeature{ii});%得到每一类的协方差矩阵
           InvSigma{ii} = inv(Sigma{ii});%得到每一类的协方差矩阵的逆
                PrioP(ii) = length(Cfeature{ii})/lf;
              end
           SampleInfo.MeanCfeature = MeanCfeature;
           SampleInfo.Sigma = Sigma;
           SampleInfo.InvSigma = InvSigma;
           SampleInfo.Uclass = Uclass;
           SampleInfo.PrioP = PrioP;
              setappdata(BayesH,'SampleInfo',SampleInfo);            
           otherwise
        end
        h=msgbox('准备完毕,请点击开始判别进行测试!');%弹出对话框
        uiwait(h);%等待用户确认后再运行程序        
  end
%============================================================
%function:StartDiscriminant,开始判别按钮的回调函数


%============================================================
function StartDiscriminant(hObject,eventdata)
     [filename, pathname, flag]=uigetfile('*.xls',...
        '请导入测试样本数据(*.xls)','*.xls');%弹出提示对话框
    if ~flag
        return;%flag为0,用户取消选择,返回;
    end
    feature = xlsread([pathname,filename]);
lf = size(feature,1);
  WhichDisc=get(findobj(UiButtonGroupH,'style','radio','value',1),...
 'string');%当前界面中选择的是哪种判别法
   switch WhichDisc
       case '距离判别法'
           %获取判别前准备完成时存储的用于判别的信息
           SampleInfo = getappdata(DistanceH,'SampleInfo');
            if isempty(SampleInfo)  %如果SampleInfo为空值
                hstr = '距离判别法还没有准备,请点击判别前准备按钮做相应准备!';
               h = msgbox(hstr);
                uiwait(h);
                return;
            end
           lUc = length(SampleInfo.Uclass);%类别数目
            %存储每个样本到每个类的距离,行对应样本,列对应类
            Dist = zeros(lf,lUc);
            for k = 1:lf
                for kk = 1:lUc
                       


Dist(k,kk)=(feature(k,:)-SampleInfo.MeanCfeature(kk,:))*...
                            SampleInfo.InvSigma{kk}*(feature(k,:)-...
                 SampleInfo.MeanCfeature(kk,:))';
                end %计算每个样本到每个类的距离
           end
           [md,ClassNum] = min(Dist,[],2);
           Class = SampleInfo.Uclass(ClassNum);
           uiwait(helpdlg('当前样本已用距离判别法判别完毕,请按提示保存结果',...
           '距离判别法判别'));
  [file,path] = uiputfile([filename,'距离判别法判别结果.xls'],...
                   '保存当前判别结果为:');
            if ~file
               uiwait(msgbox('用户放弃保存!'));
                return;
            end
            xlswrite([path,file],Class);
        case 'Bayes判别法'
            %获取判别前准备完成时存储的用于判别的信息
            SampleInfo = getappdata(BayesH,'SampleInfo');
           if isempty(SampleInfo)  %如果SampleInfo为空值
               hstr = 'Bayes判别法还没有准备,请点击判别前准备按钮做相应准备!';
                h = msgbox();
               uiwait(h);
                return;
            end
           lUc = length(SampleInfo.Uclass);%类别数目
             %存储每个样本到每一类的判别函数,行对应样本,列对应类
     

    DiscrimFun = zeros(lf,lUc);
              for k = 1:lf
                    for kk = 1:lUc
   DiscrimFun(k,kk) =( 2*log(SampleInfo.PrioP(kk)) - ...
         log(det(SampleInfo.Sigma{kk})) - ...
                            (feature(k,:)-SampleInfo.MeanCfeature(kk,:)) * ...
   SampleInfo.InvSigma{kk}*...
                            (feature(k,:)-SampleInfo.MeanCfeature(kk,:))')/2;
                    end %计算每个样本到每个类的判别函数
                end
                [md,ClassNum] = max(DiscrimFun,[],2);
                Class = SampleInfo.Uclass(ClassNum);
               uiwait(helpdlg('当前样本已用Bayes判别法判别完毕,请按提示保存结果',...
                  'Bayes判别法判别'));
                [file,path] = uiputfile([filename,'Bayes判别法判别结果.xls'],...
                '保存当前判别结果为:');
                if ~file
                    uiwait(msgbox('用户放弃保存!'));
                    return;
                end
                xlswrite([path,file],Class);            
            otherwise
        end
    end 
End


(2)目标图像分割识别编程代码:
function DuckLakeSegmentation
%导入图像文件引导对话框
[filename,pathname,flag] = uigetfile('*.jpg','请导入图像文件');
Duck = imread([pathname,filename]);
LakeTrainData = [52 74 87;76 117 150;19 48 62;35 64 82;46 58 36;...
    50 57 23;110 127 135;156 173 189;246 242 232;...
    166 174 151];%从图上选取的几个位于湖面区域的有代表的点的RGB值
%从图上选取的几个位于鸭子区域的有代表的点的RGB值
DuckTrainData = [211 192 107;202 193 164;32 25 0;213 201 151;115 75 16;...
    101 70 0;169 131 22;150 133 87];
%属于湖的点为0,鸭子为1
group = [zeros(size(LakeTrainData,1),1);ones(size(DuckTrainData,1),1)];
LakeDuckSVM = svmtrain([LakeTrainData;DuckTrainData],group,...
    'Kernel_Function','polynomial','Polyorder',2);%训练得到支持向量分类机
[m,n,k] = size(Duck);
Duck1 = double(reshape(Duck, m*n, k));%将数组Duck转成m*n行,3列的双精度矩阵
%根据训练得到的支持向量机对整个图像的像素点分类
IndDuck = svmclassify(LakeDuckSVM,Duck1);
IndLake = ~IndDuck;%属于湖的点的逻辑数组
result = reshape([IndLake, IndLake, IndLake],[m,n,k]);%和图片的维数相对应
Duck2 = Duck;
Duck2(result) = 0;
figure
imshow(Duck2)


四 实验结果与分析
输入的训练数据与待测数据如图4-1所示:
             
图4-1 (a)输入的训练数据 (b)输入的待测数据
运用距离判别法和Bayes判别法判别结果如图4-2:
                         
图4-2 (a)距离判别法 (b)Bayes判别法判别结果
支持向量机进行训练对图像进行识别分割的结果如图4-3:


       

图4-3 (a)原图 (b)图像分割后效果图
优点:SVM理论提供了一种避开高维空间的复杂性,直接用此空间的内积函数(既是核函数),再利用在线性可分的情况下的求解方法直接求解对应的高维空间的决策问题.当核函数已知,可以简化高维空间问题的求解难度.同时SVM是基于小样本统计理论的基础上的,这符合机器学习的目的.而且支持向量机比神经网络具有较好的泛化推广能力.
   缺点:对于每个高维空间在此空间的映射F,如何确定F也就是核函数,现在还没有合适的方法,所以对于一般的问题,SVM只是把高维空间的复杂性的困难转为了求核函数的困难.而且即使确定核函数以后,在求解问题分类时,要求解函数的二次规划,这就需要大量的存储空间.这也是SVM的一个问题.


 

你可能感兴趣的:(SVM图像识别 含源码)