一.实验目的
通过本实验的学习,使学生了解或掌握模式识别中利用势函数思想设计非线性判别函数的方法,能够实现模式的分类。学会运用已学习的先导课程如数据结构和算法设计知识,选用合适的数据结构完成算法的设计和程序的实现。并通过训练数据来建立非线性判别函数,通过代待分类样本进行分类预测,通过检查预测结果和数据的几何分布特性检验分类器的正确性。通过选用此种分类方法进行分类器设计实验,强化学生对非线性分类器的了解和应用,从而牢固掌握模式识别课程内容知识。
二.实验内容
假定对病人3项主要指标检查得到正常(类)和非正常(类)的数据如下:
W1类: (1,2, 5), (1,1, 2),(3,3,6);
W2类: (5,6,10),(7,6,11),(8,7,12).
三.原理分析
.实验步骤
1、选定势函数(3个双变量对称基函数中选1;或做成多选的,实现人工自动选择);
2、确定合适数据结构,以便分别完成势函数和判别函数的正确表示;
3、对训练样本加以训练学习,建立判别函数,使其满足分类要求
4、记录并输出训练轮次;
5、对所有样本的类别用你的分类器加以判断(分类决策),比较与实际类别的差异;
6、对待分类样本进行判断,得到其类别(预测),如可能,以几何分布情况加以说明;
7、输出你的判别函数的表达形式(注意:表达形式要求便于阅读理解)。
1,理论基础
势函数法是非线性分类器中常用到的一种方法,它借用电场的概念,来解决模式分类问题。用势函数的概念来确定判别函数和划分类别界面。在势函数法中,把属于一类的样品看做正电荷,而属于另一类的样品看作负电荷,从而把模式的分类转变为正负电荷的转移,电位为0 的等位线即为判别界限。
2,基本思想
假设要划分属于两种类别ω1ω1和ω2ω2的模式样本,这些样本可看成是分布在nn维模式空间中的点xkxk。
把属于ω1ω1的点比拟为某种能源点,在点上,电位达到峰值。
随着与该点距离的增大,电位分布迅速减小,即把样本xkxk附近空间xx点上的电位分布,看成是一个势函数K(x,xk)K(x,xk)。
对于属于ω1ω1的样本集群,其附近空间会形成一个"高地",这些样本点所处的位置就是"山头"。
同理,用电位的几何分布来看待属于ω2ω2的模式样本,在其附近空间就形成"凹地"。
只要在两类电位分布之间选择合适的等高线,就可以认为是模式分类的判别函数。
3,判别函数的产生
模式分类的判别函数可由分布在模式空间中的许多样本向量{xk,k=1,2,⋯且,xk∈ω1∪w2}{xk,k=1,2,⋯且,xk∈ω1∪w2}的势函数产生。
任意一个样本所产生的势函数以K(x,xk)K(x,xk)表征,则判别函数d(x)d(x)可由势函数序列K(x,x1),K(x,x2),⋯K(x,x1),K(x,x2),⋯来构成,序列中的这些势函数相应于在训练过程中输入机器的训练模式样本x1,x2,⋯x1,x2,⋯。
在训练状态,模式样本逐个输入分类器,分类器就连续计算相应的势函数,在第kk步迭代时的积累位势决定于在该步前所有的单独势函数的累加。
以K(x)K(x)表示积累位势函数,若加入的训练样本xk+1xk+1是错误分类,则积累函数需要修改,若是正确分类,则不变。
4,逐步分析
设初始势函数K0(x)=0K0(x)=0
第一步:加入第一个训练样本x1x1,
则有
K1(x)={K(x,x1)−K(x,x1)ifx1∈ω1ifx1∈ω2K1(x)={K(x,x1)ifx1∈ω1−K(x,x1)ifx1∈ω2
这里第一步积累势函数K1(x)K1(x)描述了加入第一个样本时的边界划分。当样本属于ω1ω1时,势函数为正;当样本属于ω2ω2时,势函数为负。
第二步:加入第二个训练样本x2x2,
则有
若x2∈ω1x2∈ω1且K1(x2)>0K1(x2)>0,或x2∈ω2x2∈ω2且K1(x2)<0K1(x2)<0,则分类正确,此时K2(x)=K1(x)K2(x)=K1(x),即积累势函数不变。
若x2∈ω1x2∈ω1且K1(x——2)<0K1(x——2)<0,则
K2(x)=K1(x)+K(x,x2)=±K(x,x1)+K(x,x2)K2(x)=K1(x)+K(x,x2)=±K(x,x1)+K(x,x2)
若x2∈ω2x2∈ω2且K1(x2)>0K1(x2)>0,则
K2(x)=K1(x)−K(x,x2)=±K(x,x1)−K(x,x2)K2(x)=K1(x)−K(x,x2)=±K(x,x1)−K(x,x2)
以上(ii)、(iii)两种情况属于错分。假如x2x2处于K1(x)K1(x)定义的边界的错误一侧,则当x∈ω1x∈ω1时,积累位势K2(x)K2(x)要加K(x,x2)K(x,x2),当x∈ω2x∈ω2时,积累位势K2(x)K2(x)要减K(x,x2)K(x,x2)。
第KK步:设Kk(x)Kk(x)为加入训练样本x1,x2,⋯,xkx1,x2,⋯,xk后的积累位势,则加入第(k+1)(k+1)个样本时,Kk+1(x)Kk+1(x)决定如下:
1. 若xk+1∈ω1xk+1∈ω1且Kk(xk+1)>0Kk(xk+1)>0,或xk+1∈ω2xk+1∈ω2且Kk(xk+1)<0Kk(xk+1)<0,则分类正确,此时Kk+1(x)=Kk(x)Kk+1(x)=Kk(x),即积累位势不变。
2. 若xk+1∈ω1xk+1∈ω1且Kk(xk+1)<0Kk(xk+1)<0,则Kk+1(x)=Kk(x)+K(x,xk+1)Kk+1(x)=Kk(x)+K(x,xk+1);
3. 若xk+1∈ω2xk+1∈ω2且Kk(xk+1)>0Kk(xk+1)>0,则Kk+1(x)=Kk(x)−K(x,xk+1)Kk+1(x)=Kk(x)−K(x,xk+1).
因此,积累位势的迭代运算可写成:Kk+1(x)=Kk(x)+rk+1K(x,xk+1)Kk+1(x)=Kk(x)+rk+1K(x,xk+1),rk+1rk+1为校正系数:
rk+1=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪001−1ifxk+1∈ω1andKk(xk+1)>0ifxk+1∈ω2andKk(xk+1)<0ifxk+1∈ω1andKk(xk+1)<0ifxk+1∈ω2andKk(xk+1)>0rk+1={0ifxk+1∈ω1andKk(xk+1)>00ifxk+1∈ω2andKk(xk+1)<01ifxk+1∈ω1andKk(xk+1)<0−1ifxk+1∈ω2andKk(xk+1)>0
若从给定的训练样本集x1,x2,⋯,xk,⋯x1,x2,⋯,xk,⋯中去除不使积累位势发生变化的样本,即使Kj(xj+1)>0Kj(xj+1)>0且xj+1∈ω1xj+1∈ω1,或Kj(xj+1)<0Kj(xj+1)<0且xj+1∈ω2xj+1∈ω2的那些样本,则可得一简化的样本序列{x⌢1,x⌢2,…,x⌢j,…}{x⌢1,x⌢2,…,x⌢j,…},它们完全是校正错误的样本。此时,上述迭代公式可归纳为:
Kk+1(x)=∑x⌢jajK(x,x⌢j)Kk+1(x)=∑x⌢jajK(x,x⌢j)
其中
aj={+1−1forx⌢j∈ω1forx⌢j∈ω2aj={+1forx⌢j∈ω1−1forx⌢j∈ω2
也就是说,由k+1k+1个训练样本产生的积累位势,等于ω1ω1类和ω2ω2类两者中的校正错误样本的总位势之差。
从势函数可以看出,积累位势起着判别函数的作用:当xk+1xk+1属于ω1ω1时,Kk(xk+1)>0Kk(xk+1)>0;当xk+1xk+1属于ω2ω2时,Kk()xk+1<0Kk()xk+1<0,则积累位势不做任何修改就可用作判别函数。
由于一个模式样本的错误分类可造成积累位势在训练时的变化,因此势函数算法提供了确定ω1ω1和ω2ω2两类判别函数的迭代过程。判别函数表达式:取d(x)=K(x)d(x)=K(x),则有:dk+1(x)=dk(x)+rk+1K(x,xk+1)dk+1(x)=dk(x)+rk+1K(x,xk+1).
4 构成势函数的两种方式:
第一类势函数:
可用对称的有限多项式展开,即:
K(x,xk)=∑i=1mϕi(x)ϕi(xk)K(x,xk)=∑i=1mϕi(x)ϕi(xk)
其中{
}在模式定义域内为正交函数集。将这类势函数代入判别函数,有:
dk+1(x)=dk(x)+rk+1∑i=1mϕi(xk+1)ϕi(x)=dk(x)+∑i=1mrk+1ϕi(xk+1)ϕi(x)dk+1(x)=dk(x)+rk+1∑i=1mϕi(xk+1)ϕi(x)=dk(x)+∑i=1mrk+1ϕi(xk+1)ϕi(x)
得迭代关系:
dk+1(x)=∑i=1mCi(k+1)ϕi(x)dk+1(x)=∑i=1mCi(k+1)ϕi(x)
其中
Ci(k+1)=Ci(k)+rk+1ϕi(xk+1)Ci(k+1)=Ci(k)+rk+1ϕi(xk+1)
因此,积累位势可写成:
Kk+1(x)=∑i=1mCi(k+1)ϕi(x)Kk+1(x)=∑i=1mCi(k+1)ϕi(x)
$Ci$可用迭代式求得。
第二类势函数:
选择双变量xx和$x_k$的对称函数作为势函数,即$K(x, x_k) = K(x_k, x)$,并且它可展开成无穷级数,例如:
(a) K(x,xk)=e−α∥x−xk∥2K(x,xk)=e−α‖x−xk‖2
(b) K(x,xk)=11+α∥x−xk∥2K(x,xk)=11+α‖x−xk‖2, αα是正常数
(c) K(x,xk)=∣∣∣sinα∥x−xk∥2α∥x−xk∥2∣∣∣
四.实验步骤
1、选定势函数(3个双变量对称基函数中选1;或做成多选的,实现人工自动选择);
2、确定合适数据结构,以便分别完成势函数和判别函数的正确表示;
3、对训练样本加以训练学习,建立判别函数,使其满足分类要求
4、记录并输出训练轮次;
5、对所有样本的类别用你的分类器加以判断(分类决策),比较与实际类别的差异;
6、对待分类样本进行判断,得到其类别(预测),如可能,以几何分布情况加以说明;
7、输出你的判别函数的表达形式(注意:表达形式要求便于阅读理解)。
五.测试
1、先测试已有样本的正确性。
2、用待分类数据加以分类。这里,对样本: (2,3,5),(6,7,10)
分别测试,检查它们几何分布情况是否与得到的分别属于类和类的结果相符,从而确认所设计的分类器是正确的。
六.实现提示
1)样本存放在矩阵s中,s的每一行是一个样本,为方便编程,可将类别号增加在每个样本中,作为最后一维;
2)为了保存和计算判别函数,可使用一个辅助的结构数组ftbl,该数组的每个分量含两个成分:index和symbol。 index记录对应样本下标号,symbol记录该项的符号。
七、参考代码
% 用势函数法设计非线性判别器
n=6; % n表示样本总数。这里n=6,前3个样本属于第一类,后三个样本属于第二类
m=30; % 判别函数最大的项数
d=3; % d表示维长
r=0; % r表示在判别函数中所具有的项数(每项是一个基函数,含3个坐标分量(维度=3))
tag=1; %判断是否继续循环的标志量
g=0;
% 样本
s=[ 1,2, 5,1
1,1, 2,1
3,3, 6,1
5,6,11,2
7,6,11,2
8,7,12,2]; % 第4列表示类别: 1表示属于第1类 % 2表示属于第2类
run=0; % run为轮次,初值置为0
while tag==1
run=run+1;
tag=0;
for k=1:n % n表示样本总数。
if r==0 % r==0表示判别函数还不含任何项时
r=r+1; %r指向到目前为止所得到的势函数的最后一项,此时准备含第一个项
% ftbl为结构数组,数组每个分量含index和symbol两个成分,分别记录样本号和符号
ftbl(r).symbol=1; % 该项的符号。 1--正;-1--负
ftbl(r).index=1; % 该项对应的样本下标号
continue;
else
g=0;
% 将当前的第k个样本先代入已建立的部分判别函数中进行计算,再判断分类是否正确
for i=1:r % i为扫描每一项的整数变量
temp=0;
for j=1:d % d表示维长。这里,d实际上为3,即d=3
temp=temp+(s(k,j)-s(ftbl(i).index,j))*(s(k,j)-s(ftbl(i).index,j));
end
g= g+ftbl(i).symbol*exp(-temp); %每项都是一指数形式,求出共r项的和
end
if ((g>0 &s(k,4)==1)||(g<0&s(k,4)==2))
continue; %正确分类时,不修改判别函数
else % 当前样本要构成一项保存到判别表达式中
tag=1;
r=r+1;
ftbl(r).index=k;
if(g>0& s(k,4)==2)
ftbl(r).symbol=-1;
else if(g<0&s(k,4)==1)
ftbl(r).symbol=1;
end
end
end
end
end
end
fprintf('所循环的轮次= %d',run);
fprintf('\n输出判别函数的表达式:\n');
% 输出判别函数,即输出判别函数的每一项。通过输出结构数组ftbl中的每一分量
for i=1:r
% 输出第i项
if(ftbl(i).symbol==1)
if i==1
fprintf('exp{-[(x1')
else
fprintf('+exp{-[(x1')
end
else
fprintf('-exp{-[(x1');
end
% 样本的第一个分量是正号,还是负号,决定输出分量数值前的符号
if (s(ftbl(i).index,1)>0) % 样本的第一个分量是正号
fprintf('-')
fprintf('%d',s(ftbl(i).index,1))
fprintf(')^2+(x2')
else if(s(ftbl(i).index,1)<0) % 样本的第一个分量是负号
fprintf('+')
fprintf('%d',-s(ftbl(i).index,1)) % 负负得正
fprintf(')^2+(x2');
else %s(ftbl(i).index,1)==0
fprintf(')^2+(x2');
end
end
if (s(ftbl(i).index,2)>0)
fprintf('-')
fprintf('%d',s(ftbl(i).index,2))
fprintf(')^2+(x3')
else if(s(ftbl(i).index,2)<0)
fprintf('+')
fprintf('%d',-s(ftbl(i).index,2))
fprintf(')^2+(x3');
else
fprintf(')^2+(x3')
end
end
if (s(ftbl(i).index,3)>0)
fprintf('-')
fprintf('%d',s(ftbl(i).index,3))
fprintf(')^2]}');
else
if(s(ftbl(i).index,3)<0)
fprintf('+')
fprintf('%d',-s(ftbl(i).index,3))
fprintf(')^2]}');
else
fprintf(')^2]}')
end
end
end
fprintf('\n')
% 判别每一样本的类别:
fprintf('判别每一样本的类别:\n');
for k=1:n;
g=0;
for i=1:r
temp=0;
for j=1:d %d表示维长
temp=temp+(s(k,j)-s(ftbl(i).index,j))*(s(k,j)-s(ftbl(i).index,j));
end
g=g+ftbl(i).symbol*exp(-temp); %共r项,每项都是一指数形式
end
if (g>0)
fprintf('第')
fprintf('%d',k)
fprintf('个样本的类别为: ')
fprintf('%d\n',1)
else if (g<0)
fprintf('第')
fprintf('%d',k)
fprintf('个样本的类别为: ')
fprintf('%d\n',2)
else %g==1
fprintf('第')
fprintf('%d',k)
fprintf('个样本的类别无法判别! ')
fprintf('但第')
fprintf('%d',k)
fprintf('个样本的实际类别为: ')
fprintf('%d\n',s(k,4));%输出实际类别
end
end
end
% cout<<endl;
%判断(2,3,5),(6,7,11)分别所属的类别:
%先对第一个样本,即(2,3,5)
a=[2,3,5];
g=0;
for i=1:r
temp=0;
for j=1:d %d表示维长
temp=temp+(a(j)-s(ftbl(i).index,j))*(a(j)-s(ftbl(i).index,j));
end
g=g+ftbl(i).symbol*exp(-temp); %共r项,每项都是一指数形式
end
if g>0
fprintf('样本a=(2,3,5)的类别为: ')
fprintf('%d\n',1)
else
if (g<0)
fprintf('样本a=(2,3,5)的类别为: ')
fprintf('%d\n',2)
else
fprintf('样本a=(2,3,5)的类别无法判别!\n')
end
end
%现对第二个样本,即(6,7,11)
b=[6,7,11];
g=0;
for i=1:r
temp=0;
for j=1:d % d表示维长
temp=temp+(b(j)-s(ftbl(i).index,j))*(b(j)-s(ftbl(i).index,j));
end
g=g+ftbl(i).symbol*exp(-temp); %共r项,每项都是一指数形式
end
if g>0
fprintf('样本b=(6,7,11)的类别为: ')
fprintf('%d\n',1)
else
if (g<0)
fprintf('样本b=(6,7,11)的类别为: ')
fprintf('%d\n',2)
else
fprintf('样本b=(6,7,11)的类别无法判别!\n')
end
end
fprintf('\n')
%%%%
%%%
function g=calfun(s,ftbl,r)
% s存放样本;ftbl存放样本号和符号;r为项数
g=1;
for i=1:r
temp=1;
for j=1:d % d表示维长
temp= temp+(s(k,j)-s(ftbl(i).index,j))*(s(k,j)-s(ftbl(i).index,j));
g= g+ftbl(i).symbol*exp(-temp); %共r项,每项都是一指数形式
end
end
end