贝叶斯网络的python实现:Monty Hall问题的求解

前两节分别介绍了贝叶斯图模型的必要性以及贝叶斯网络的基本原理,本节将通过一个简单的问题介绍贝叶斯网络的python实现。

三门问题(Monty Hall problem)亦称为蒙提霍尔问题、蒙特霍问题或蒙提霍尔悖论,是电视节目中一个简单的游戏(主持人叫Monty Hall),游戏中有三扇门(编号为1、2、3号门),一扇门后面是一辆车,剩下两扇门后面各有一只山羊,此时随机的选择一扇门(并不打开它),比如2号门。此时,主持人(后面我们称其名字monty)是知道汽车藏在哪扇门后面的,而他会打开另一扇后面是山羊的门,比如1号门,这是主持人会问你,是否考虑放弃之前的选择,把自己的选择变为3号门?那么,坚持自己的选择还是放弃?哪个更好?我们可以用贝叶斯网络来解释下这件事情。

 

首先,构建一个有向非循环图结构,如上图,

该图有三个节点,每个节点代表对一个门的操作或信息:

1.门被参赛者选择;

2.门后面有汽车;

3.门被monty选择;

要注意1和2是完全独立的,但3是要依赖于1和2的,因为主持人必须要选择既没有被参赛者选择后面有没有车的门。

下面我们来构建贝叶斯网络,首先,安装python的贝叶斯网络包:

pip install pomegranate

python代码如下:

#引入需要的开发包
import math
from pomegranate import *
 
# 参赛者初始选择门是完全随机的,因此三个门选择的概率相等。
guest =DiscreteDistribution( { 'A': 1./3, 'B': 1./3, 'C': 1./3 } )
 
# 哪个门后面是奖品也是随机的,因此同样等概率。
prize =DiscreteDistribution( { 'A': 1./3, 'B': 1./3, 'C': 1./3 } )
 
# 主持人monty选择的门,取决于参赛者的选择以及奖品在哪个门后面。
monty =ConditionalProbabilityTable(
[[ 'A', 'A', 'A', 0.0 ],
[ 'A', 'A', 'B', 0.5 ],
[ 'A', 'A', 'C', 0.5 ],
[ 'A', 'B', 'A', 0.0 ],
[ 'A', 'B', 'B', 0.0 ],
[ 'A', 'B', 'C', 1.0 ],
[ 'A', 'C', 'A', 0.0 ],
[ 'A', 'C', 'B', 1.0 ],
[ 'A', 'C', 'C', 0.0 ],
[ 'B', 'A', 'A', 0.0 ],
[ 'B', 'A', 'B', 0.0 ],
[ 'B', 'A', 'C', 1.0 ],
[ 'B', 'B', 'A', 0.5 ],
[ 'B', 'B', 'B', 0.0 ],
[ 'B', 'B', 'C', 0.5 ],
[ 'B', 'C', 'A', 1.0 ],
[ 'B', 'C', 'B', 0.0 ],
[ 'B', 'C', 'C', 0.0 ],
[ 'C', 'A', 'A', 0.0 ],
[ 'C', 'A', 'B', 1.0 ],
[ 'C', 'A', 'C', 0.0 ],
[ 'C', 'B', 'A', 1.0 ],
[ 'C', 'B', 'B', 0.0 ],
[ 'C', 'B', 'C', 0.0 ],
[ 'C', 'C', 'A', 0.5 ],
[ 'C', 'C', 'B', 0.5 ],
[ 'C', 'C', 'C', 0.0 ]], [guest, prize] )
 
d1 = State( guest, name="guest" )
d2 = State( prize, name="prize" )
d3 = State( monty, name="monty" )
 
#构建贝叶斯网络
network = BayesianNetwork( "Solving the Monty Hall Problem With Bayesian Networks" )
network.add_states(d1, d2, d3)
network.add_edge(d1, d3)
network.add_edge(d2, d3)
network.bake()

状态'A'、'B'和'C'表示参赛者选中了哪个门、哪个门后面有奖品或者Monty选中了哪个门,那么这里已经给出了每个节点的条件分布,且所有条件分布情况均已给出。接下来的步骤,就是利用此模型做预测,贝叶斯网络的优势之一是能够根据“观察变量(observed variables)”推断任意“隐藏变量(hidden variables)”的值。这些隐藏的和观察到的变量不需要事先指定,观察到的变量越多,对隐藏变量的推断就越好。现在我们根据建立了模型来进行预测:

beliefs = network.predict_proba({ 'guest' : 'A' })
beliefs = map(str, beliefs)
print("n".join( "{}t{}".format( state.name, belief ) for state, belief in zip( network.states, beliefs ) ))

打印结果如下:

guesttAnprizet{
    "class" : "Distribution",
    "dtype" : "str",
    "name" : "DiscreteDistribution",
    "parameters" : [
        {
            "A" : 0.3333333333333333,
            "B" : 0.3333333333333333,
            "C" : 0.3333333333333333
        }
    ],
    "frozen" : false
}nmontyt{
    "class" : "Distribution",
    "dtype" : "str",
    "name" : "DiscreteDistribution",
    "parameters" : [
        {
            "C" : 0.49999999999999994,
            "B" : 0.49999999999999994,
            "A" : 0.0
        }
    ],
    "frozen" : false
}

在上面的代码中,我们假设从参赛者选择了门“A”。给定这个信息,获奖门为‘A’、‘B’、‘C’的概率是相等的(1/3),因为它完全是一个随机过程。但是,monty选‘A’的概率显然是零,因为参赛者选的是门‘A’。因为我们不知道哪个是最佳选择,另外两扇门均有50%的机会被monty选中。接下来,我们加入我们的输入给贝叶斯网络,进行预测:

beliefs = network.predict_proba({'guest' : 'A', 'monty' : 'B'})
print("n".join( "{}t{}".format( state.name, str(belief) ) for state, belief in zip( network.states, beliefs )))

打印结果如下:

guesttAnprizet{
    "class" : "Distribution",
    "dtype" : "str",
    "name" : "DiscreteDistribution",
    "parameters" : [
        {
            "A" : 0.3333333333333334,
            "B" : 0.0,
            "C" : 0.6666666666666664
        }
    ],
    "frozen" : false
}nmontytB

在上面的代码中,我们提供了两个输入给贝叶斯网络,参赛者选的门为‘A’,monty选的为'B',注意输出,汽车在门“C”后面的概率大约是66%,这证明如果参赛者转换选择,他获胜的概率更大。

其实也比较容易理解,参赛者坚持选择,那么这个就是一个随机的等概率选择,有1/3中奖,而如果放弃选择,如果之前选择的是中奖的,那必然就不会再中奖,此概率为1/3,如果之前选择不中奖,那么剩下两个,必然一个中奖一个有山羊,而主持人已经指出有山羊的门,选择另一个必然中奖,故中奖概率2/3。贝叶斯网络可以准确的给出这一问题的概率。

这里通过一个简单的例子给出了基于python的贝叶斯网络算法实现。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值