CS188—贝叶斯网络
- 介绍
- 项目解决方案
- question1:贝叶斯网络结构
- question2:贝叶斯净概率
- question3:连接因子
- 总结
介绍
项目解决方案
question1:贝叶斯网络结构
贝叶斯网络(Bayesian network),又称信念网络(belief network)或是有向无环图模型(directed acyclic graphical model),是一种概率图型模型。一个贝叶斯网络是一个有向无环图(Directed Acyclic Graph,DAG),由代表变量结点及连接这些结点有向边构成。
上面只是一些繁琐的定义,接下来的说明比较关键:结点代表随机变量,结点间的有向边代表了结点间的互相关系(由父结点指向其子结点),用条件概率进行表达关系强度,没有父结点的用先验概率进行信息表达。 结点变量可以是任何问题的抽象,如:测试值,观测现象,意见征询等。适用于表达和分析不确定性和概率性的事件,应用于有条件地依赖多种控制因素的决策,可以从不完全、不精确或不确定的知识或信息中做出推理。
提取到几个有用信息:
- 结点代表随机变量
- 结点间的有向边代表了结点间的相互关系,由父结点指向子结点
- 用条件概率表达变量间依赖关系1
在本问题中我们需要在实验项目的框架下完善BayesAgents.py
文件中的constructBayesNet
函数来实现一个贝叶斯网络的构建,应实现的贝叶斯网络如下图所示:
其实在项目代码中已经给出了非常明确的提示信息:
"""
Construct an empty Bayes net according to the structure given in the project
description.
主要是要构建一个空的贝叶斯网络结构
There are 5 kinds of variables in this Bayes net:
- a single "x position" variable (controlling the x pos of the houses)
- a single "y position" variable (controlling the y pos of the houses)
- a single "food house" variable (containing the house centers)
- a single "ghost house" variable (containing the house centers)
- a large number of "observation" variables for each cell Pacman can measure
这里是给出的贝叶斯网络中的五个变量参数
You *must* name all position and house variables using the constants
(X_POS_VAR, FOOD_HOUSE_VAR, etc.) at the top of this file.
The full set of observation variables can be obtained as follows:
for housePos in gameState.getPossibleHouses():
for obsPos in gameState.getHouseWalls(housePos)
obsVar = OBS_VAR_TEMPLATE % obsPos
提供了一段获取“观测值”集的代码,一会儿会直接用到
In this method, you should:
- populate `obsVars` using the procedure above
- populate `edges` with every edge in the Bayes Net (a tuple `(from, to)`)
- set each `variableDomainsDict[var] = values`, where `values` is the set
of possible assignments to `var`. These should again be set using the
constants defined at the top of this file.
"""
所以我们需要补充的代码的内容以及逻辑结构已经非常清晰了,只要按照它的提示一步步来实现就可以了。
具体实现代码如下:
# 贝叶斯网络中的4个变量,“x位置”变量、“y位置变量”、“食物屋”位置变量、“鬼房子”位置变量
# 由于常量已经给出,故可以直接装入variableDomainsDict字典中
variableDomainsDict[X_POS_VAR] = X_POS_VALS
variableDomainsDict[Y_POS_VAR] = Y_POS_VALS
variableDomainsDict[FOOD_HOUSE_VAR] = HOUSE_VALS
variableDomainsDict[GHOST_HOUSE_VAR] = HOUSE_VALS
# 利用给出提示的方法填充obsVars,并且将五个变量中最后一个装入variableDomainsDict字典中
for housePos in gameState.getPossibleHouses():
for obsPos in gameState.getHouseWalls(housePos):
obsVar = OBS_VAR_TEMPLATE % obsPos
obsVars.append(obsVar)
variableDomainsDict[obsVar] = OBS_VALS
# 用贝叶斯网络中的每条边来填充edges
for position in [X_POS_VAR, Y_POS_VAR]:
for house in HOUSE_VARS:
edges.append((position, house))
for obs in obsVars:
edges.append((house, obs))
测试结果:
Question q1
===========
*** PASS: test_cases\q1\1-small-board.test
*** PASS: test_cases\q1\2-long-bottom.test
*** PASS: test_cases\q1\3-wide-inverted.test
### Question q1: 3/3 ###
question2:贝叶斯净概率
概率流动的影响性指的是在一定的观测条件下,变量间的取值改变是否会有相互影响,这里给出两个概念:
- 观测变量:变量取值可观测,或变量取值已经确定
- 隐变量:变量取值未知,通常根据观测变量的取值,对隐变量的取值概率进行推理。
在本问题中,我们需要给出y位置变量的先验概率,也就是说我们需要设定每一个观测值就可以了。项目提示指出:“Y 位置因子中只有四个条目,因此您可以手动指定每个条目”。故我们只需要以下四行代码即可实现该功能函数:
yFactor.setProbability({Y_POS_VAR: BOTH_TOP_VAL}, PROB_BOTH_TOP)
yFactor.setProbability({Y_POS_VAR: BOTH_BOTTOM_VAL}, PROB_BOTH_BOTTOM)
yFactor.setProbability({Y_POS_VAR: LEFT_TOP_VAL}, PROB_ONLY_LEFT_TOP)
yFactor.setProbability({Y_POS_VAR: LEFT_BOTTOM_VAL}, PROB_ONLY_LEFT_BOTTOM)
测试结果:
Question q2
===========
*** PASS: test_cases\q2\1-small-board.test
*** PASS: test_cases\q2\2-long-bottom.test
*** PASS: test_cases\q2\3-wide-inverted.test
### Question q2: 1/1 ###
question3:连接因子
在这个问题中,最重要的是建立对应的乘积规则,而在项目介绍中,我们可以获取到joinFactors
功能函数可以解决的一些概率计算问题:
joinFactors(P(X|Y), P(Y)) = P(X,Y)
joinFactors(P(V,W|X,Y,Z), P(X,Y|Z)) = P(V,W,X,Y|Z)
joinFactors(P(X|Y,Z),P(Y)) =P(X,Y|Z)
joinFactors(P(V|W),P(X|Y),P(Z)) = P(V,X,Z|W,Y)
由此,我们不难发现一旦一个事件既作为被求概率事件又作为先决条件出现的时候,它就只能作为被求概率事件出现了。所以在joinFactors
函数中,我们要将被求概率事件(条件变量)和先决条件(非条件变量)分别放在两个集合中,然后再进行概率计算就可以了。
具体实现代码如下:
# 首先构建两个集合,分别存放条件变量和非条件变量
ConditionVariables = set()
UnconditionedVariables = set()
# 先将所有概率中的条件变量和非条件变量取出来
for factor in factors:
for condVar in factor.conditionedVariables():
ConditionVariables.add(condVar)
for uncondVar in factor.unconditionedVariables():
UnconditionedVariables.add(uncondVar)
# 在非条件变量中,寻找是否有作为条件变量出现的对象
# 若有则从非条件变量集合中剔除
for uncondVar in UnconditionedVariables:
if uncondVar in ConditionVariables:
ConditionVariables.remove(uncondVar)
joinedFactor = Factor(UnconditionedVariables,ConditionVariables,factor.variableDomainsDict())
# 计算概率
for joinedAssignment in joinedFactor.getAllPossibleAssignmentDicts():
factorAssignmentProduct = 1
for factor in factors:
factorAssignmentProduct = factorAssignmentProduct * Factor.getProbability(factor, joinedAssignment)
Factor.setProbability(joinedFactor, joinedAssignment, factorAssignmentProduct)
return joinedFactor
测试结果:
Question q3
===========
*** PASS: test_cases\q3\1-product-rule.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q3\2-product-rule-extended.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q3\3-disjoint-right.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q3\4-common-right.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q3\5-grade-join.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q3\6-product-rule-nonsingleton-var.test
*** Executed FactorEqualityTest
### Question q3: 5/5 ###
总结
在本次的实验项目中,着重巩固了贝叶斯网络知识的学习。
在我看来,贝叶斯网络展现的就是一个多线性多情况的逻辑,有不同的先决条件影响不同的事件发生的概率。贝叶斯网络本身是一种不定性因果关联模型,它将多元知识图解可视化,蕴含了网络结点变量之间的因果关系以及条件相关关系,这张网中的每个结点之间都紧密联系着;贝叶斯网络用条件概率表达各个信息要素之间的相关关系,能在有限的、不完整的、不确定的信息条件下进行知识学习和推理,所以它能够非常好地借助已有的信息来处理不确定性问题。
在具有诸多优势的同时,贝叶斯网络也存在一些缺陷,例如:在复杂的贝叶斯网络中,根据已有数据和相关知识快速高效的构建出贝叶斯网络是一个难点。
本次实验只完成了该贝叶斯项目中前三个part,这三个part难度并不大,主要是在项目介绍以及代码注释中已经将要实现的功能目标与代码逻辑几乎已经完全呈现出来了,所以只需要跟着所给的提示按部就班地将每一部分的要求给实现就可以了。