题目:贝叶斯网络结构学习之K2算法(基于FullBNT-1.0.4的MATLAB实现)

有关贝叶斯网络结构学习的一基本概念可以参考:贝叶斯网络结构学习方法简介

有关函数输入输出参数的解释可以参考:贝叶斯网络结构学习若干问题解释

对于应用贝叶斯评分进行结构学习的研究,国外的学者做了很多相关的工作。其中最著名的是Cooper和Herskovits提出的K2算法,他们应用贝叶斯评分和爬山法搜索的方法来优化网络模型,其中的评分函数即为贝叶斯评分的一种简化,又被称为K2评分。(摘自【张鸿勋. 基于K2评分的贝叶斯网结构学习算法的研究[D]. 北京工业大学, 2009.】)

K2算法于【Cooper G F, Herskovits E. A Bayesian method for the inductionof probabilistic networks from data[J]. Machine Learning, 1992, 9(4):309-347.】中提出,算法流程如下:

算法第10行中的Pred(x_i)的意思是根据节点顺序(nodeordering)排在x_i前面的节点:

算法第7、10、11行出现的函数g即为评分函数:

为什么取名叫K2算法呢?原文中给出了解释:

本文基于FullBNT-1.0.4工具箱,可自行搜索下载链接,附录1给出了几个参考链接。在MATLAB中设置第三方工具箱的步骤参见附录2,若MATLAB版本不同,可自行搜索添加步骤,大同小异。

工具箱添加完成后,即可在MATLAB的命令行窗口(commandwindows)使用help命令查看函数的帮助文件,使用edit命令打开函数的源文件。

函数learn_struct_K2.m目录:\FullBNT-1.0.4\BNT\learning\learn_struct_K2.m,接下来简单解释一下输入和输出参数。

输入:(注意除特别标注外,其余均来自learn_struct_K2.m本身)

data:大小n*m,其中n为节点个数,m为数据集的大小(即流程中的databaseD)

% data(i,m) = value of node i in case m (can be a cell array).
        ns:大小n*1,每个node可能的取值个数(一般要求是离散值)

以下注释来自\FullBNT-1.0.4\BNT\general\mk_bnet.m,learn_struct_K2.m中的注释太简单

% node_sizes(i) is the number of values node i can take on,
%   or the length of node i if i is a continuous-valued vector.
% node_sizes(i) = 1 if i is a utility node. 
        order:大小n*1,节点之间顺序,K2算法需要先设定各节点之间的顺序,即专家知识

% order(i) is the i'th node in the topological ordering.
        max_fan_in:大小n*1,每个节点最大的父亲节点个数(即流程中的upper bound u),默认为节点个数

% max_fan_in - this the largest number of parents we allow per node [N]
       scoring_fn:评分函数的类型,默认为贝叶斯评分

% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
%              Currently, only networks with all tabular nodes support Bayesian scoring.

输出:

dag:大小n*n,若第i个节点是第j个节点的父亲,则dag(i,j)=1,否则dag(i,j)=0

函数\FullBNT-1.0.4\BNT\learning\learn_struct_K2.m的代码:

function dag = learn_struct_K2(data, ns, order, varargin)
% LEARN_STRUCT_K2 Greedily learn the best structure compatible with a fixed node ordering
% best_dag = learn_struct_K2(data, node_sizes, order, ...)
%
% data(i,m) = value of node i in case m (can be a cell array).
% node_sizes(i) is the size of node i.
% order(i) is the i'th node in the topological ordering.
%
% The following optional arguments can be specified in the form of name/value pairs:
% [default value in brackets]
%
% max_fan_in - this the largest number of parents we allow per node [N]
% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
%              Currently, only networks with all tabular nodes support Bayesian scoring.
% type       - type{i} is the type of CPD to use for node i, where the type is a string
%              of the form 'tabular', 'noisy_or', 'gaussian', etc. [ all cells contain 'tabular' ]
% params     - params{i} contains optional arguments passed to the CPD constructor for node i,
%              or [] if none.  [ all cells contain {'prior', 1}, meaning use uniform Dirichlet priors ]
% discrete   - the list of discrete nodes [ 1:N ]
% clamped    - clamped(i,m) = 1 if node i is clamped in case m [ zeros(N, ncases) ]
% verbose    - 'yes' means display output while running [ 'no' ]
%
% e.g., dag = learn_struct_K2(data, ns, order, 'scoring_fn', 'bic', 'params', [])
%
% To be backwards compatible with BNT2, you can also specify arguments as follows
%   dag = learn_struct_K2(data, node_sizes, order, max_fan_in)    
%
% This algorithm is described in
% - Cooper and Herskovits,  "A Bayesian method for the induction of probabilistic
%      networks from data", Machine Learning Journal 9:308--347, 1992
 
[n ncases] = size(data);
 
% set default params
type = cell(1,n);
params = cell(1,n);
for i=1:n
  type{i} = 'tabular';
  %params{i} = { 'prior', 1 };
  params{i} = { 'prior_type', 'dirichlet', 'dirichlet_weight', 1 };
end
scoring_fn = 'bayesian';
discrete = 1:n;
clamped = zeros(n, ncases);
 
max_fan_in = n;
verbose = 0;
 
args = varargin;
nargs = length(args);
if length(args) > 0 
  if isstr(args{1})
    for i=1:2:nargs
      switch args{i},
       case 'verbose',    verbose = strcmp(args{i+1}, 'yes');
       case 'max_fan_in', max_fan_in = args{i+1}; 
       case 'scoring_fn', scoring_fn = args{i+1};
       case 'type',       type = args{i+1}; 
       case 'discrete',   discrete = args{i+1}; 
       case 'clamped',    clamped = args{i+1}; 
       case 'params',     if isempty(args{i+1}), params = cell(1,n); else params = args{i+1};  end
      end
    end
  else
    max_fan_in = args{1};
  end
end
 
dag = zeros(n,n);
 
for i=1:n
  ps = [];
  j = order(i);
  u = find(clamped(j,:)==0);    
  score = score_family(j, ps, type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
  if verbose, fprintf('\nnode %d, empty score %6.4f\n', j, score); end
  done = 0;
  while ~done & (length(ps) <= max_fan_in)
    pps = mysetdiff(order(1:i-1), ps); % potential parents
    nps = length(pps);
    pscore = zeros(1, nps);
    for pi=1:nps
      p = pps(pi);
      pscore(pi) = score_family(j, [ps p], type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
      if verbose, fprintf('considering adding %d to %d, score %6.4f\n', p, j, pscore(pi)); end
    end
    [best_pscore, best_p] = max(pscore);
    best_p = pps(best_p);
    if best_pscore > score
      score = best_pscore;
      ps = [ps best_p];
      if verbose, fprintf('* adding %d to %d, score %6.4f\n', best_p, j, best_pscore); end
    else
      done = 1;
    end
  end
  if ~isempty(ps) % need this check for matlab 5.2
    dag(ps, j) = 1;
  end
end

这个函数很简单,基本与上图中的K2流程一模一样,函数调用了评分函数score_family.m,可以通过参数设置不同类型的评分函数。

工具箱提供了函数learn_struct_K2.m的使用例子k2demo1.m,文件目录:\FullBNT-1.0.4\BNT\examples\static\StructLearn\k2demo1.m

N = 4;
dag = zeros(N,N);
%C = 1; S = 2; R = 3; W = 4;
C = 4; S = 2; R = 3; W = 1; % arbitrary order
dag(C,[R S]) = 1;
dag(R,W) = 1;
dag(S,W)=1;
 
false = 1; true = 2;
ns = 2*ones(1,N); % binary nodes
 
bnet = mk_bnet(dag, ns);
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]);
 
seed = 0;
rand('state', seed);
randn('state', seed);
ncases = 100;
data = zeros(N, ncases);
for m=1:ncases
  data(:,m) = cell2num(sample_bnet(bnet));
end
 
order = [C S R W];
max_fan_in = 2;
 
%dag2 = learn_struct_K2(data, ns, order, 'max_fan_in', max_fan_in, 'verbose', 'yes');
  
sz = 5:5:50;
for i=1:length(sz)
  dag2 = learn_struct_K2(data(:,1:sz(i)), ns, order, 'max_fan_in', max_fan_in);
  correct(i) = isequal(dag, dag2);
end
correct
 
for i=1:length(sz)
  dag3 = learn_struct_K2(data(:,1:sz(i)), ns, order, 'max_fan_in', max_fan_in, 'scoring_fn', 'bic', 'params', []);
  correct(i) = isequal(dag, dag3);
end
correct
        这个例子很简单:定义贝叶斯网络-->根据贝叶斯网生成数据集-->根据数据集使用K2算法学习贝叶斯网络结构,并与定义的真实网络结构作对比,以判断K2算法重构性能。

前7行代码是自己定义一个贝叶斯网络结构,第9~16行代码是给出这个贝叶斯网的条件概率表(即,参数),第18~25行是根据前16行定义的贝叶斯网来生成数据集。剩下的代码是分别采用了两种评分函数(第34行采用的是默认的贝叶斯评分,第41行采用的是BIC评分)根据数据集使用K2算法学习网络结构,并比较网络结构与真实结构的差异。值得注意的是,两处调用learn_struct_K2均未直接使用整个数据集,而是将数据集前50个每5个分成一小份,第1次使用数据集前5个,第2次使用数据集前10个,第3次使用数据集前15个,依此类推,每次将学得的网络结构与真实的网络结构作对比。通过结果可以发现,当数据集大于30时即可基本学习到正确的贝叶斯网络结构。

运行输出结果如下:

correct =
 
     0     0     0     0     0     1     1     1     1     1
 
 
correct =
 
     0     0     0     0     0     1     0     1     1     1
        (@20180922更新)鉴于评论中有网友问这个结果什么意思,那今天就补充这一段。注意sz=5:5:50,共包含10个元素值,而后面分别调用了10次learn_struct_K2学习dag2和dag3,尤其注意输入的data在每次循环时取前sz(i)个,因此共得到了10个dag2和10个dag3,每次循环会把学习到的dag2(或dag3)与真实的dag比较(isequal函数),若两个矩阵相等则输出为1,反之为0,比较结果存入correct。所以上面两个correct分别代表了10个dag2和10个dag3与真实dag的关系。从第1个correct输出可以看出,当learn_struct_K2输入的data样本小于等于25时学到的dag2与真实的dag均不相等(correct前五个值为0),当learn_struct_K2输入的data样本大于等于30时学到的dag2与真实的dag均相等(correct前五个值为1);同理解释第2个correct即可。
         有了以上例子,可进一步琢磨每一个输入参数的含义,进而可将learn_struct_K2函数用起来了,但是K2算法需要事先给定节点顺序,好处是可以充分利用专家知识,坏处是如果无法事先确定节点顺序怎么办?所以我们还需要掌握一些不需要输入节点顺序的贝叶斯网络结构学习函数(当不知道节点顺序但又想用K2算法时,有一种做法是随机生成若干个顺序如1000个分别学习多个贝叶斯网络结构,然后选择一个最好的结构)。另外,在learn_struct_K2中调用了评分函数score_family,既然评分函数都有了,那么就可以自行设计搜索策略例如模拟退火、遗传算法等进而得到新的基于评分的贝叶斯网络结构学习算法。

附录1:BNT下载链接

原来作者(http://www.cs.ubc.ca/~murphyk/)的主页的BNT工具箱链接已经失效,在网上搜了几个下载链接,我用的是FullBNT-1.0.4.zip,在CSDN下载的。

1、FullBNT-1.0.4.zip

http://download.csdn.net/download/yinzuooguigui/9014175

http://www.pudn.com/downloads464/sourcecode/math/detail1949349.html

https://pan.baidu.com/s/1o7X2Sqe 密码vted

https://github.com/bayesnet/bnt

2、FullBNT-1.0.7.zip

https://pan.baidu.com/share/link?shareid=3829960033&uk=2955152529

3、作者murphyk主页Bayes工具箱汇总

http://www.cs.ubc.ca/~murphyk/Bayes/junk/bnsoft.html

上面链接列出了很多Bayes工具箱,虽然很多链接已经失效了。

附录2:在MATLAB中添加工具箱的步骤

以我正在使用的MATLAB R2014a为例,其它版本请自行在网上搜索,大同小异。

第1步:单击“设置路径”(matlab版本不同,主要是这一步不同,只要找到“设置路径”一般后面步骤都差不多)

第2步:单击“添加并包含子文件夹”

第3步:找到BNT工具箱目录,例如FullBNT-1.0.4,单击“选择”,如下图所示,再单击“保存”后再单击“关闭”即可。

此时,你就可以像使用MATLAB自带的函数一样使用BNT工具箱里的函数了,若想查看某函数的代码,可以在MATLAB的命令行窗口(command windows)使用edit命令,语法与help命令相同,例如“edit mk_bnet”即可打开mk_bnet.m源文件。

————————————————
版权声明:本文为CSDN博主「jbb0523」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jbb0523/article/details/78804963

贝叶斯网络结构学习之K2算法(基于FullBNT-1.0.4的MATLAB实现)相关推荐

  1. 贝叶斯网络结构学习(基于BDAGL工具箱的MATLAB实现)

    题目:贝叶斯网络结构学习(基于BDAGL工具箱的MATLAB实现) 有关贝叶斯网络结构学习的一基本概念可以参考:贝叶斯网络结构学习方法简介 有关函数输入输出参数的解释可以参考:贝叶斯网络结构学习若干问 ...

  2. 基于搜索的贝叶斯网络结构学习算法-K2

    部分内容取自:[Cooper and Herskovits, 1991] Cooper, G. and Herskovits, E. (January, 1991). A Bayesian metho ...

  3. 贝叶斯网络结构学习若干问题解释

    题目:贝叶斯网络结构学习若干问题解释 本篇主要为后续讲解具体结构学习算法打基础,共解释以下几个问题: 1.用于贝叶斯网络结构学习的数据集如何存储? 2.学得的贝叶斯网络结构如何存储? 3.什么是节点顺 ...

  4. 贝叶斯网络结构学习之连续参数处理方法

    题目:贝叶斯网络结构学习之连续参数处理方法 注:本文有更新,参见<有关属性离散化算法CACC的补充说明>和<有关属性离散化算法CACC的再次补充说明>.以下为原文: 首先必须说 ...

  5. R语言做贝叶斯网络结构学习

    文章目录 本文使用pcalg包做贝叶斯网络结构的学习 #实例分析 ##pcalg包的安装 安装pcalg包时由于有些依赖包已经被CRAN撤掉,所以安装起来有些技巧. 以下是安装代码: install. ...

  6. 贝叶斯网络结构学习方法

    文章目录 1. 完备数据的结构学习 基于评分搜索 定义 评分函数 基于贝叶斯统计的评分 K2评分 BD(Bayesian Dirichlet)评分 BDeu(Bayesian Dirichlet eu ...

  7. 贝叶斯网络学习总结与中科院…

    原文地址:贝叶斯网络学习总结与中科院贝叶斯网络视频教程下载 作者:jiang-19861112 贝叶斯网络结构学习总结 贝叶斯网络视频下载网址:http://www.abab123.com/bbs/d ...

  8. 【因果学习】贝叶斯网络结构学习方法

      随机对照试验是发现因果关系的黄金准则,然而现实世界中很多问题往往由于道德伦理的原因不允许我们设置干预进行试验,这就引发了在观测数据上学习因果关系的需求.贝叶斯网络是概率论与图论相结合的产物,它用图 ...

  9. 基于图正则化的贝叶斯宽度学习系统

    摘要 作为一种前馈神经网络,宽度学习系统因其精度高.训练速度快且能有效代替深度学习方法而备受研究者的关注.然而,宽度学习系统存在对网络中的特征节点个数比较敏感且求伪逆方式易使模型出现过拟合等问题.为此 ...

最新文章

  1. 总结个人项目设计保障5大原则
  2. 【转载】基于ASP.NET Web Application的插件实现,附DEMO
  3. 四、Git多人开发:不同人修改了同文件的相同区域如何处理?
  4. html form src,form.html
  5. 仅需一行代码,你的纯文本秒变Markdown
  6. python求和_用python求和
  7. IIS和APACHE共用80端口的方法
  8. css不继承上级样式_CSS基础知识(一)
  9. java B2B2C 源码多租户电子商城系统-Spring Cloud整合Netflix Archaius介绍
  10. linux下c程序调用reboot函数实现直接重启【转】
  11. Zcash — 完全隐匿货币流向
  12. 使用ffmpeg合并.h264文件
  13. 4399ATAPI讲解用例配置篇
  14. qpython3打开app_Android QPython3 扩展:调用其他App打开文件
  15. 统计每个日期新用户的次日留存率
  16. php mysql可以跨站_Laravel5中防止XSS跨站攻击的方法
  17. 为什么不居中(CellRangeAddress),关于excel导出合并单元格
  18. 计算机行业热点的专业信息渠道,新南威尔士大学信息技术硕士专业详解 通往IT大神的必经之路...
  19. Scrapy学习笔记 爬取w3school
  20. Microsoft Edge:你不能不知道的6个Web开发者工具

热门文章

  1. 慧荣科技获GSA年度大奖
  2. 关于宝塔下的项目中的php不能访问的问题
  3. 进阶之初探nodeJS
  4. robot.txt 搜索引擎 蜘蛛爬虫 搜索规则
  5. mysql 常用操作命令
  6. golang中slice切片的修改操作
  7. Google收购安全分析软件厂商Zynamics
  8. 复位最佳方式:异步复位,同步释放
  9. 单IP无TMG拓扑Lync Server 2013:边缘服务器
  10. 30分钟,让你彻底明白Promise原理