GameMale
登陆 / 注册 搜索

USERCENTER

SEARCHSITE

搜索

查看: 1941|回复: 17
收起左侧

[技术交流] 【Python】【原创】条件概率分布与贝叶斯网络

[复制链接] |关注本帖

邪恶的面具海盗弯钩神秘的红茶冒险用绷带魔法石碑箭术卷轴质量效应三部曲

     楼主| 白冥 发表于 2025-1-26 19:40:54 | 显示全部楼层 |阅读模式 <
    本帖最后由 白冥 于 2025-1-28 16:55 编辑

    目录      

    • 概述
    • 依赖库
    • 类与方法概述
    • Cpd类的详细说明
    • Bayesian_Network类的详细说明
    • 示例代码


    概述      

            本贴将介绍两种用于构建和操作贝叶斯网络的 Python 类: Cpd  和  Bayesian_Network 。这些类提供了构建贝叶斯网络所需的核心功能,允许定义变量、变量的条件概率表(CPD),以及设置变量间的依赖关系。

    依赖库      

    该项目依赖以下几个 Python 库:
    • collections.deque : 用于队列操作,特别是在实现图的拓扑排序时。
    • math : 提供数学计算支持。
    • typing : 用于类型注解。


    类与方法概述      

    3.1 Cpd类

             Cpd  类用于表示贝叶斯网络中每个节点的条件概率分布(CPD)。它通过指定变量及其父节点,定义了该变量在给定父节点条件下的概率值。

    1. class Cpd:
    2.     def __init__(self, variable: str, variable_card: int, values: List[List[float]], parents: List[str] = [], parent_cards: List[int] = []):
    3.         self.variable=variable
    4.         self._variable_card = variable_card
    5.         self.values=values
    6.         self.parents=parents
    7.         self._parent_cards = parent_cards
    复制代码


    关键属性:
    • variable : 当前变量的名称(字符串类型)。
    • variable_card : 当前变量的状态数(整数类型)。
    • values : 条件概率表(二维列表,每行对应一种父节点状态的条件概率)。
    • parents : 当前变量的父节点列表(字符串类型)。
    • parent_cards : 父节点的状态数(整数类型列表)。


    3.2 Bayesian_Network类

    Bayesian_Network 类用于表示贝叶斯网络,提供了网络结构的定义、拓扑排序和条件概率分布的添加等功能。贝叶斯网络由节点(变量)和它们之间的有向边组成。


    1. class Bayesian_Network:
    2.     def __init__(self,edges:List[Tuple[str,str]]):
    3.         self._nodes=self._add_nodes(edges)
    4.         self._parents=self._add_parents(edges, self._nodes)
    5.         self._neighbors=self._add_neighbors(edges, self._nodes)
    6.         if not self._is_acyclic_graph(edges, self._nodes, self._neighbors):
    7.             raise ValueError("Bayesian network is DAG")
    8.         self._cpds=dict()
    9.     def _add_nodes(self, edges):
    10.         nodes=set()
    11.         for node0,node1 in edges:
    12.             nodes.update([node0,node1])
    13.         return list(nodes)
    14.     def _add_parents(self, edges, nodes):
    15.         parents = {node: set() for node in nodes}
    16.         for node0, node1 in edges:
    17.             parents[node1].add(node0)
    18.         return parents
    19.     def _add_neighbors(self, edges, nodes):
    20.         neighbors = {node: set() for node in nodes}
    21.         for node0, node1 in edges:
    22.             neighbors[node0].add(node1)
    23.         return neighbors
    24.     def _is_acyclic_graph(self, edges, nodes, neighbors):
    25.         in_degree = {node: 0 for node in nodes}  
    26.         for node0, node1 in edges:
    27.             in_degree[node1] += 1
    28.         queue = deque([node for node, degree in in_degree.items() if degree == 0])
    29.         visited = set()
    30.         while queue:
    31.             node = queue.popleft()
    32.             for neighbor in neighbors[node]:
    33.                 in_degree[neighbor] -= 1
    34.                 if in_degree[neighbor] == 0:
    35.                     queue.append(neighbor)
    36.             visited.add(node)
    37.         return len(visited)==len(in_degree)
    38.     def add_cpds(self, *cpds: Cpd):
    39.         for cpd in cpds:
    40.             if cpd.variable not in self._nodes:
    41.                 raise ValueError(f"Variable {cpd.variable} is not a node in the model")
    42.             for parent in cpd.parents:
    43.                 if parent not in self._parents[cpd.variable]:
    44.                     raise ValueError(f"Parent node {parent} is not connected to {cpd.variable} in the model")
    45.             self._cpds[cpd.variable] = cpd
    复制代码

    关键方法:
    • __init__(self, edges: List[Tuple[str, str]]) : 初始化贝叶斯网络,接受网络中的边(变量间的依赖关系)。
    • _add_nodes(self, edges) : 从边列表中提取所有节点。
    • _add_parents(self, edges, nodes) : 生成每个节点的父节点列表。
    • _add_neighbors(self, edges, nodes) : 生成每个节点的邻居节点列表。
    • _is_acyclic_graph(self, edges, nodes, neighbors) : 检查图是否为无环图(DAG)。
    • add_cpds(self, *cpds: Cpd) : 向网络中添加条件概率分布(CPD)。


    Cpd类的详细说明      

    4.1  __init__ 方法


        和上面的一样,不说了


    Bayesian_Network类的详细说明      

    5.1  __init__方法

      edges : 由一组二元组(边)组成的列表,表示网络中节点之间的依赖关系。每个二元组表示一个有向边,其中第一个元素是父节点,第二个元素是子节点。


            此方法用于初始化贝叶斯网络。通过提供网络中的边,它将自动添加所有节点、父节点和邻居节点。同时,方法会检查网络的拓扑是否是无环图(DAG),因为贝叶斯网络必须满足这一条件。如果图中存在环,则会抛出  ValueError  异常。


    5.2 _add_nodes 方法
    5.3 _add_parents 方法
    5.4 _add_neighbors 方法

            以上方法的逻辑都是一样的,相信大家光看代码就能清楚。都是遍历边,然后生成对应的数据结构。不再赘述。


    5.5  _is_acyclic_graph 方法

             edges : 由一组二元组(边)组成的列表,表示网络中节点之间的依赖关系。
             nodes : 网络中所有节点的列表。
             neighbors : 每个节点的邻居节点列表。
            此方法用于检查网络中的图是否为有向无环图(DAG)。通过计算每个节点的入度并进行拓扑排序,验证图是否有环。如果存在环,方法将返回  False ;否则返回  True


    5.6   add_cpds 方法

             cpds : 一个或多个  Cpd  实例,表示添加到网络中的条件概率分布。
            此方法用于将条件概率分布添加到贝叶斯网络中。它检查每个  Cpd  实例是否有效,即变量是否在网络中,并且父节点是否存在于网络的父节点列表中。如果  Cpd  实例无效,则抛出  ValueError  异常。


    示例代码      

    1. # 定义贝叶斯网络的边
    2. edges = [
    3.     ('A', 'B'),
    4.     ('A', 'C'),
    5.     ('B', 'D'),
    6.     ('C', 'D')
    7. ]

    8. # 创建贝叶斯网络实例
    9. bn = Bayesian_Network(edges)

    10. # 创建条件概率分布实例
    11. cpd_A = Cpd(variable='A', variable_card=2, values=[[0.1], [0.9]])
    12. cpd_B = Cpd(variable='B', variable_card=2, values=[[0.8, 0.2], [0.3, 0.7]], parents=['A'], parent_cards=[2])
    13. cpd_C = Cpd(variable='C', variable_card=2, values=[[0.7, 0.3], [0.4, 0.6]], parents=['A'], parent_cards=[2])
    14. cpd_D = Cpd(variable='D', variable_card=2, values=[[0.6, 0.4, 0.5, 0.5], [0.2, 0.8, 0.3, 0.7]], parents=['B', 'C'], parent_cards=[2, 2])

    15. # 将条件概率分布添加到贝叶斯网络中
    16. bn.add_cpds(cpd_A, cpd_B, cpd_C, cpd_D)
    复制代码




    补充-2025-01-27      修改次数4
            
            贝叶斯网络,是一种概率图模型,它通过DAG表示一组随机变量及其条件依赖关系。当我们想要表示一组随机变量的因果关系时,最常使用贝叶斯网络。
            贝叶斯网络的局部独立性:对于贝叶斯网络内的任何随机变量X,若它的父级变量是Pa(X),那么X与自身的除父级节点外的任何非后代变量Non-Desc(X),都与X条件独立:记作X⊥Non-Desc(X) | Pa(X)。
            贝叶斯网络的基本结构:
                链式结构A→B→C
                V型结构A→B←C
                倒V型结构A←B→C
            贝叶斯网络的全局独立性:对于贝叶斯网络内的任意随机变量X,若对于任意不是X且不与X相邻的的随机变量Y,若X,Y之间任意路径path都存在阻断点W,则X,Y条件独立。这称为贝叶斯网络的全局独立性,记为X⊥Y | W。
            阻断点:
                对于路径path上的任意链式结构…A→B→C…,若随机变量B是给定的,则B是路径path上的阻断点;
                对于路径path上的任意V型结构…A→B←C…,若随机变量B是不定的,则B是路径path上的阻断点;
                对于路径path上的任意倒V型结构…A←B→C…,若随机变量B是给定的,则B是路径path上的阻断点。

    补充-2025-01-28      修改次数5
            
            独立性能做一个事情,那就是化简概率表达式。事实上,任何一个贝叶斯网络,都可以唯一表示一个分布,那就是全体随机变量的联合分布。
            对于一个有N个随机变量的贝叶斯网络,它代表全体随机变量的联合分布,根据概率链式法则我们知道,P(X₁,X₂,X₃,…,Xɴ) = P(X₁|X₂,X₃,…,Xɴ) × P(X₂|X₃,X₄,…,Xɴ) × P(X₃|X₄,X₅,…,Xɴ) × … × P(Xɴ|Xɴ₋₁) × P(Xɴ)。
            对于我们所举的例子,就以这张图为例。
    (节点,箭头代表依赖关系)
            假设一个贝叶斯网络的节点和边构成的DAG如图所示,它代表的联合概率分布为P(A,B,C,D,E,F,G) = P(A|B,C,D,E,F,G) × P(B|C,D,E,F,G) × P(C|D,E,F,G) × P(D|E,F,G) × P(E|F,G) × P(F|G) × P(G)
            让我们分析每个点的独立性。

    -------------

            由局部独立性可得:
            A的父级变量是B,C,则A⊥D,E,F,G | B,C
            B的父级变量是D,则B⊥C,E,F,G | D
            C的父级变量是D,F,G,则C⊥B,E | D,F,G
            D的父级变量是E,则D⊥F,G | E
            E,F,G没有父级变量

    ------------

            由全局独立性可得:
            (A,B,C,D由于可能独立的点都找完了,剩下来的都是父级节点或后代节点,是绝对相关的,因此不分析)
            E到F有两条路径:
                E→D→C←F,C是阻断点
                E→D→B→A←C←F,A是阻断点
                因此E⊥F | A,C
            E到G有两条路径:
                E→D→C←G,C是阻断点
                E→D→B→A←C←G,A是阻断点
                因此E⊥G | A,C
            F到G有一条路径:
                F→C←G,C是阻断点
                因此F⊥G | C

    ------------

            由随机变量独立的性质,P(A,B,C,D,E,F,G)可化简为 P(A,B,C,D,E,F,G) = P(A|B,C) × P(B|D) × P(C|D,F,G) × P(D|E) × P(E) × P(F) × P(G)。
            此时此刻你会发现,贝叶斯网络全体随机变量的联合分布就是贝叶斯网络的全体随机变量的cpd(条件概率分布)的乘积,即P(X₁,X₂,X₃,…,Xɴ) = ΠP(Xᵢ | Pa(Xᵢ)) (i = 1 → N)。


    补充-2025-01-28      修改次数2
            
            所谓边际化就是把联合分布中若干随机变量分离出来考虑,消除对需求无关的变量。边际化最简单的方式就是变量消除。
            假如我们只想知道P(A,B,C),我们就需要消除D,E,F,G的影响。
            我们知道了P(A,B,C,D,E,F,G) = P(A|B,C) × P(B|D) × P(C|D,F,G) × P(D|E) × P(E) × P(F) × P(G)。
            根据全概率公式,我们有P(A,B,C) = P(A|B,C) × Σᴅ(P(B|D) × ΣғΣɢ(P(C|D,F,G) × Σᴇ(P(D|E) × P(E) × P(F) × P(G))))
            事实上,我们边际化对任何随机变量的联合分布都有效,最终能得到若干随机变量的联合分布或单一随机变量的边际分布。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x

    评分

    参与人数 1血液 +3 追随 +1 收起 理由
    沐雨慕鱼 + 3 + 1

    查看全部评分

      收起(3)
    回复

    使用道具 举报

    炼金之心达拉然骑兽之子月亮提灯夏之歌男色时代最终幻想XVI荒野大镖客:救赎 II黑神话:悟空

      zhnlwwdzz 发表于 2025-3-2 13:48:26 | 显示全部楼层 <
      回复

      举报

      万众瞩目神奇宝贝大师球神奇宝贝图鉴『搓粉团珠』雪王的心脏肉垫手套『落樱缤纷』里昂‧S‧甘乃迪小小安全帽丹雀衔五穗,人间始丰登

        zhuovboyan 发表于 2025-2-9 21:44:31 | 显示全部楼层 <
        回复

        举报

        满是血迹的徽章杰夫‧莫罗莱因哈特·威尔海姆石鬼面阿帕茶岛田半藏知识大典虎克船长

          1051506056 发表于 2025-2-1 14:36:02 | 显示全部楼层 <
          回复

          举报

          『林中过夜』杰森‧斯坦森守卫: 轮班侦察阿拉喵?神灯雪王的心脏夜魔护符许愿之星我的冶金打火机阿拉贡·王者归来『搓粉团珠』

            白鸟探 发表于 2025-1-29 15:28:11 | 显示全部楼层 <
            回复

            举报

            【夏日限定】夏日的泰凯斯射手的火枪虚空之海的鲸泰比里厄斯很久很久以前史莱姆牧场【新春限定】果体 隆和你一起飞行的皮卡丘丹妮莉丝·坦格利安

              DiederichYH 发表于 2025-1-29 14:38:46 | 显示全部楼层 <
              回复

              举报

                hush 发表于 2025-1-27 20:51:19 | 显示全部楼层 <
                回复

                举报

                捡到了肥皂灵光补脑剂原罪之初纯真护剑

                  Sam30 发表于 2025-1-27 16:42:11 | 显示全部楼层 <
                  感覺是比較特殊的東西呢, 看看之後有沒有機會可以用上的了
                  回复

                  举报

                  自定义男从Homunculus极·龙の意新神的赐福官复原职实现梦想冰原史莱姆牧场传奇虚空之海的鲸不朽之恋

                    2297988 发表于 2025-1-27 13:06:21 | 显示全部楼层 <
                    回复

                    举报

                    『住在GM村』『道具超市』黑神话:悟空perrito『不败之花』卡利亚权杖幸福的小阿尔GM吸血伯爵Jo太螂钢铁侠

                      黑夜下的灯光 发表于 2025-1-27 11:04:59 | 显示全部楼层 <
                      回复

                      举报

                      诺克提斯·路西斯·伽拉姆克莱夫・罗兹菲尔德【夏日限定】夏日的泰凯斯终归一人钢铁侠杰森‧斯坦森月光骑士传奇刀锋女王 - 归宿剑指撒冷

                        万俟 发表于 2025-1-27 08:25:46 | 显示全部楼层 <
                        就围观一下,贝叶斯和条件概率我都懂,代码看不太懂
                        回复

                        举报

                          kisakuni 发表于 2025-1-27 02:28:26 | 显示全部楼层 <
                          回复

                          举报

                            a5173347 发表于 2025-1-26 23:32:14 | 显示全部楼层 <
                            回复

                            举报

                            Zootopia森林羊男龙腾世纪:审判荒野大镖客:救赎 II伪造的红石小凤凰GM論壇勛章

                              荆棘之环 发表于 2025-1-26 23:21:25 | 显示全部楼层 <
                              太深奥了,所以是用在?
                              回复

                              举报

                              GM論壇進階勛章GM吸血伯爵月亮提灯柏树枝艾吉奥灵魂残絮聚合法肉乖乖神奇宝贝图鉴

                                aboab 发表于 2025-1-26 21:48:44 | 显示全部楼层 <
                                回复

                                举报

                                安德森‧戴维斯安德鲁·库珀Drover冒险专用绳索卡利亚权杖不朽之恋“腐败女神”玛莲妮亚

                                  没药 发表于 2025-1-26 21:08:09 | 显示全部楼层 <
                                  回复

                                  举报

                                  史蒂芬·斯特兰奇GM論壇進階勛章念念往日士官盔牧羊人瑞雪兆丰年,生灵万物新森林羊男青梅竹马

                                    天逸0 发表于 2025-1-26 20:58:53 | 显示全部楼层 <
                                    回复

                                    举报

                                    守卫: 坚守眼位裸体克里斯虚空之海的鲸黄粱一梦【新春限定】果体 隆新神的赐福都市:天际线2永远的克叔業火死鬥实现梦想

                                      娱乐法师火布偶 发表于 2025-1-26 20:10:31 | 显示全部楼层 <
                                      论坛架构支持md估计只能靠架构官方的更新了
                                      回复

                                      举报

                                      您需要登录后才可以回帖 登录 | 立即注册

                                      本版积分规则

                                      文字版|手机版|小黑屋|GameMale

                                      GMT+8, 2025-5-15 23:25 , Processed in 0.137201 second(s), 133 queries , Redis On.

                                      Copyright © 2013-2025 GameMale

                                      All Rights Reserved.

                                      快速回复 返回列表