matlab 贝叶斯网络学习

来源:互联网 发布:公路工程计价软件 编辑:程序博客网 时间:2024/03/28 18:03
提纲:
最近工作:
    B-COURSE工具学习
    BNT研究与学习
    BNT相关实验及结果
手动建立贝叶斯网及简单推理
       参数学习
        结构学习
下一步工作安排
 
 
最近工作:
1.   B-COURSE 工具学习
B-COURSE是一个供教育者和研究者免费使用的web贝叶斯网络工具。主要分为依赖关系建模和分类器模型设计。输入自己的研究数据,就可以利用该工具在线建立模型,并依据建立好的模型进行简单推理。
B-COURSE要求数据格式是ASCII txt格式的离散数据,其中第一行是各种数据属性变量,其余各行则是采集的样本,属性变量值可以是字符串也可以是数据,属性变量之间用制表符分割,缺失属性变量值用空格代替。读入数据后,在进行结构学习前,可以手动的选择需要考虑的数据属性!生成过程中,可以手动确定模型,确定好模型后,可以选择JAVA playgroud,看到一个java applet程序,可以手动输入相应证据,从而进行简单推理。
B-COURSE的详细使用介绍,可详见[url]http://b-course.cs.helsinki.fi/obc/[/url]。
B-COURSE工具隐藏了数据处理,算法实现等技术难点,所以对初学者来说,容易上手。但是却不能够针对不同的应用进行自主编程,缺乏灵活性。
2.   贝叶斯网工具箱BNT的研究与学习
基于matlab的贝叶斯网络工具箱BNT是kevin p.murphy基于matlab语言开发的关于贝叶斯网络学习的开源软件包,提供了许多贝叶斯网络学习的底层基础函数库,支持多种类型的节点(概率分布)、精确推理和近似推理、参数学习及结构学习、静态模型和动态模型。
   贝叶斯网络表示:BNT中使用矩阵方式表示贝叶斯网络,即若节点i到j有一条弧,则对应矩阵中(i,j)值为1,否则为0。
   结构学习算法函数:BNT中提供了较为丰富的结构学习函数,都有:
1.     学习树扩展贝叶斯网络结构的TANC算法learn_struct_tan().
2.     数据完整条件下学习一般贝叶斯网络结构的K2算法learn_struct_k2()、贪婪搜索GS(greedy search)算法learn_struct_gs()和爬山HC(hill climbing)算法learn_struct_hc()等。
3.     缺失数据条件下学习一般贝叶斯网络结构的最大期望EM(expectation maximization)算法learn_struct_EM()和马尔科夫链蒙特卡罗MCMC(Markov Chain Monte Carlo)learn_struct_mcmc()算法等。
参数学习算法函数:BNT中也提供了丰富的参数学习函数,都有:
1.  完整数据时,学习参数的方法主要有两种:最大似然估计learn_params()和贝叶斯方法bayes_update_params();
2.  数据缺失时,如果已知网络拓扑结构,用EM算法来计算参数,倘若未知网络拓扑结构,使用结构最大期望SEM(structure EM)算法learn_struct_SEM()。
推理机制及推理引擎:为了提高运算速度,使各种推理算法能够有效应用,BNT工具箱采用了引擎机制,不同的引擎根据不同的算法来完成模型转换、细化和求解。这个推理过程如下:
 
 
BNT中提供了多种推理引擎,都有:
1.  联合树推理引擎jtree_inf_engine();
2.  全局联合树推理引擎global_joint_inf_engine();
3.  信念传播推理引擎 belprop_inf_engine();
4.  变量消元推理引擎 var_elim_inf_engine().
3.   使用BNT做的相关实验及结果
u       手动建立贝叶斯网模型及简单推理实验:
1.     “草地潮湿原因模型”建立及推理:(全是离散变量)
%建立贝叶斯网络结构并制定条件概率表
N = 4;  %四个节点 分别是cloudy,sprinkler,rain,wetgrass
dag = zeros(N,N);
C = 1; S = 2; R = 3; W = 4;
dag(C,[R S]) = 1; %节点之间的连接关系
dag(R,W) = 1;
dag(S,W) = 1;
discrete_nodes = 1:N; %离散节点
node_sizes = 2*ones(1,N);%节点状态数
bnet =mk_bnet(dag,node_sizes,'names',{'cloudy','sprinkler','rain','wetgrass'},'discrete',discrete_nodes);    
bnet.CPD{C} = tabular_CPD(bnet,C,[0.5 0.5]);
bnet.CPD{R} = tabular_CPD(bnet,R,[0.8 0.2 0.2 0.8]);
bnet.CPD{S} = tabular_CPD(bnet,S,[0.5 0.9 0.5 0.1]);
bnet.CPD{W} = tabular_CPD(bnet,W,[1 0.1 0.1 0.01 0 0.9 0.9 0.99]);
%画出建立好的贝叶斯网络
figure
draw_graph(dag)
%选择jtree_inf_engine推理引擎。
engine = jtree_inf_engine(bnet);
%输入证据
evidence = cell(1,N);
evidence{R} = 2;
[engine, loglike] = enter_evidence(engine, evidence);
%计算单个节点后验概率,即进行推理
marg1 = marginal_nodes(engine,S);
marg1.T
%计算对节点联合后验概率
marg2 = marginal_nodes(engine,[S R W]);
marg2.T
%给出“软证据”,即节点的可能分布概率情况下的推理
evidence{R} = [];
soft_evidence{R}=[0.6 0.4];
[engine, loglike] = enter_evidence(engine,evidence,'soft',soft_evidence);
marg3 = marginal_nodes(engine,S);
marg3.T
实验结果:
1.贝叶斯网络                             2.单个节点后验概率                                 
3.多个节点后验概率                        4.soft_evidence情况下的后验概率
   
2.     焚化炉厂废物排放模型建立及推理:(包含离散变量和连续变量)
这个实验与第一个实验不同的地方就是它所建立的贝叶斯网中的节点变量包含连续变量,在建立条件概率概率表时会有所不同,离散变量使用CPD构造器tabular_CPD,连续变量使用gaussian_CPD。这里指给出这一部分的代码:
bnet.CPD{B} = tabular_CPD(bnet,B,'CPT',[0.85 0.15]);
bnet.CPD{F} = tabular_CPD(bnet,F,'CPT',[0.95 0.05]);
bnet.CPD{W} = tabular_CPD(bnet,W,'CPT',[2/7 5/7]);
bnet.CPD{E} = gaussian_CPD(bnet,E,'mean',[-3.9 -0.4 -3.2 -0.5],'cov',[0.00002 0.0001 0.00002 0.0001]);
bnet.CPD{D} = gaussian_CPD(bnet,D,'mean',[6.5 6.0 7.5 7.0],'cov',[0.03 0.04 0.1 0.1],'weights',[1 1 1 1]);
bnet.CPD{C} = gaussian_CPD(bnet,C,'mean',[-2 -1],'cov',[0.1 0.3]);
bnet.CPD{L} = gaussian_CPD(bnet,L,'mean',3,'cov',0.25,'weights',-0.5);
bnet.CPD{Min} = gaussian_CPD(bnet, Min,'mean',[0.5 -0.5],'cov',[0.01 0.005]);
bnet.CPD{Mou}=gaussian_CPD(bnet,Mout,'mean',0,'cov',0.002,'weights',[1 1]);
贝叶斯网建立好后,推理部分和实验一相似,这里就不再讨论。
实验结果建立的贝叶斯网如下:
 
 
u       参数学习实验:
这里使用的例子依然是“草地潮湿原因模型”。首先我先如上面实验那样建立好贝叶斯网bnet,并手动构造条件概率表CPT。然后使用BNT里的函数sample_bnet(bnet)来产生nsamples个数据样本,nsamples分别取值20,200,2000。然后,再重新建立一个不知道条件概率表的贝叶斯网bnet2(结构和bnet相同),并把得到的样本作为训练集代入learn_params()函数进行学习,把学习到的条件概率表CPT2与手动构造的CPT进行了比较。参数学习部分代码:
nsamples = 20;
samples = cell(N, nsamples);
for i = 1:nsamples
    samples(:,i) = sample_bnet(bnet);
end
data = cell2num(samples);
bnet2 = mk_bnet(dag,node_sizes,'discrete',discrete_nodes);
seed = 0;
rand('state',seed);
bnet2.CPD{C} = tabular_CPD(bnet2,C);
bnet2.CPD{S} = tabular_CPD(bnet2,S);
bnet2.CPD{R} = tabular_CPD(bnet2,R);
bnet2.CPD{W} = tabular_CPD(bnet2,W);
bnet3 = learn_params(bnet2,data);
实验结果:
手动给出的CPT         
nsamples=20        
nsamples=200      
nsamples=2000
查看网络中节点条件概率的方法:
%查看节点C的条件概率
s = struct(bnet.CPD{C})
s.CPT

 
可以看出,随着训练样本数的增加,学习到的条件概率表越来越逼近于手动给出的条件概率表。
u       结构学习实验:
这里我主要作了两个实验,一个是基于上面“草地潮湿原因模型”例子,首先手动建立好贝叶斯网bnet,然后使用函数sample_bnet(bnet)产生训练样本,制定节点顺序和最大父亲节点数,代入K2算法,进行结构学习,并比较了不同训练样本数(nsamples)的情况下,学习到的结构和实际结构的差异。实验结果如下:
可以看出当样本数达到一定的值以后,K2算法可以很好的建立出需要的贝叶斯网络结构。
 
 
1.手动给出的结构                    2.nsamples=10
 
3.nsamples=20                         4.nsamples=30
 
另一个是根据叶进,林士敏的《基于贝叶斯网络的推理在移动客户中流失分析中的应用》提到的使用K2算法进行结构学习方法,通过手动构造相应数据,最后实现了该算法,成功实现了模型的建立,而且与论文中给出的模型比较接近。实验部分代码如下:
n = 6;
ns = [3,3,2,2,2,2];
names = {'A','B','C','D','E','class'};
A = 1; B = 2; C = 3; D = 4;E = 5; class = 6;
order = [4 5 6 3 2 1];
max_fan_in = 2;
result_matrix = zeros(ns(class),ns(class));
fn = 'e:/data.txt';
load(fn);
data_train1 = data';
[num_attrib num_cases] = size(data_train1);
data_train = zeros(num_attrib, num_cases);
dag = zeros(n,n);
dag = learn_struct_k2(data_train,ns,order,'max_fan_in',max_fan_in);%结构学习
bnet = mk_bnet(dag,ns);
priors = 1;
seed = 0;
rand('state', seed);
for i = 1:n
    bnet.CPD{i} = tabular_CPD(bnet,i,'CPT','unif','prior_type','dirichlet','dirichlet_type','BDeu','dirichlet_weight',priors);
end
bnet2 = bayes_update_params(bnet,data_train);%更新条件概率表
实验结果如下,虽然比较接近作者给出的结构,但多了几条边,而且因为训练样本是自己手动给出的,不是实际数据,所以学习到的条件概率表偏离较大。

原创粉丝点击