一 算法背景

贝叶斯网络结构学习就是从给定的数据集中学出贝叶斯网络结构,即各节点之间的依赖关系,即对于网络中任意两个节点,我们要判断它们之间是否有边相连,如果相连,边的方向是从谁指向谁。我们自然会想到,每次取两个边测试并确定它们之间的状态,直至所有边与边之间的关系都被确定。然而具体实施的时候,我们遇到两个问题,一是如何对边进行测试;二是如何减少测试的次数以提高效率。

二 预备知识:马尔科夫毯

首先介绍一下马尔科夫毯(Markov Blanket)。一旦确定了马尔科夫毯,我们可以减少独立性测试的范围。

1.马尔科夫毯定义

形式化定义为:对于任意变量X∈U,其马尔科夫毯是一个变量集B(X)⊆U,且对任意Y∈U-B(X)-{X},满足X⊥Y|B(X)。

通俗理解就是,对一个贝叶斯网,假设其节点集为U,任选某个节点X,我们求出其马尔科夫毯B(X),B(X)是一个全集U的子集。那么当马尔科夫毯B(X)中的节点已知时,剩余部分节点(从全集U中除去X及B(X))与X独立。也就是B(X)将其他的节点对X的影响屏蔽了。

2.马尔科夫毯实例

某个节点的马尔科夫毯包含这个节点的父变量,孩子节点以及孩子节点的父节点。如下图中,对于节点X,其马尔科夫毯是图中灰色的部分,可以验证当图中灰色部分已知时,X和图中除去灰色部分的其他节点都是独立的。为什么马尔科夫毯包含这些节点呢?首先对于节点X,与其有直接连边的节点一定是相互依赖的,所以这些节点,也就是X的父节点和孩子节点只能被放入马尔科夫毯中。此外,如果X的孩子节点是一个collider,那么根据D-Separation(关于d-分离,可以看一下这篇 ),在已知collider的条件下,collider的两个父节点是相互依赖的,所以节点X的孩子变量的父节点也要放入马尔科夫毯中。

java实现贝叶斯网络进行故障诊断 贝叶斯网络结构训练_ide

3.如何求出马尔科夫毯

上面因为有已经建立依赖的图,我们可以直接看出马尔科夫毯。但实际处理时,依赖图是我们的最终目标。现在假设我们没有依赖图,但是有节点之间的独立性关系。下面介绍一种算法,当给定一个节点X,可以得到其马尔科夫毯B(X)。算法共分为两个阶段:grow和shrink。直观的讲,就是定义一个集合存储候选的B(X)。我们在grow阶段尽可能的把潜在节点放入B(X)中;而在shrink阶段,我们再对B(X)中节点进行严格检测,把错误的节点剔除出去。具体算法如下图3.2。

java实现贝叶斯网络进行故障诊断 贝叶斯网络结构训练_点集_02

step1定义一个集合S来表示马尔科夫毯,一开始自然是空集。

step2是grow阶段,定义一个节点集R=U-S-{X},我们遍历节点集R中的节点,假设当前遍历到Y,进行条件独立性测试(conditional independence test,CI),即在给定S的条件下,如果X和Y不独立,那么就将Y放入S中。

我们要持续进行step2,直到某一次R中没有任何一个节点满足被放入S的条件。然而,step2我们最多只会进行2次。与X有直接连边的节点一定不独立,所以在第一次step2时就会被放入S。在第二次step2时,X的所有父节点和孩子节点都已经被放入S中了,那么X的孩子节点的父节点在S已知的条件下与X不独立,所以也保证一定会被放入S中。

在step2中,可以保证马尔科夫毯中的节点一定会被放入S中,然而一些不属于马尔科夫毯的节点也会被错误地放入S中,如下图

java实现贝叶斯网络进行故障诊断 贝叶斯网络结构训练_ide_03

上图是step2中的某一刻遍历时的情况,虚线表示underlying net,我们要求出A的马尔科夫毯。此时集合S包含B、C、G,要测试的是K。显然在S已知时,K和A是不独立的,所以会被放入S中,但K明显不属于A的马尔科夫毯。可以发现这种错误的情况与遍历变量的顺序有关,如果我们先测试D,那么D会被放入S,那么在后续测试K时,K与A将在S的条件下独立,就不会被放入S中。然而遍历的顺序很难确定,通常都是随机的,所以我们要引入一个shrink阶段,也就是step3,将错误节点从S中除去。

在step3中,遍历S中的所有节点,假设当前遍历到节点Y,如果满足X⊥Y|S-{Y},那么就将Y从S中移出。在step2中,我们保证马尔科夫毯中的所有节点都被放入S中,根据定义,当马尔科夫毯中节点已知时,X与其他所有节点独立。所以如果遍历到的Y不属于马尔科夫毯,那么其一定与X独立,因此step3只需执行一次就可将错误变量从S中移除。


三 建立有向无环图

至此我们得到了变量X的马尔科夫毯,接下来我们就要去建立变量间的依赖关系了。在图中我们通常用节点表示变量,依赖关系则表现为一系列节点间的连边。直观上说就是利用马尔科夫毯建立基本的无向图,之后再利用v-structure,无环等性质确定边的方向。详细算法步骤如下:

java实现贝叶斯网络进行故障诊断 贝叶斯网络结构训练_贝叶斯网络_04

step1就是将每个节点的马尔科夫毯都求出来。

step2就是判断每个节点与其马尔科夫毯中节点的连接方式。对某个节点X,遍历其马尔科夫毯。假设遍历到的是Y,我们想判断X和Y是否直接相连。马尔科夫毯中既有孩子节点,又有孩子节点的父节点,前者相连,无论任何情况下都相互依赖;后者不相连,若collider(公共孩子节点)未知则是独立的。利用这个特性,我们对X或Y的马尔科夫毯中节点自由组合,并以组合后的节点集此作为条件集,来进行条件独立性测试测试,当X和Y不直接相连时,我们总是可以找到一个条件集使X和Y不独立,所以只要在任何集合下都依赖,那么变量Y就是与X直接相连的。这里取B(X)或B(Y)对最终的结果没有影响,我们选择长度更小的集合有助于减少条件独立性测试的次数。对所有变量执行相同操作后,我们就获取了整个网络无向连接的方式了。

step3中我们通过找到v-structure来确定网络中某些边的方向。为了找到潜在的v-structure,首先要找到这样的结构:Y和X相连,X和Z相连,Y和Z不相连。也就是遍历所有节点X,对每个X,再遍历其邻居节点集N(X),比如遍历到一个Y,接下来找Z,其实Z就是与X相连但与Y不相连的节点,即Z∈N(X)-N(Y)-{Y}。现在X,Y,Z只能是一个潜在的v-structure,因为其方向还未能确定。为此要判断Y和Z的独立性,所以我们要对Y或Z的马尔科夫毯中节点自由组合,并以组合后的节点集与X的并集作为条件集,来进行条件独立性测试测试。对于非v-structure,我们总能找到一个节点集使其独立。而对于underlying net中的v-structure,当collider(节点X)已知时,其父亲节点一定相互依赖。所以只要在任何节点集上都依赖。Y-X-Z组成了v-structure就可以确定边的方向:Y->X。这里无法保证所有的边都能被确认方向,比如在underlying net中,N(X)只有Y,那么无法找到任何一个Z。或是v-structure的父亲节点存在连边的情况,此时v-structure的父亲节点不会被放入Z可能的集合中。

step4要除去环结构。对于一条边,我们计算包含它的环的个数,找到一条计数最大的边并从图中移除。移除后如果仍有环,再次计算计数最大的边并移除。

step5中,我们要把step4中移除的边逆向添加回图中,添加的顺序正好与step4中移除的顺序相反。

step4和step5我看的不是太明白,比如说step5里,为啥要是相反的顺序,反正就是添加边,而且是全部添加,顺序不同有影响吗。这里只能大体说一说自己的理解,希望其他人可以更正。

在step4中移除,并在step5中反向添加,会不会引入新的环?答案是不会。看下图:

java实现贝叶斯网络进行故障诊断 贝叶斯网络结构训练_点集_05

如果在step4中移除的边是x->y,那么step5反向为y->x,就引入了新的环,这似乎说明算法第5步无法保证步引入新的环。然而无论x与y连边的方向如何,总是会存在环,出现这种情况就意味着underlying net本身就是存在环的,这显然与underlying net的无环性矛盾。

step6我们需要给剩余的边确定方向,对于所有的X和其邻居Y,如果它们之间还没有确定方向,我们来找是否有一条路径从X通往Y,如果有则确定边X->Y。这一步显然是根据无环性来确定方向,因为引入相反的方向一定会引入环。

四 总结

再次回顾开头提到两个问题:

一是如何对边进行测试;解决方法是利用独立性测试,在处理实际样本时,我们通常考虑去计算变量间的相关性,如互信息,卡方检验。

二是如何减少测试的次数以提高效率。解决方法是对每个节点构造其马尔科夫毯,只需要对马尔科夫毯中的节点进行处理。