CS188 Project 4: Inference in Bayes Nets(4-6)

Question 4 (4 points): Eliminate

原理

变量消元方法是用于降低贝叶斯网推理复杂度的主要手段。而变量消元的复杂度又与变量消元的顺序有关,通过一些启发式算法,可以找到较好的消元顺序。除了寻找较好的消元顺序来降低推理复杂度,还可以通过独立性关系剔除与推理无关的变量,对推理问题进行简化。
贝叶斯网推理主要包含三大类问题:后验概率问题、最大后验假设问题和最大可能解释问题。其中后验概率问题是最基本的问题。
(1) 后验概率问题
后验概率问题是指已知贝叶斯网中某些变量的值,计算另外一些变量的后验概率分布。
此类问题中,已知变量称为证据变量,记为E,取值记为e;需要计算后验概率分布的变量称为查询变量,记为Q;需要计算的后验概率分布为P(Q|E=e)。
根据证据变量和查询变量的因果关系不同,后验概率问题又可分为以下4种类型:从结果到原因的诊断推理;从原因到结果的预测推理;同一结果的不同原因之间的原因间推理;包含上述多种类型的混合推理。
虽然存在以上多种推理类型,但贝叶斯网推理都使用同一种方法来处理,即计算已知证据变量条件下查询变量的条件概率。
(2) 最大后验假设问题
已知证据E=e,若要求出一些变量的后验概率最大的状态组合,则这些变量称为假设变量,记作H。H的一个状态组合称为一个假设,记为h。在所有可能的假设中,找出后验概率最大的那个假设h*,即h*=arg maxP(H=h|E=e)。
这就是最大后验假设问题,简称为MAP(Maximum a posteriori hypothesis)。MAP问题的基础是后验概率问题。但MAP问题的复杂度与假设变量H的个数呈指数关系,对实际情况,需要作特殊的化简处理。
(3) 最大可能解释问题
在贝叶斯网络中,证据E=e的一个解释指的是网络中全部变量的一个与E=e相一致的状态组合。概率最大的那个解释叫做最大可能解释,简称MPE(Most probable explanation)。MPE问题是MAP问题的一个特例,即MAP中的假设变量H包含了贝叶斯网络中所有非证据变量。

可以看出,以上三种问题中,最基础的是后验概率问题。通过变量间的条件独立关系对联合分布进行分解,减少模型参数个数,可使推理过程简化,即可以使用变量消元法降低推理复杂度。

在贝叶斯网络中,一个联合分布是一个多变量函数,分解可以推广到一般的多元函数。设F(X1,X2,…,Xn)是变量{X1,X2,…,Xn}的一个函数,而f={f1,f2,…,fm}是一组函数,其中每个fi所涉及的变量是{X1,X2,…,Xn}的一个子集。若在这里插入图片描述
,则称f是F的一个分解,f1,f2,…,fm是这个分解的因子,设f中与X1相关的函数为{f1,f2,…,fk}。从f中消去X1的过程称为消元运算。包括以下过程:首先从f中删去所有与X1相关的函数f1,…fk;然后将这些函数相乘,并通过如下运算消去变量X1在这里插入图片描述
将新函数在这里插入图片描述
放回f中。消元运算等价于直接从联合概率分布求边缘概率分布。

方法

对于Question 4,将在factorOperations.py的eliminate函数中编写代码,该函数的输入是一个因子和一个变量,实现消除输入变量的功能后,返回一个不包含该变量的新因子。这相当于将因子中的所有条目相加,这些条目仅在被消除的变量值上存在区别。在该函数的参数列表中,输入变量factor是一个单一变量,输入变量eliminationVariable是需要被消除因子的变量,且是因子中的无条件变量,对无条件变量集和已经消除掉变量eliminationVariable中的因子的条件变量集进行计算后,输出包含eliminationVariable变量的所有行与相匹配的其他变量所在的行相加后的新因子。

   根据代码框架中的提示,我们会用到的有效函数如下:
    Factor.getAllPossibleAssignmentDicts
    Factor.getProbability
    Factor.setProbability
    Factor.unconditionedVariables
    Factor.conditionedVariables
    Factor.variableDomainsDict

代码

完成该eliminate函数,实现消除输入变量的功能。首先从输入变量中得到条件变量集和无条件变量集,进行变量消除之后,生成新因子,最后计算概率。

def eliminateWithCallTracking(callTrackingList=None):

    def eliminate(factor, eliminationVariable):
        """
        Question 4: Your eliminate implementation 

        Input factor is a single factor.
        Input eliminationVariable is the variable to eliminate from factor.
        eliminationVariable must be an unconditioned variable in factor.
        
        You should calculate the set of unconditioned variables and conditioned 
        variables for the factor obtained by eliminating the variable
        eliminationVariable.

        Return a new factor where all of the rows mentioning
        eliminationVariable are summed with rows that match
        assignments on the other variables.

        Useful functions:
        Factor.getAllPossibleAssignmentDicts
        Factor.getProbability
        Factor.setProbability
        Factor.unconditionedVariables
        Factor.conditionedVariables
        Factor.variableDomainsDict
        """
        # autograder tracking -- don't remove
        if not (callTrackingList is None):
            callTrackingList.append(('eliminate', eliminationVariable))

        # typecheck portion
        if eliminationVariable not in factor.unconditionedVariables():
            print("Factor failed eliminate typecheck: ", factor)
            raise ValueError("Elimination variable is not an unconditioned variable " \
                            + "in this factor\n" + 
                            "eliminationVariable: " + str(eliminationVariable) + \
                            "\nunconditionedVariables:" + str(factor.unconditionedVariables()))
        
        if len(factor.unconditionedVariables()) == 1:
            print("Factor failed eliminate typecheck: ", factor)
            raise ValueError("Factor has only one unconditioned variable, so you " \
                    + "can't eliminate \nthat variable.\n" + \
                    "eliminationVariable:" + str(eliminationVariable) + "\n" +\
                    "unconditionedVariables: " + str(factor.unconditionedVariables()))

        "*** YOUR CODE HERE ***"
        
        # 从初始变量中得到条件变量集和无条件变量集
        unconditioned_variables = list(factor.unconditionedVariables())
        conditioned_variables = list(factor.conditionedVariables())
        variablesDomainDict = factor.variableDomainsDict()
        
        # 生成新因子
        retFactor = Factor([i for i in unconditioned_variables if i != eliminationVariable], \
            conditioned_variables, variablesDomainDict)
            
        # 计算概率
        assignments = retFactor.getAllPossibleAssignmentDicts()
        print("assignments:",assignments)
        print("variablesDomainDict:", variablesDomainDict)
        print("eliminationVariable:", eliminationVariable)
        print("eliminated_values:", variablesDomainDict[eliminationVariable])
        print("variablesDomainDict[eliminationVariable]:", variablesDomainDict[eliminationVariable])
        for assignment in assignments:
            probability = 0
            for eliminated_values in variablesDomainDict[eliminationVariable]:
                prev_assignment = assignment.copy()
                prev_assignment[eliminationVariable] = eliminated_values
                probability += factor.getProbability(prev_assignment)
            
            retFactor.setProbability(assignment, probability)
        
        return retFactor

        "*** END YOUR CODE HERE ***"

    return eliminate

eliminate = eliminateWithCallTracking()

结果

在这里插入图片描述

Question 5 (4 points): Normalize

原理

对变量的正则化不影响概率的分布,因为正则化要求输出的变量的概率表中所有项之和为1,factors不仅存储了贝叶斯网络的可变域的信息,还存储了无条件变量集和条件变量集。返回的factor应该与输入的factor具有相同的可变域。

方法

对于Question 5,将在factorOperations.py的normalize函数中编写代码,该函数的输入是一个因子,在对该因子进行正则化后,输出一个经过处理后的新的因子。正则化即对输入的因子进行缩放,使其概率表中所有项之和为1。在该函数的参数列表中,输入变量factor是一个单一因子。正则化因子的条件变量集包括输入因子的条件变量集和在输入因子的变量域中只有一个入口的无条件变量集,因为该输入因子的变量域中只有一个入口,所以假定在它的变量域中只有一个变量,也就是说它只有一个入口可以进入。这样就模糊了证据分配和拥有单一值域的变量的区别,因为必须将值域中只有一个值的变量转换为单个值,所以这样做是可行的。进行正则化之后,输出一个新的因子,要求它的概率表中所有项之和为1。但是若输入因子的概率表中所有项之和为1,那么应该返回None。将值域中超过一个值的变量集视为无条件变量集。

根据代码框架中的提示,我们会用到的有效函数如下:

Factor.getAllPossibleAssignmentDicts
Factor.getProbability
Factor.setProbability
Factor.unconditionedVariables
Factor.conditionedVariables
Factor.variableDomainsDict

代码

对变量进行正则化的过程,首先定义条件变量集、无条件变量集和变量值域,然后对输入因子进行正则化后生成新的因子,最后计算新生成的因子的概率表。

def normalize(factor):
    """
    Question 5: Your normalize implementation 

    Input factor is a single factor.

    The set of conditioned variables for the normalized factor consists 
    of the input factor's conditioned variables as well as any of the 
    input factor's unconditioned variables with exactly one entry in their 
    domain.  Since there is only one entry in that variable's domain, we 
    can either assume it was assigned as evidence to have only one variable 
    in its domain, or it only had one entry in its domain to begin with.
    This blurs the distinction between evidence assignments and variables 
    with single value domains, but that is alright since we have to assign 
    variables that only have one value in their domain to that single value.

    Return a new factor where the sum of the all the probabilities in the table is 1.
    This should be a new factor, not a modification of this factor in place.

    If the sum of probabilities in the input factor is 0,
    you should return None.

    This is intended to be used at the end of a probabilistic inference query.
    Because of this, all variables that have more than one element in their 
    domain are assumed to be unconditioned.
    There are more general implementations of normalize, but we will only 
    implement this version.

    Useful functions:
    Factor.getAllPossibleAssignmentDicts
    Factor.getProbability
    Factor.setProbability
    Factor.unconditionedVariables
    Factor.conditionedVariables
    Factor.variableDomainsDict
    """

    # typecheck portion
    variableDomainsDict = factor.variableDomainsDict()
    for conditionedVariable in factor.conditionedVariables():
        if len(variableDomainsDict[conditionedVariable]) > 1:
            print("Factor failed normalize typecheck: ", factor)
            raise ValueError("The factor to be normalized must have only one " + \
                            "assignment of the \n" + "conditional variables, " + \
                            "so that total probability will sum to 1\n" + 
                            str(factor))

    "*** YOUR CODE HERE ***"
    unconditioned_variables = list(factor.unconditionedVariables())
    conditioned_variables = list(factor.conditionedVariables())
    variablesDomainDict = factor.variableDomainsDict()

    # 生成新的因子
    retFactor_conditioned_varaibles = conditioned_variables \
        + [i for i in unconditioned_variables if len(variableDomainsDict[i]) == 1]
    retFactor_unconditioned_varaibles = [i for i in unconditioned_variables if i not in retFactor_conditioned_varaibles]
    retFactor = Factor(retFactor_unconditioned_varaibles, retFactor_conditioned_varaibles, variablesDomainDict)

    # 计算变量正则化后的总概率
    total_probablity = 0
    for assignment_dict in factor.getAllPossibleAssignmentDicts():
    
        total_probablity += factor.getProbability(assignment_dict)
    
    # 生成新的因子的概率表
    for assignment in retFactor.getAllPossibleAssignmentDicts():
        probability = factor.getProbability(assignment)
        retFactor.setProbability(assignment, probability / total_probablity)
    
    return retFactor
    "*** END YOUR CODE HERE ***"

结果

在这里插入图片描述
在这里插入图片描述

Question 6 (4 points): Variable Elimination

原理

变量消除法的思想就是对联合概率不断求和消除其中的变量,最后得到边缘分布。
如下图所示,首先对联合概率来说,先把b消元,得到中间只含a和c的表,然后对c进行求和,得到最后只含有a的概率表,对这个表进行归一化之后,就得到了a的概率。
在这里插入图片描述
在这里插入图片描述
如上图a所示为一个贝叶斯网的结构,写出它的因子乘积。
在这里插入图片描述
接下来选定消元顺序,首先对x1进行消元,消元过程如下:
在这里插入图片描述
因为在这里插入图片描述
只和x1、x2有关系,所以对x1进行积分,剩下的就是关于x2的式子。将上述过程有符号表达为m12(x2),其中m的第一个下标表示对那一个变量进行求和,第二个下标表示的是求和剩下的变量,其中括号内的x2,表示的是关于x2的函数。
接下来是对剩余变量的消元过程:
在这里插入图片描述

方法

对于Question 6,将在inference.py的inferenceByVariableElimination函数中编写代码,该函数执行概率推断查询,该查询使用贝叶斯网络、变量列表和证据变量进行表示。该变量消除算法按照消除顺序迭代隐藏变量,进行连接后消除该变量,直到最后只剩余查询变量和证据变量。该函数的变量列表为bayesNet、queryVariables、evidenceDict以及eliminationOrder,经过变量消除操作后,输出因子的概率之和应该为1。该函数返回P(查询变量|证据变量)。根据eliminationOrder来判断变量消除的顺序。使用joinFactorsByVariable来连接所有的factor。

若要从中消除变量的因子只有一个无条件变量,则不应对其执行消除变量操作,否则会将所有无条件变量边缘化。

变量说明:
bayesNet:执行查询的贝叶斯网络
queryVariables:推理查询中的无条件变量列表
evidenceDict:推理查询中作为证据呈现的变量
eliminationOrder:消除变量的顺序
根据代码框架中的提示,我们会用到的有效函数如下:
BayesNet.getAllCPTsWithEvidence
normalize
eliminate
joinFactorsByVariable
joinFactors

代码

    def inferenceByVariableElimination(bayesNet, queryVariables, evidenceDict, eliminationOrder):
        """
        Question 6: Your inference by variable elimination implementation

        This function should perform a probabilistic inference query that
        returns the factor:

        P(queryVariables | evidenceDict)

        It should perform inference by interleaving joining on a variable
        and eliminating that variable, in the order of variables according
        to eliminationOrder.  See inferenceByEnumeration for an example on
        how to use these functions.

        You need to use joinFactorsByVariable to join all of the factors 
        that contain a variable in order for the autograder to 
        recognize that you performed the correct interleaving of 
        joins and eliminates.

        If a factor that you are about to eliminate a variable from has 
        only one unconditioned variable, you should not eliminate it 
        and instead just discard the factor.  This is since the 
        result of the eliminate would be 1 (you marginalize 
        all of the unconditioned variables), but it is not a 
        valid factor.  So this simplifies using the result of eliminate.

        The sum of the probabilities should sum to one (so that it is a true 
        conditional probability, conditioned on the evidence).

        bayesNet:         The Bayes Net on which we are making a query.
        queryVariables:   A list of the variables which are unconditioned
                          in the inference query.
        evidenceDict:     An assignment dict {variable : value} for the
                          variables which are presented as evidence
                          (conditioned) in the inference query. 
        eliminationOrder: The order to eliminate the variables in.

        Hint: BayesNet.getAllCPTsWithEvidence will return all the Conditional 
        Probability Tables even if an empty dict (or None) is passed in for 
        evidenceDict. In this case it will not specialize any variable domains 
        in the CPTs.

        Useful functions:
        BayesNet.getAllCPTsWithEvidence
        normalize
        eliminate
        joinFactorsByVariable
        joinFactors
        """

        # this is for autograding -- don't modify
        joinFactorsByVariable = joinFactorsByVariableWithCallTracking(callTrackingList)
        eliminate             = eliminateWithCallTracking(callTrackingList)
        if eliminationOrder is None: # set an arbitrary elimination order if None given
            eliminationVariables = bayesNet.variablesSet() - set(queryVariables) -\
                                   set(evidenceDict.keys())
            eliminationOrder = sorted(list(eliminationVariables))

        "*** YOUR CODE HERE ***"
        all_factors = bayesNet.getAllCPTsWithEvidence(evidenceDict)

        for elimination_variable in eliminationOrder:
            unjoined_factors, joined_factors = joinFactorsByVariable(all_factors, elimination_variable)
            all_factors = unjoined_factors
            
            if len(joined_factors.unconditionedVariables()) != 1:
                all_factors.append(eliminate(joined_factors, elimination_variable))
        
        return normalize(joinFactors(all_factors))
    
        "*** END YOUR CODE HERE ***"

    return inferenceByVariableElimination

结果

在这里插入图片描述
在这里插入图片描述

数据及效果对比

Eliminate

在这里插入图片描述

Normalize

在这里插入图片描述
在这里插入图片描述

Variable Elimination

在这里插入图片描述
在这里插入图片描述

收获

变量消除 (Variable Elimination) ,指的是不断从贝叶斯网络中移除变量,但是保持其回答查询 (Query) 的能力。这是最简单的一种推断方法 (Inference Method)。贝叶斯网推理主要包四种不同的查询:证据概率 (Probability of Evidence),先验和后验边际 (Prior and Posterior Marginal),最大可能解释 (MPE),最大后验假设 (MAP)。 而变量消除 (VE) 可以用来回答以上所有的查询。

对于Question 4,要求进行贝叶斯网络的消元操作,变量消元方法是用于降低贝叶斯网推理复杂度的主要手段。而变量消元的复杂度又与变量消元的顺序有关,通过一些启发式算法,可以找到较好的消元顺序。除了寻找较好的消元顺序来降低推理复杂度,还可以通过独立性关系剔除与推理无关的变量,对推理问题进行简化。贝叶斯网推理主要包含三大类问题:后验概率问题、最大后验假设问题和最大可能解释问题。其中后验概率问题是最基本的问题。以上三种问题中,最基础的是后验概率问题。通过变量间的条件独立关系对联合分布进行分解,减少模型参数个数,可使推理过程简化,即可以使用变量消元法降低推理复杂度。在贝叶斯网络中,一个联合分布是一个多变量函数,分解可以推广到一般的多元函数。设F(X1,X2,…,Xn)是变量{X1,X2,…,Xn}的一个函数,而f={f1,f2,…,fm}是一组函数,其中每个fi所涉及的变量是{X1,X2,…,Xn}的一个子集。若在这里插入图片描述
,则称f是F的一个分解,f1,f2,…,fm是这个分解的因子,设f中与X1相关的函数为{f1,f2,…,fk}。从f中消去X1的过程称为消元运算。包括以下过程:首先从f中删去所有与X1相关的函数f1,…fk;然后将这些函数相乘,并通过如下运算消去变量X1在这里插入图片描述
将新函数在这里插入图片描述
放回f中。消元运算等价于直接从联合概率分布求边缘概率分布。

对于Question 5,要求进行消元后的正则化操作,该函数的输入是一个因子,在对该因子进行正则化后,输出一个经过处理后的新的因子。正则化即对输入的因子进行缩放,使其概率表中所有项之和为1。对变量的正则化不影响概率的分布,因为正则化要求输出的变量的概率表中所有项之和为1。

对于Question 6,要求进行变量消除操作,执行概率推断查询,该查询使用贝叶斯网络、变量列表和证据变量进行表示。该变量消除算法按照消除顺序迭代隐藏变量,进行连接后消除该变量,直到最后只剩余查询变量和证据变量。根据eliminationOrder来判断变量消除的顺序。使用joinFactorsByVariable来连接所有的factor。若要从中消除变量的因子只有一个无条件变量,则不应对其执行消除变量操作,否则会将所有无条件变量边缘化。

在本次实习中,着重训练了对于贝叶斯网络的实践应用,熟悉了贝叶斯网络的变量消除算法,通过Pacman游戏来对贝叶斯网络进行深入学习。巩固了课堂上学习的贝叶斯网络,加强了对贝叶斯网络的应用能力,锻炼了我的算法思维,巩固了以往所学的知识,查漏补缺,夯实基础,同时也学习了许多新的、高效的、实用的知识,提高了算法设计能力。通过这次实习,我更加深刻地掌握了贝叶斯网络的基础,也能够较为熟练地将其运用到应用中去。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值