风云高的模式识别和图像处理

fisher准则函数程序演示

 

      理论部分我就不细说了,可以参看上面提及的《模式识别(第二版)》P91。程序的算法是梯度下降法,参看书的P93~94,形式如下:

感知准则函数的梯度下降法公式

      这个算法还是很简单的,用Matlab实现尤为容易,废话不多说,贴程序(Matlab版本7.0.1):

      下面这个是用感知准则函数和梯度下降法求解向量的函数JP.m:

function a=JP(c1,c2,varargin)
%感知准则函数
%用梯度下降算法
%求解满足条件的
%解向量a
nv=numel(varargin);
%函数的第三个参数是余量
%使解向量远离解区的边界
%默认为0
if nv>0 && isa(varargin{1},'double')
    b=varargin{1};
else
    b=0;
end
%函数的第四个参数是修正次数
%如果未指定,则默认1000次
if 2==nv && isa(varargin{2},'double')
    times=varargin{2};
else
    times=1000;
end
[m1,n1]=size(c1);
[m2,n2]=size(c2);
%两类样本必须维数相同
if m1~=m2
    error('样本维数必须相同');
end
%增广样本向量
c1=[ones(1,n1);c1];
c2=[ones(1,n2);c2];
%样本规范化
Y=[c1,-c2].';
%假设a初始时为0向量
a=zeros(m1+1,1);
%不断使用分类错误的向量修正a向量
count=0;
while 1
    v=Y*a;
    %如果没有错误分类的样本,则退出循环
    if 0==any(v<=b)
        break;
    end
    %找到错误分类的样本向量,并加到a上
    a=a+sum(Y(v<=b,:),1).';
    %如果超过了指定的循环次数,则退出
    count=count+1;    
    if count>times
        break;
    end
end
%将a转化为单位向量
a=a/sqrt(sum(a.^2));

      下面是生成2D空间样本的函数(createSwatch.m),关于这个函数的更多说明参见《简单的利用Fisher准则函数获取最佳投影线的Matlab程序》

function swatch=createSwatch(xmin,xmax,ymin,ymax,num,varargin)
xlen=abs(xmax-xmin);
ylen=abs(ymax-ymin);
if numel(varargin)>0 && isa(varargin{1},'function_handle')
    f=varargin{1};
else
    f=@rand;
end
swatch=[xlen*f(1,num)+min(xmax,xmin);...
    ylen*f(1,num)+min(ymax,ymin)];

      下面是测试用的脚本:

clear all;
%定义两类样本的空间范围
x1min=0;x1max=5;
y1min=5;y1max=10;
x2min=5;x2max=10;
y2min=0;y2max=5;
%两类样本的个数
num1=100;
num2=80;
%产生两类2D空间的样本
c1=createSwatch(x1min,x1max,y1min,y1max,num1);
c2=createSwatch(x2min,x2max,y2min,y2max,num2);
%获取感知准则函数的解向量
a=JP(c1,c2,500);
%分界面的横坐标
x=-10:10;
%分界面的纵坐标
y=-10:10;
%分界面的法向量是a
[X,Y]=meshgrid(x,y);
Z=(-a(1)*X-a(2)*Y)/a(3);
%开始绘图
figure;
hold on;
%绘制第一类样本点
plot3(ones(1,num1),c1(1,:),c1(2,:),'r.');
%绘制第二类样本点
plot3(ones(1,num2),c2(1,:),c2(2,:),'b.');
%绘制分界面
mesh(x,y,Z);
%绘制向量a
a=10*a;
line([-a(1),a(1)],[-a(2),a(2)],[-a(3),a(3)],'color','k');
axis([-10,10,-10,10,-10,10]);
grid on;
hold off;

           作一点简要的说明:在JP函数中有一行a=a+sum(Y(v<=b,:),1).';。之所以使用sum(...,1)的形式,那个1是为了防止当样本中只有一个被错误分类时,直接使用sum得到一个标量的结果。而sum(...,1)的形式,如果只有一个错分样本,则sum不进行任何操作。

      还有关于那个余量的引入,我不知道我的方法是否合适,不过余量的确改善了解向量的分类效果。

      使用增广样本向量也很重要,因为它能使方程简化为齐次方程。

      程序的运行结果如下:

      由于样本向量变成了增广样本向量,所以原来的2D空间样本变成了3D空间样本:

p2

 

p1

      上面两图是从不同角度观察得到的,大家用Matlab试一下就知道了。

posted on 2010-03-15 11:01  风云高  阅读(1502)  评论(0编辑  收藏  举报

导航