如何使用贝叶斯网络工具箱
2004-1-7 版
翻译:By 斑斑(QQ:23920620)
联系方式:banban23920620@163.com
安装
安装 Matlab 源码
安装 C 源码
有用的 Matlab 提示
创建你的第一个贝叶斯网络
手工创建一个模型
从一个文件加载一个模型
使用 GUI 创建一个模型
推断
处理边缘分布
处理联合分布
虚拟证据
最或然率解释
条件概率分布
列表(多项式)节点
其它(噪音)确定性节点
神经网络节点
Noisy-or 节点
Softmax(多项式 分对数)节点
根节点
高斯节点
广义线性模型节点
分类 / 回归树节点
其它连续分布
CPD 类型摘要
PCA、ICA 等
模型举例
高斯混合模型
专家系统的混合
专家系统的分等级混合
条件高斯模型
其它混合模型
QMR
MCMC
K2 算法
参数学习
从一个文件里加载数据
从完整的数据中进行最大似然参数估计
先验参数
从完整的数据中(连续)更新贝叶斯参数
数据缺失情况下的最大似然参数估计(EM 算法)
参数类型
结构学习
穷举搜索
爬山算法
主动学习
结构上的 EM 算法
肉眼观察学习好的图形结构
基于约束的方法
推断函数
联合树
消元法
全局推断方法
快速打分
置信传播
采样(蒙特卡洛法)
推断函数摘要
影响图 / 制定决策
DBNs、HMMs、Kalman 滤波器等等
安装
安装 Matlab 代码
1. 下载 FullBNT.zip 文件。
2. 解压文件。
3. 编辑"FullBNT/BNT/add_BNT_to_path.m"让它包含正确的工作路径。
4. BNT_HOME = 'FullBNT 的工作路径';
5. 打开 Matlab。
6. 运行 BNT 需要 Matlab 版本在 V5.2 以上。
7. 转到 BNT 的文件夹例如在 windows 下,键入
8. >> cd C:\kpmurphy\matlab\FullBNT\BNT
9. 键入"add_BNT_to_path",执行这个命令。添加路径。添加所有的文件夹在 Matlab 的路
径下。
10. 键入"test_BNT",看看运行是否正常,这时可能产生一些数字和一些警告信息。(你可
以忽视它)但是没有错误信息。
11. 仍有问题?你是否编辑了文件?仔细检查上面的步骤。
创建你的第一个贝叶斯网络
为了定义一个贝叶斯网络,你必须指定它的图形结构和参数。我们用一个简单的例子依次
看一下它们。(根据 Russell and Norvig, "Artificial Intelligence: a Modern Approach",
Prentice Hall, 1995, p454 改编)
图形结构
设想如下网络
我们创建一个相邻矩阵来指定这个有向无环图
N = 4;
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;
我们给节点按照如下编号:Cloudy = 1, Sprinkler = 2, Rain = 3, WetGrass = 4.在拓扑
次序中,节点是必须被编号的,也就是说:父节点要在子节点前。对于一个更复杂的图来
说,这有点麻烦:我们将在下面(以后)看一看如何避免这个。*注:在原文中“下面”是使用
的超链接,因此,这里的下面并不一定等同目前的上下文关系。后面的文中也是如此,为方便区别,我将
把非上下文关系的“下面”翻译为“以后”或“后面”。
在 Matlab6 中,你可以使用逻辑数组来代替双重数组,这样可以缩小四倍。
dag = false(N,N);
dag(C,[R S]) = true;
..
然而,一些图的功能(比如 无环的)不支持逻辑数组
你可以使用后面讨论的方法来观察结果图形结构。
关于 GUIs 的详细内容,点击这里。
创建贝叶斯网络的框架
除了指定图形结构,我们必须指定每个节点的大小和类型。如果一个节点是离散的,它的
大小就是该节点可能采取的数值;如果一个节点是连续的,它就是一个矢量,它的大小就
是矢量的长度。在这个例子中,我们假定所有的节点是离散的和二进制的。
discrete_nodes = 1:N;
node_sizes = 2*ones(1,N);
如果节点不是二进制的,我们可以这样键入。
node_sizes = [4 2 3 5];
这意味 Cloudy 有四种可能的值,Sprinkler 有两种可能的值等等。
注意,这些都是基数而不是序数。他们不能用任何方式排序,如“低”“中”“高”
现在,我们准备建立贝叶斯网络:
bnet = mk_bnet(dag, node_sizes, 'discrete', discrete_nodes);
默认情况下,所有的节点都被假定为离散的,因此我们可以只写成
bnet = mk_bnet(dag, node_sizes);
你也可以指定那些节点是可以被观察的。如果你不知道或者预先没有确定,那么就使用空
的列表。
onodes = [];
bnet = mk_bnet(dag, node_sizes, 'discrete', discrete_nodes, 'observed', onodes);
注意你可以使用一个名字或语法值来指定可选参数。这在 BNT 的函数中很普遍。通常,要
找到一个函数更多的信息(例如,可以使用那些可选参数),请按如下方式查看它的帮助文
档。
help mk_bnet
请参阅 useful Matlab tips.
将一个名字和节点关联起来可以按如下方式:
bnet = mk_bnet(dag, node_sizes, 'names', {'cloudy','S','R','W'}, 'discrete', 1:4);
你可以用它的名字引用一个节点:
C = bnet.names('cloudy'); % bnet.names 是一个关联数组;
bnet.CPD{C} = tabular_CPD(bnet, C, [0.5 0.5]);
这个特征使用我自己的关联数组类。
参数
一个模型由图形结构和参数组成。参数用 CPD(条件概率分布)来表达.CPD 定义了一个节点
与它父节点间的概率分布。(我们将交替使用“节点”项和“随机变量”项)最简单的一种
CPD 是一个表格(多维数组),与之匹配的是所有节点类型都是离散的。值得注意的是离散
值是被假定为不能用任何方式排序的。换句话说,它代表绝对数量,如男或女,而非序
数,如低、中、高。(我们将在后面更详细的讨论 CPD 的类型)
列表状的 CPDs,也叫 CPTs(条件概率表),是作为多维数组储存的。这些维数作为节点以
相同的方式安排。例如:节点 4(WetGrass)的 CPT 是与 Sprinkler (2), Rain (3)和 WetGrass
(4)本身挂钩的。因此,子节点通常是最后一维。如果一个节点没有父节点,它的 CPT 是一
个列向量,代表它的先验概率。要注意的是在 Matlab 里(不同于 C),数组的索引是从 1
开始安排在内存中的,这样第一个索引切换的最快,例如在节点 4(WetGrass)的 CPT 中(如
下)
这里我们按惯例 false(假)==1, true(真)==2. 我们可以在 Matlab 中创建如下 CPT:
CPT = zeros(2,2,2);
CPT(1,1,1) = 1.0;
CPT(2,1,1) = 0.1;
...
这里有一个更简单的方法:
CPT = reshape([1 0.1 0.1 0.01 0 0.9 0.9 0.99], [2 2 2]);
事实上,我们不需要改造这个数组,CPD 构造函数会为我们做这件事。因此我们可以只要
这样写。
bnet.CPD{W} = tabular_CPD(bnet, W, 'CPT', [1 0.1 0.1 0.01 0 0.9 0.9 0.99]);
其它节点按类似方法创建(对于可选参数使用旧的语法)
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]);
随机参数
如果我们没有指定 CPT,随机参数将被创建。也就是说,CPT 的每一行将按均匀分布创建。
为了确保可重复的结果,使用:
rand('state', seed);
randn('state', seed);
通过控制无规度(熵),你可以从狄利克雷分布采样CPT的每一行。如果P<<1,将促使“确
定性”CPTs(一个条目接近 1,剩余的接近 0)。如果P=1,每个条目从U[0,1]间形成。如
果P>>1,所有条目将全接近 1/K,K是这个节点的元数,也就是每一行几乎一致。你可以象
下面这样做,假定这个节点是数目i,ns是它的node_size。
k = ns(i);
ps = parents(dag, i);
psz = prod(ns(ps));
CPT = sample_dirichlet(p*ones(1,k), psz);
bnet.CPD{i} = tabular_CPD(bnet, i, 'CPT', CPT);
从文件加载一个网络
如果你已经拥有一个基于 XML 的贝叶斯交换格式(BNIF)的贝叶斯网络,(例如,从 Bayes
Net repository 下载一个),你可以用 Ken Shan 写的 BIF-BNT Java program 转换它成为
BNT 格式(这不需要最新的)。
目前还不能保存或加载一个 BNT 的 matlab 对象到文件当中,但是如果你修改了类的构造函
数,还是很容易确定的。
使用 GUI 创建一个模型
续。
图形可视化
图形可视化见原始文件超链接
Philippe LeRay 用 matlab 写了 BNT GUI
Imme Ebert-Uphoff 写的工具包 LinkStrength
Senthil Nachimuthu 用 Java 写的开源软件 projeny using Java. 这是 BNJ 的后