我们之前提到的有向图不能有环,即带环的条件概率分解公式一定是缺少变量的
P ( A B C D ) = P ( A ) P ( B ∣ A ) P ( C ∣ B ) P ( D ∣ C ) P(ABCD)=P(A)P(B|A)P(C|B)P(D|C) P(ABCD)=P(A)P(B∣A)P(C∣B)P(D∣C)
这是是一个非常简单的推理链,
P ( B = i ) = ∑ a P ( B = i ∣ a ) P ( a ) P(B=i)=\sum_{a}P(B=i|a)P(a) P(B=i)=a∑P(B=i∣a)P(a)
P ( D ) = ∑ c P ( D ∣ C ) ∑ b P ( C ∣ B ) ∑ a P ( A ) P ( B ∣ A ) P(D)=\sum_{c}P(D|C)\sum_{b}P(C|B)\sum_{a}P(A)P(B|A) P(D)=c∑P(D∣C)b∑P(C∣B)a∑P(A)P(B∣A)
怎么找到最合适的消解边缘的方法呢,一种可能的执行方式是使用和积变量消解算法(sum-product Variable Elimination Algorithm)
A =matrix(c(0.8, 0.2), 2, 1)
B =matrix(c(0.6, 0.4, 0.3, 0.7), 2, 2)
C =matrix(c(0.5, 0.5, 0.8, 0.2), 2, 2)
D =matrix(c(0.3, 0.7, 0.4, 0.6), 2, 2)
B
A
B_prior =t(A) %*%t(B)
C_prior =B_prior %*%t(C)
D_prior =C_prior %*%t(D)
D_prior
输出
> B
[,1] [,2]
[1,] 0.6 0.3
[2,] 0.4 0.7
> A
[,1]
[1,] 0.8
[2,] 0.2
> D_prior
[,1] [,2]
[1,] 0.3362 0.6638
联结树算法的名字基于下列事实:在执行数值计算之前,我们会把概率图模型转换为一个树,它的一些属性保证后验概率的高效计算。
算法的一个特点是不仅计算查询中的后验概率,还要计算其他未被观察到的变量的后验概率?为了得到这样的结果,联结树算法结合了之前变量消解算法的通用性,事实上变量消解可以用在任何没有回路的树上,和积算法可以保存中间结果?。因为变量消解算法只能用在树中,因此我们需要把带有回路的图转换为表示等价分布分解形式的树。(这段话看起来干货很多,但是真的看不懂)
从哪个经典的例子开始 P ( A B C D ) = P ( A ) P ( B ∣ A ) P ( C ∣ B ) P ( D ∣ C ) P(ABCD)=P(A)P(B|A)P(C|B)P(D|C) P(ABCD)=P(A)P(B∣A)P(C∣B)P(D∣C),对每一个因子使用贝叶斯规则(对每一个条件概率进行替换)
P ( A ) ⋅ P ( A , B ) P ( A ) ⋅ P ( B , C ) P ( B ) ⋅ P ( C , D ) P ( C ) = P ( A , B ) P ( B , C ) P ( C , D ) P ( B ) P ( C ) P(A)\cdot\frac{P(A,B)}{P(A)}\cdot \frac{P(B,C)}{P(B)}\cdot\frac{P(C,D)}{P(C)}=\frac{P(A,B)P(B,C)P(C,D)}{P(B)P(C)} P(A)⋅P(A)P(A,B)⋅P(B)P(B,C)⋅P(C)P(C,D)=P(B)P(C)P(A,B)P(B,C)P(C,D)
联结树的概率分布可以写作:
P ( χ ) = ∏ c ϵ C φ ( c ) ∏ s ϵ S φ ( s ) P(\chi)=\frac{\prod_{c\epsilon C}^{}φ(c)}{\prod_{s\epsilon S}^{}φ(s)} P(χ)=∏sϵSφ(s)∏cϵCφ(c)
其中分子代表联结树每一个聚类(团)的因子,分母代表每一个分隔的因子,下面以一个例子来说明
联结树就是从一个聚类传递信息给另一个聚类实现的过程,每一个聚类都会包含自身变量的后验概率分布。最后找出任意变量的后验概率都可以归结为对其中一个聚类使用贝叶斯规则,并边缘化我们不感兴趣的变量。
R语言包包含了联结树实现的完整过程,第一章中,我们使用的推断算法就是联结树法,下面我们通过一个具体的试验来加深印象:
上图可以用分解公式
P ( A B C D E F ) = P ( F ) P ( C ∣ F ) P ( E ∣ F ) P ( A ∣ C ) P ( D ∣ E ) P ( B ∣ A , D ) P(ABCDEF)=P(F)P(C|F)P(E|F)P(A|C)P(D|E)P(B|A,D) P(ABCDEF)=P(F)P(C∣F)P(E∣F)P(A∣C)P(D∣E)P(B∣A,D)
并可以写出如下代码:
library(gRain)
# 定义一个二元取值变量
val =c("true", "false")
# 两个就是先验概率
F =cptable(~F, values = c(10, 90), levels = val)
C =cptable(~C |F, values = c(10, 90, 20, 80), levels = val)
E =cptable(~E |F, values = c(50, 50, 30, 70), levels = val)
A =cptable(~A |C, values = c(50, 50, 70, 30), levels = val)
D =cptable(~D |E, values = c(60, 40, 70, 30), levels = val)
B =cptable(~B |A:D, values = c(60, 40, 70, 30, 20, 80, 10, 90), levels = val)
plist =compileCPT(list(F, C, E, A, D, B))
plist
print(plist$F)
print(plist$C)
print(plist$B)
结果可以看到:
> plist
CPTspec with probabilities:
P( F )
P( C | F )
P( E | F )
P( A | C )
P( D | E )
P( B | A D )
> print(plist$F)
F
true false
0.1 0.9
attr(,"class")
[1] "parray" "array"
> print(plist$C)
F
C true false
true 0.1 0.2
false 0.9 0.8
attr(,"class")
[1] "parray" "array"
> print(plist$B)
, , D = true
A
B true false
true 0.6 0.7
false 0.4 0.3
, , D = false
A
B true false
true 0.2 0.1
false 0.8 0.9
attr(,"class")
[1] "parray" "array"
接下来调用联结树算法:
# 调用联结树算法
jtree =grain(plist)
jtree
# 执行查询
querygrain(jtree, nodes = c("C"), type = "marginal")
querygrain(jtree, nodes = c("B"), type = "marginal")
querygrain(jtree, nodes = c("A","B"), type = "joint")
querygrain(jtree, nodes = c("A","B", "C"), type = "joint")
querygrain(jtree, nodes = c("A", "D"), type = "joint") # independent
# asumption
jtree2 =setEvidence(jtree, evidence = list(F = "true"))
querygrain(jtree2, nodes = c("C"), type = "marginal")
我们可以看到,一旦建树完成,我们可以求任意节点的边缘分布,以及节点之间的联合分布,同时我们还可以进行假设。上面代码的结果为:
$C
C
true false
0.19 0.81
> querygrain(jtree, nodes = c("B"), type = "marginal")
$B
B
true false
0.478564 0.521436
> querygrain(jtree, nodes = c("A","B"), type = "joint")
B
A true false
true 0.309272 0.352728
false 0.169292 0.168708
> querygrain(jtree, nodes = c("A","B", "C"), type = "joint")
, , B = true
A
C true false
true 0.044420 0.047630
false 0.264852 0.121662
, , B = false
A
C true false
true 0.050580 0.047370
false 0.302148 0.121338
attr(,"class")
[1] "parray" "array"
> querygrain(jtree, nodes = c("A", "D"), type = "joint") # independent
D
A true false
true 0.44218 0.21982
false 0.22582 0.11218
> # asumption
> jtree2 =setEvidence(jtree, evidence = list(F = "true"))
> querygrain(jtree2, nodes = c("C"), type = "marginal")
$C
C
true false
0.1 0.9
同时我们还可以发现,一旦我们给出F和A的假设会极大地改变C的分布。