CS188 Project 4: Inference in Bayes Nets(1-3)

Question 1 (3 points): Bayes Net Structure

原理

根据对统计的理解,数理统计存在概率学派与贝叶斯学派两种学派,他们之间的主要区别在于对于概率的理解方法不同。

概率学派认为世界存在一个固定的先验概率,频率派把需要推断的参数θ看做是固定的未知常数,即概率虽然是未知的,但它是确定的一个值,同时,样本X 是随机的,所以频率派重点研究样本空间;而贝叶斯派的观点则截然相反,他们认为参数是随机变量,而样本X 是固定的,由于样本是固定的,所以他们重点研究的是参数的分布。贝叶斯学派则认为世界没有一个确定的先验概率。贝叶斯提出了一个思考问题的固定模式:先验分布π(θ)+ 样本信息 X X X-> 后验分布π(θ| X X X)。

贝叶斯网络是一种描述随机变量之间互相条件独立关系的有向无环图。贝叶斯网络的有向无环图中的节点表示随机变量,它们可以是可观察到的变量,或隐变量、未知参数等。认为有因果关系(或非条件独立)的变量或命题则用箭头来连接。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(children)”,两节点就会产生一个条件概率值。连接两个节点的箭头代表此两个随机变量具有因果关系,或非条件独立。每个节点代表一个随机变量对其父节点的条件概率分布P( X X X|parents( X X X)),每一条边可以理解成变量之间的联系。虽然一般来讲这种“联系”可以被解释为“因果关系”,但是实际上这种关系并不一定是因果关系,只要两个变量之间互相不条件独立就应该被连在一起。在贝叶斯网络中,已知X的父节点parents( X X X)时 X X X的条件概率分布P( X X X|parents( X X X))与已知 X X X的父节点时网络中 X X X的“祖先节点”的概率分布P(ancestor( X X X)|parents( X X X))互相条件独立。

方法

对于Question 1,将在bayesAgents.py的constructBayesNet函数中编写代码,该函数已经构造了一个空的贝叶斯网络,根据题目要求,将根据如下图所示要求的贝叶斯网络进行贝叶斯网络的构建。其中X的位置决定木板的哪一侧是哪栋房子,它取食物屋的左侧或鬼屋的左侧。Y的位置决定食物屋和鬼屋的位置。它取两顶、两下、左上和左下。左上:板左侧的房子在上面,板右侧的房子在底部,左下:板左侧的房子在下面,板右侧的房子在顶部,两顶:板上侧的房子在顶部,板下侧的房子在底部,两下:板上侧的房子在底部,板下侧的房子在顶部。食物屋和鬼屋是X位置和Y位置的决定性函数。
观测结果是Pacman在木板上得到的。它会取无、红色或蓝色。观测到鬼屋代表蓝色,观测到食物屋代表红色,若没有观测到房屋,则观测结果为无。
在这里插入图片描述

代码

对于题目给出的贝叶斯网络的构建,首先对X、Y、食物屋、鬼屋的位置进行定义,然后定义Pacman的观测结果,最后将X->Food house、X->Ghost house、Y->Food house、Y->Ghost house有向边加入到贝叶斯网络中,再将Food house->Observation和Goust house->Observation有向边加入到贝叶斯网络中,完成贝叶斯网络的构建。

def constructBayesNet(gameState):
    """
    Question 1: Bayes net structure

    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.
    """

    obsVars = []
    edges = []
    variableDomainsDict = {}

    "*** YOUR CODE HERE ***"
    # 定义X和Y的位置
    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

    # 定义Pacman的观测结果
    for housePos in gameState.getPossibleHouses():
        for obsPos in gameState.getHouseWalls(housePos):
            obsVar = OBS_VAR_TEMPLATE % obsPos
            obsVars.append(obsVar)
            variableDomainsDict[obsVar] = OBS_VALS
    
    #向贝叶斯网络中加入有向边
    edges.append((X_POS_VAR, GHOST_HOUSE_VAR))
    edges.append((X_POS_VAR, FOOD_HOUSE_VAR))
    edges.append((Y_POS_VAR, FOOD_HOUSE_VAR))
    edges.append((Y_POS_VAR, GHOST_HOUSE_VAR))

    for obsVar in obsVars:
        edges.append((FOOD_HOUSE_VAR, obsVar))
        edges.append((GHOST_HOUSE_VAR, obsVar))
    

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

    variables = [X_POS_VAR, Y_POS_VAR] + HOUSE_VARS + obsVars
    net = bn.constructEmptyBayesNet(variables, edges, variableDomainsDict)
    return net, obsVars

结果

在这里插入图片描述

Question 2 (1 point): Bayes Net Probabilities

原理

条件概率表 (CPT):需要满足以下条件中的一条
1.对于条件变量,其总和必须为 1;
2.存在一个无条件变量。

方法

对于Question 2,将在bayesAgents.py的fillYCPT函数中编写代码,该函数使用Question 1已经构造的贝叶斯网络。需要填写给出Y位置变量的先验概率的CPT。Y的位置决定食物屋和鬼屋的位置。它有四个取值:两顶、两下、左上和左下。左上:板左侧的房子在上面,板右侧的房子在底部,左下:板左侧的房子在下面,板右侧的房子在顶部,两顶:板上侧的房子在顶部,板下侧的房子在底部,两下:板上侧的房子在底部,板下侧的房子在顶部。

代码

由于Y位置有四个可能的取值,所以当Y取BOTH_TOP_VAL(两上)时,对应的概率为PROB_BOTH_TOP;当Y取BOTH_BOTTOM_VAL(两下)时,对应的概率为PROB_BOTH_BOTTOM;当Y取LEFT_TOP_VAL(左上)时,对应的概率为PROB_ONLY_LEFT_TOP;当Y取LEFT_BOTTOM_VAL(左下)时,对应的概率为PROB_ONLY_LEFT_BOTTOM。

def fillYCPT(bayesNet, gameState):
    """
    Question 2: Bayes net probabilities

    Fill the CPT that gives the prior probability over the y position variable.
    See the definition of `fillXCPT` above for an example of how to do this.
    You can use the PROB_* constants imported from layout rather than writing
    probabilities down by hand.
    """

    yFactor = bn.Factor([Y_POS_VAR], [], bayesNet.variableDomainsDict())
    "*** YOUR CODE HERE ***"
    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)
    
    "*** END YOUR CODE HERE ***"
    bayesNet.setCPT(Y_POS_VAR, yFactor)

结果

在这里插入图片描述

Question 3 (5 points): Join Factors

原理

因为贝叶斯公式:P(X|Y)=P(Y|X)*P(X)/P(Y),所以给定先验概率P(Y)和后验概率P(Y|X),以及许多factors的factor列表,就能够得出P(X,Y)。

方法

对于Question 3,将在factorOperations.py的joinFactors函数中编写代码,输入是具有许多factors的factor列表,应该计算用于连接factors的有条件变量集和非条件变量集,返回的是一个新的factor,它包含这些变量、输入的factor对应行乘积的概率。假设所有输入的variableDomainsDict因子是相同的,因为它们来自同一个贝叶斯网络。joinFactors只允许非条件变量出现在一个输入的factor中。可能会用到的函数有:
Factor.getAllPossibleAssignmentDicts
Factor.getProbability
Factor.setProbability
Factor.unconditionedVariables
Factor.conditionedVariables
Factor.variableDomainsDict

对于Question 3,首先列出条件变量和无条件变量的列表,因为joinFactors不允许多个因子均存在非条件变量,所以需要过滤条件变量列表,最后计算概率。

代码

def joinFactors(factors):
    """
    Question 3: Your join implementation 

    Input factors is a list of factors.  
    
    You should calculate the set of unconditioned variables and conditioned 
    variables for the join of those factors.

    Return a new factor that has those variables and whose probability entries 
    are product of the corresponding rows of the input factors.

    You may assume that the variableDomainsDict for all the input 
    factors are the same, since they come from the same BayesNet.

    joinFactors will only allow unconditionedVariables to appear in 
    one input factor (so their join is well defined).

    Hint: Factor methods that take an assignmentDict as input 
    (such as getProbability and setProbability) can handle 
    assignmentDicts that assign more variables than are in that factor.

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

    # typecheck portion
    setsOfUnconditioned = [set(factor.unconditionedVariables()) for factor in factors]
    if len(factors) > 1:
        intersect = functools.reduce(lambda x, y: x & y, setsOfUnconditioned)
        if len(intersect) > 0:
            print("Factor failed joinFactors typecheck: ", factor)
            raise ValueError("unconditionedVariables can only appear in one factor. \n"
                    + "unconditionedVariables: " + str(intersect) + 
                    "\nappear in more than one input factor.\n" + 
                    "Input factors: \n" +
                    "\n".join(map(str, factors)))


    "*** YOUR CODE HERE ***"
    factors_list = [i for i in factors]
    unconditioned_variables = []
    conditioned_variables = []
    variablesDomainDict = factors_list[0].variableDomainsDict()

    # 列出非条件变量和条件变量列表
    for factor in factors_list:
        unconditioned_variables += [i for i in factor.unconditionedVariables() if i not in unconditioned_variables]

        conditioned_variables += [i for i in factor.conditionedVariables() if i not in conditioned_variables]

    # 使用remove函数过滤条件变量列表
    for variable in unconditioned_variables:
        if variable in conditioned_variables:
            conditioned_variables.remove(variable)

    retFactor = Factor(unconditioned_variables, conditioned_variables, variablesDomainDict)

    # 计算概率
    assignments = retFactor.getAllPossibleAssignmentDicts()
    for assignment in assignments:
        probability = 1
        for factor in factors_list:
            probability = probability * factor.getProbability(assignment)

        retFactor.setProbability(assignment, probability)
    
    return retFactor
    "*** END YOUR CODE HERE ***"

结果

在这里插入图片描述

数据及效果对比

在这里插入图片描述

Bayes Net Structure

在这里插入图片描述

Bayes Net Probabilities

在这里插入图片描述

Join Factors

在这里插入图片描述

收获

在本周,我们从之前的知识表示,转移到贝叶斯网络的学习。在课堂上学习到了贝叶斯网络的构造等知识。

对于Question 1,要求进行贝叶斯网络的构造,贝叶斯网络是一种描述随机变量之间互相条件独立关系的有向无环图。贝叶斯网络的有向无环图中的节点表示随机变量,它们可以是可观察到的变量,或隐变量、未知参数等。认为有因果关系(或非条件独立)的变量或命题则用箭头来连接。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(children)”,两节点就会产生一个条件概率值。连接两个节点的箭头代表此两个随机变量具有因果关系,或非条件独立。每个节点代表一个随机变量对其父节点的条件概率分布P( X X X|parents( X X X)),每一条边可以理解成变量之间的联系。虽然一般来讲这种“联系”可以被解释为“因果关系”,但是实际上这种关系并不一定是因果关系,只要两个变量之间互相不条件独立就应该被连在一起。在贝叶斯网络中,已知X的父节点parents( X X X)时 X X X的条件概率分布P( X X X|parents( X X X))与已知 X X X的父节点时网络中 X X X的“祖先节点”的概率分布P(ancestor( X X X)|parents( X X X))互相条件独立。根据题目要求,可以得知本次需要构建一个链式网络,即head-to-tail结构,而该结构也存在两种情况,当a与b不独立时,有:P(a,b,c)=P(a)*P(c|a)*P(b|c),
当a与b独立时,有:P(a,b|c)*P( c c c)=P(a,b,c),据题目给出的贝叶斯网络图可知,此处的X Positions和Y Positions与Observations不独立,因此满足P(a,b,c)=P(a)*P(c|a)*P(b|c)。

对于Question 2,要求填写条件概率表CPT,使用Question 1已经构造完成的贝叶斯网络进行CPT的撰写。

对于Question 3,要求输入具有许多factors的factor列表,计算用于连接factors的有条件变量集和非条件变量集,返回一个新的factor,它包含这些变量、输入的factor对应行乘积的概率。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值