CS188—贝叶斯网络
介绍
本文承接上一篇博客:《贝叶斯神经网络——CS188 project4(上)》,在本篇文章中,将对CSS188project4中的question4-question5进行一个拆解并提出一个解决方案。
贝叶斯网推理问题
贝叶斯网络推理是指利用贝叶斯网络的结构及其条件概率表,在给定证据后计算某些节点取值的概率。概率推理和最大验后概率解释是贝叶斯网络推理的两个基本任务。
贝叶斯网络推理包含后验概率问题、最大后验假设问题和最大可能解释问题,是一个NP-困难问题。但是针对特定类型的贝叶斯网络,研究人员还是在精确的和近似的推理算法研究中取得了很大进展。
精确推理算法:消息传递算法、条件算法、联结树算法、符号概率推理算法、弧反向/节点缩减算法;
近似推理算法:随机抽样算法、基于搜索的算法、模型化简算法、循环消息传递算法。
但是有了以上的推理算法还不够,因为我们还需要考虑如何去降低推理的复杂度。而变量消元方法是最主要用来降低贝叶斯网络推理复杂度的方法,通过启发式算法找到一个较好的顺序来降低变量消元的复杂度。
变量消元法1
抽象地讲,一个联合分布是一个多变量函数,分解的概念可以推广到一般的多元函数。设f(X1,X2,···,Xn)是变量{X1,X2,···,Xn}的一个函数,而F={f1,f2,···,fm}是一组函数,其中每个fi所涉及的变量是{X1,X2,···,Xn}的一个子集。如果:
则称F是f的一个分解,f1,f2,···,fm是这个分解的因子,不失一般性,设f中与X1相关的函数为{f1,···,fk}。
从F中消去X1的过程称为消元运算,包括指如下过程:
(1)从F中删去所有与X1相关的函数f1,···,fk;
(2)将这些函数相乘,并通过如下运算消去变量X1:
(3)将新函数放回F中
项目解决方案
question4:Eliminate
在本题中我们需要对factorOperations.py中的eliminate函数进行实现,该函数的主要目的是在Factor中消除一个指定元素即上述变量消元中的消元运算过程。
实现目标如下所示:
在代码提示中,作业提供了以下几个可用的函数:
Factor.getAllPossibleAssignmentDicts
Factor.getProbability
Factor.setProbability
Factor.unconditionedVariables
Factor.conditionedVariables
Factor.variableDomainsDict
解决思路:
- 从原来的因子中继承非条件和条件变量
- 从非条件和条件变量中移出要待消除的变量
- 重组一个新的因子并返回
代码如下:
# 继承因子中的非条件和条件变量
unconditionedVariables = factor.unconditionedVariables()
conditionedVariables = factor.conditionedVariables()
# 从非条件和条件变量中移出eliminationVarible变量
if eliminationVariable in unconditionedVariables:
unconditionedVariables.remove(eliminationVariable)
if eliminationVariable in conditionedVariables:
conditionedVariables.remove(eliminationVariable)
# 假设所有输入因子的variableDomainsDict都是相同的
eliminatedFactor = Factor(unconditionedVariables, conditionedVariables, factor.variableDomainsDict())
oldAssignments = factor.getAllPossibleAssignmentDicts()
for assignment in eliminatedFactor.getAllPossibleAssignmentDicts():
prob = 0
for o in oldAssignments:
c = o.copy()
c.pop(eliminationVariable)
if assignment == c:
prob += factor.getProbability(o)
eliminatedFactor.setProbability(assignment, prob)
return eliminatedFactor
测试结果:
Question q4
===========
*** PASS: test_cases\q4\1-simple-eliminate.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q4\2-simple-eliminate-extended.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q4\3-eliminate-conditioned.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q4\4-grade-eliminate.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q4\5-simple-eliminate-nonsingleton-var.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q4\6-simple-eliminate-int.test
*** Executed FactorEqualityTest
### Question q4: 4/4 ###
question5:Normalize
在本问题中我们要在factorOperations.py中实现normalize函数,即实现将一个Factor作为输入并对其进行正则化,即对Factor中的所有项进行缩放,使Factor中所有项的和为1(如果输入因子中的概率和为0,则应该返回None)。
解决思路:
- 获取概率列表
- 获取每个因子的概率计算总和
- 对于在非条件中的概率,若已存在域为1,则转入条件变量中
- 重组正则化后的因子
- 计算通过正则化后的新概率
代码如下:
assignments = factor.getAllPossibleAssignmentDicts()
totalProb = 0
for assignment in assignments:
totalProb += factor.getProbability(assignment)
if totalProb == 0:
return None
varDomain = factor.variableDomainsDict()
unconditionedVariables = factor.unconditionedVariables()
conditionedVariables = factor.conditionedVariables()
for var in unconditionedVariables.copy():
if len(varDomain[var]) == 1:
conditionedVariables.add(var)
unconditionedVariables.remove(var)
normalizedFactor = Factor(unconditionedVariables,conditionedVariables,varDomain)
for assignment in assignments:
newProb = factor.getProbability(assignment) / totalProb
normalizedFactor.setProbability(assignment, newProb)
return normalizedFactor
测试结果:
Question q5
===========
*** PASS: test_cases\q5\1-preNormalized.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\10-simple-normalize-int.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\2-preUnNormalized.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\3-simple-normalize.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\4-zeroVal-normalize.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\5-extended-normalize.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\6-conditioned-eliminate.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\7-singleDomainUnconditional-extraDomain.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\8-simple-normalize-nonsingleton-var.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q5\9-simple-normalize-multiple-singleEntry.test
*** Executed FactorEqualityTest
### Question q5: 4/4 ###
question6:Variable Elimination
本问题需要我们在inference.py中实现inferenceByVariableElimination函数,去实现一个使用BayesNet、查询变量列表和证据表示的概率查询,即通过变量消除来计算后验概率分布。
我们需要按照消除顺序来遍历隐藏变量,执行连接并消除该变量,直到只剩下查询变量和证据变量,同时我们要保证在输出因子中,概率的总和应该是1。
枚举推理首先连接所有变量,然后消除所有隐藏变量。相反,变量消除通过迭代所有隐藏变量来交叉连接和消除,并在执行下一个隐藏变量之前对单个隐藏变量执行连接和消除。
解决思路:
- 先获取所有的因子
- 建立证据变量和查询变量的集合
- 基于消除变量来连接所有的CPTs
- 如果因子有存在超过一次非条件变量就消除它
代码如下:
factors = bayesNet.getAllCPTsWithEvidence(evidenceDict)
evidenceVariablesSet = set(evidenceDict.keys())
queryVariablesSet = set(queryVariables)
for var in eliminationOrder:
# 基于消除变量连接所有CPTS
factors, f = joinFactorsByVariable(factors, var)
# 如果变量有存在超过一次非条件变量,则消除它
if len(f.unconditionedVariables()) > 1:
f = eliminate(f, var)
factors.append(f)
inferenceFactor = normalize(joinFactors(factors))
return inferenceFactor
测试结果:
Question q6
===========
*** PASS: test_cases\q6\1-disconnected-eliminate.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q6\2-independent-eliminate.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q6\3-independent-eliminate-extended.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q6\4-common-effect-eliminate.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q6\5-grade-var-elim.test
*** Executed FactorEqualityTest
*** PASS: test_cases\q6\6-large-bayesNet-elim.test
*** Executed FactorEqualityTest
### Question q6: 4/4 ###
总结
本次完成了上一篇文章中的后续实验,在构建了基础贝叶斯网络的基础上,对贝叶斯网络的进一步优化和改进。
概率推理和最大验后概率解释是贝叶斯网络推理的两个基本任务,其中概率推理又是比较困难的一部分,除了对其精准推理算法和近似推理算法的实现外,还需要对推理算法本身进行进一步地改进和优化。所以就引入了变量消元,通过变量消元方法来降低推理算法的复杂度,从而提高贝叶斯网络概率推理的效率。
通过本次的实验,对贝叶斯神经网络的整个结构、流程有了更深一步的了解。
变量消元法引自:https://blog.csdn.net/deepbodhi/article/details/119823431 ↩︎