【机器学习】--非参数估计实验 parzen窗以及k-近邻概率密度

一.实验题目

(所用参考教材:《模式分类》---机械工业出版社 李宏东 姚天翔等译)

4-3.考虑对于表格中的数据进行parzen窗估计和设计分类器,窗函数为一个球形的高斯函数,

<a>编写程序,使用parzen窗估计方法对一个任意的样本点x进行分类。对分类器的训练则使用表格中的三维数据。同时令h=1,分类样本点为

(0.5,1.0,0.0)‘,(0.31,1,51,-0.50)’,(-0.3,0.44,-0.1);

<b>现在我们令h=0.1,重复a

4-4.考虑不同维度的空间中,使用k-近邻概率密度估计方法的效果

<a>编写程序,对于一维的情况,当有n个数据样本点时,进行k-近邻概率密度估计。对表格中w3中的特征x1,用程序画出当k=1,3,5时的概率密度估计结果。

<b>编写程序,对于二维的情况,当有n个数据样本点时,进行k-近邻概率密度估计。对表格中的类别w2中的特征(x1,x2)',用程序画出当k=1,3,5时的概率密度估计结果。

<c>对表格中的3个类别的三维特征,使用k-近邻概率密度估计方法,并且对下列点处的概率密度进行估计:

(-0.41,0.82,0.88)‘,(0.14,0.72,4.1)’,(-0.81,0.61,-0.38)‘


二.实验环境

MATLAB 2016版


三.实验分析

1.首先进行对4-3的分析

4-3要求使用parzen窗非参数估计的方法并设计分类器

①Parzen窗方法的理解:

<a>首先由公式:pn(x)=kn/n/Vn  可以计算出非参数的概率密度估计

其中 pn(x)表示p(x)的第n次估计,

Vn为区域Rn的体积,

Kn为Rn中的样本个数。

<b>要使用的窗方法,主要就是定义Vn

设Rn为d维超立方体,hn为其中的一条边,

由此就可以得到落在窗中的样本个数kn的表达式。

<c>在题目中已经给出了使用的窗函数的形式,则可直接使用概率密度进行计算

<d>使用了表格中各类的三维数据作为训练样本,并将各个分类样本作为参数传入到编写的parzen窗函数中:

(事先已将课本上的数据样本导入到我所建的参数估计项目之下,生成了mat数据文件以备之后的程序使用)

Parzen窗函数代码:

 1 %生成函数计算样本个数kn的表达式
 2 %使用可球型的高斯函数作为窗函数,并令hn=1 3 %a为使用三维数据,h为超立方体的边长,x为测试样本
 4 function px=parzen(a,h,x)
 5 hn=h;
 6 [m,n]=size(a);              %返回m为样本的个数,m为行,n为列
 7 px=0;
 8 vn=4*pi*h^3/3;              %求出rn空间的体积vn
 9 for i=1:m
10    px=px+exp((-(x-a(i,:))*(x-a(i,:))')/(2*power(hn,2)))/(vn);
11    %px为概率密度函数
12 end
13 px=px/m;
14 end

在测试脚本中对于h=1或h=0.1做不同的赋值,最后在得到的概率密度px数组中找到相应最大的概率,即可判定分类样本属于哪个类别(即w1/w2/w3)

测试脚本如图所示:

 1 %用于进行上机题4-3
 2 clear
 3 load('w1.mat');
 4 load('w2.mat');
 5 load('w3.mat');
 6 
 7 %完成4-3第二题<a>
 8 x1=[0.5,1.0,0.0];
 9 x2=[0.31,1.51,-0.50];
10 x3=[-0.3,0.44,-0.1];
11 p1=[];
12 p2=[];
13 p3=[];
14 h1=1;
15 p11=parzen(w1,h1,x1);
16 p12=parzen(w2,h1,x1);
17 p13=parzen(w3,h1,x1);
18 p1=[p11,p12,p13];                %将每一个类别算出的概率放在一起
19 n1=find(p1==max(p1));             %find函数用于返回所需元素的所在位置
20                                  %n1,n2,n3返回的是最大概率的值,则表明样本属于那个类
21 p21=parzen(w1,h1,x2);
22 p22=parzen(w2,h1,x2);
23 p23=parzen(w3,h1,x2);
24 p2=[p21,p22,p23];
25 n2=find(p2==max(p2));
26 
27 p31=parzen(w1,h1,x3);
28 p32=parzen(w2,h1,x3);
29 p33=parzen(w3,h1,x3);
30 p3=[p31,p32,p33];
31 n3=find(p3==max(p3));
32 
33 disp('当h=1时');
34 %disp(p1);
35 disp(['样本点1 [ ',num2str(x1),' ] 落在类别 ',num2str(n1),'']);
36 disp(['样本点2 [ ',num2str(x2),' ] 落在类别 ',num2str(n2),'']);
37 disp(['样本点3 [ ',num2str(x3),' ] 落在类别 ',num2str(n3),'']);
38 
39 %完成4-3第二题<b>
40 h2=0.1;
41 k1=[];
42 k2=[];
43 k3=[];
44 k11=parzen(w1,h2,x1);
45 k12=parzen(w2,h2,x1);
46 k13=parzen(w3,h2,x1);
47 k1=[k11,k12,k13];                %将每一个类别算出的概率放在一起
48 m1=find(k1==max(k1));             %find函数用于返回所需元素的所在位置
49                                  %n1,n2,n3返回的是最大概率的值,则表明样本属于那个类
50 k21=parzen(w1,h2,x2);
51 k22=parzen(w2,h2,x2);
52 k23=parzen(w3,h2,x2);
53 k2=[k21,k22,k23];
54 m2=find(k2==max(k2));
55 
56 k31=parzen(w1,h2,x3);
57 k32=parzen(w2,h2,x3);
58 k33=parzen(w3,h2,x3);
59 k3=[k31,k32,k33];
60 m3=find(k3==max(k3));
61 
62 disp('当h=0.1时')
63 %p(k1);
64 disp(['样本点1 [ ',num2str(x1),' ] 落在类别 ',num2str(m1),'']);
65 disp(['样本点2 [ ',num2str(x2),' ] 落在类别 ',num2str(m2),'']);
66 disp(['样本点3 [ ',num2str(x3),' ] 落在类别 ',num2str(m3),'']);
67 
68 clear                        %清除所有变量

在不同的h下计算出来,各个分类样本点中,概率密度最大的值均在w2类中。

2.进行4-4的分析

要求使用k-近邻估计概率密度

①k-近邻方法的理解:

让体积成为训练样本的函数,而不是硬性的规定窗函数为全体样本个数的某个函数。

例:从n个训练样本中估计p(x),我们能以点x为中心,让体积扩张,直到包含进kn个样本点位置,其中的kn是关于n的某一个特定函数。

这些样本就被称为点x的kn个最近邻。

②首先对4-4题目中的<a>、<b>问进行分析:

<a> 题目中都要求在n个数据样本点的条件下,即把n个数据样本点作为训练样本,然后将题目<a>的一维数据w3中的x1作为特征值,

将<b>中的二位数据w2中的(x1,x2)作为特征值代入编写的kneighbor函数中。

<b>仍然使用公式:pn(x)=kn/n/Vn 来进行计算。

首先计算出Vn,

调用rand()函数先产生100个0-3之间的训练样本集

对于一维数据Vn为训练样本和测试样本之间差值的长度绝对值;

对于二维数据Vn为训练样本和测试样本之间的欧几里得距离,使用距离公式进行计算。

<c>计算出Vn后,由题目的kn可取1,3,5.分别取值代入函数中计算,得到最终结果为每个随机样本点对应的概率密度估计值。

<d>对于一维数据及二维数据进行k-近邻估计的函数如图所示:

 1 %使用kn近邻概率密度估计方法,分别对一维,二维,三维的数据进行估计
 2 %k为参数,a为样本
 3 %测试数据为一维
 4 function px= kneighbor(a,kn,x)
 5 [m,n]=size(a);
 6 b=x;
 7    N=100;
 8 if n==1              %当为一维向量时
 9    px=zeros(N,1);
10    vn1=zeros(N,1);
11 for i=1:N
12    for j=1:m
13      vn1(j)=abs(b(i)-a(j));            %求出vn,即两个数据点的距离长度
14    end                                
15     vn1=sort(vn1);                %将每一列由小到大排列一遍
16     px(i)=kn/N/(vn1(kn));             %计算概率密度
17 end
18 %disp(px);
19 end
20 
21 if n==2              %当为二维向量时
22    px=zeros(N,1);    %用于存储概率       
23    vn2=zeros(N,1);
24 for i=1:N
25    for j=1:m
26      vn2(j)=sqrt((b(i,1)-a(j,1))^2+(b(i,2)-a(j,2))^2);       %计算出两点之间的距离
27    end                                  
28     vn2=sort(vn2);
29     px(i)=kn/N/(vn2(kn));                                    %计算出概率密度
30 end
31 end
32 
33 end

使用变量n可以判定输入的数据维度。

<e>题目<a>的实验结果(kn取1,3,5)

测试所用脚本如图所示:

 1 %用于进行上机题4-4
 2 clear
 3 load('w1.mat');
 4 load('w2.mat');
 5 load('w3.mat');
 6 
 7 k1=1;
 8 k2=3;
 9 k3=5;
10 
11 %完成4-4第三题<a>
12 a1=w3(:,1);
13 N=100;                            
14 b=2*rand(N,1);                    %首先产生100个0-3之间的随机数
15 p1=kneighbor(a1,k1,b);
16 p2=kneighbor(a1,k2,b);
17 p3=kneighbor(a1,k3,b);
18 figure(1);
19 subplot(1,4,1);
20 plot(b,p1,'.');
21 subplot(1,4,2);
22 plot(b,p2,'.');
23 subplot(1,4,3);
24 plot(b,p3,'.');
25 
26 %完成4-4第三题<b>
27 b1=[];
28 a2=w2(:,1);
29 a3=w2(:,2);
30 b1=[a2 a3];
31 b2=3*rand(N,2);                 %产生100个0-4的二维随机数
32 
33 p11=kneighbor(b1,k1,b2);
34 p12=kneighbor(b1,k2,b2);
35 p13=kneighbor(b1,k3,b2);
36 data1=[b2 p11];
37 figure(2);
38 plot3(b2(:,1),b2(:,2),p11,'.');
39 grid on;
40 figure(3);
41 plot3(b2(:,1),b2(:,2),p12,'.');
42 grid on;
43 figure(4);
44 plot3(b2(:,1),b2(:,2),p13,'.');
45 grid on;
46 
47 clear

实验结果如图:

③对4-4题目中<c>进行分析

<a>对表格中的3个类别的三维特征,使用k-近邻概率密度估计方法,并且对下列点处的概率密度进行估计:

(-0.41,0.82,0.88)‘,(0.14,0.72,4.1)’,(-0.81,0.61,-0.38)‘

将表格中的3个类别的三维数据作为训练样本,来判定分类样本点属于哪个类别。

<b>使用 pn(x)=kn/n/Vn 公式

Vn由norm()求范数的函数求出每一个训练样本与测试样本之间的距离。

<c>编写函数kneighborthree来计算三维数据的概率密度估计值:

具体代码:

 1 %a,b,c分别为各类的训练样本
 2 %x:测试样本
 3 % 完成4.4题目中的<c>问,使用三维特征对特定点进行估计
 4 function  [num1,num2,num3]=kneighborthree(a,b,c,k,x)
 5 k1=k;
 6 w=[a;b;c];
 7 [m,n]=size(w);
 8 for i=1:m
 9     dist(i)=norm(x-w(i,:));    %求出向量范数
10 end
11 t1=sort(dist);     %欧式距离排序,将每一列由小到大排列一遍
12 [a1,b1]=size(t1);
13 f1=find(dist<=t1(k1+1));   %找到k个最近邻编号
14 %disp(t1);
15 num1=length(find(f1>0&f1<11));
16 num2=length(find(f1>10&f1<21));
17 num3=length(find(f1>20&f1<31));
18 end

测试脚本为:

 1 %完成4-4第三题<c>
 2 x1=[-0.41,0.82,0.88];
 3 x2=[0.14,0.72,4.1];
 4 x3=[-0.81,0.61,-0.38];
 5 x4=[0.011,1.03,-0.21];
 6 [n11,n12,n13]=kneighborthree(w1,w2,w3,k3,x1);
 7 figure(5);
 8 draw3(w1,w2,w3,n11,n12,n13,x1);         %绘制出图像
 9 grid on;
10 [n21,n22,n23]=kneighborthree(w1,w2,w3,k3,x2);
11 draw3(w1,w2,w3,n21,n22,n23,x2);
12 grid on;
13 [n31,n32,n33]=kneighborthree(w1,w2,w3,k3,x3);
14 draw3(w1,w2,w3,n21,n22,n23,x3);
15    
16 clear

编写了draw3()方法来绘制出图像。

实验结果如图:

图中不同颜色表示3个类别。圆圈是已经分好类的测试样本数据。


四.实验总结

通过对于parzen窗方法和k-近邻估计方法的使用,可以得知初始kn值选取是比较重要的,会影响结果的概率密度估计值。

Kn需要取一个合适的值,并且parzen窗方法和k-近邻估计方法的差异也比较明显,对于parzen窗方法需要首先确定一个窗函数,而k-近邻估计方法是让体积成为训练样本的函数,而不是硬性的规定窗函数为全体样本个数的某个函数。

作为机器学习的初学者,也是在老师的指导下,慢慢摸索研究,有许多方法函数的编写也很稚嫩,虚心的向各位机器学习的大神讨教,哪里有问题非常欢迎指出与探讨,自己也会在之后重新修改与测试,代码的编写、方法的使用也需要更多的成熟性与实用性。

补充draw3()函数

 1 function  m=draw3(w1,w2,w3,num1,num2,num3,x)
 2 %UNTITLED3 此处显示有关此函数的摘要
 3 %画出根据三维数据特征,使用k-近邻概率估计方法
 4 %并对点,进行估计分类
 5 plot3(w1(:,1),w1(:,2),w1(:,3),'r+');
 6 hold on;
 7 grid on;
 8 plot3(w2(:,1),w2(:,2),w2(:,3),'c+');
 9 plot3(w3(:,1),w3(:,2),w3(:,3),'g+');    
10 if(num1>num2)&&(num1>num3)
11    plot3(x(1,1),x(1,2),x(1,3),'ro');
12    disp(['[ ',num2str(x),' ] 是w1类']);
13 elseif (num2>num1)&&(num2>num3)
14    plot3(x(1,1),x(1,2),x(1,3),'co');
15    disp(['[ ',num2str(x),' ] 是w2类']);
16 elseif  (num3>num1)&&(num3>num2)
17    plot3(x(1,1),x(1,2),x(1,3),'go');
18    disp(['[ ',num2str(x),' ] 是w3类']);
19 else
20    disp('无法分类');
21 end
22 m=0;
23 
24 end
25  

作者:魔王是翼伊

是在大学三年级学习过程中老师布置的实验题目,欢迎指教与探讨。

2017年4月25日 重新修改总结发布

原文地址:https://www.cnblogs.com/mowangshiyiyi316/p/6474834.html