python实现贝叶斯网络的概率推导(Probabilistic Inference) (2)

该实验的主程序(包括读取指定数据文件的函数)如下:

import sys from BN import BN from cpt import cpt # 读取文件并生成一个贝叶斯网络 def readBN(filename): f = open(filename, 'r') # 读取变量数 nums = int(f.readline()) f.readline() # 读取变量名称 variables = f.readline()[:-1].split(' ') f.readline() # 读取有向图邻接表 graph = [] for i in range(nums): line = f.readline()[:-1].split(' ') graph.append(list(map(int, line))) f.readline() # 读取cpt表 # 注意,文件中数据格式必须完全按照指定要求,不可有多余的空行或空格 cpts = [] for i in range(nums): probabilities = [] while True: line = f.readline()[:-1].split(' ') if line != ['']: probabilities.append(list(map(float, line))) else: break CPT = cpt(variables[i], [], probabilities) cpts.append(CPT) f.close() # 根据邻接表为每个节点生成其父亲节点 # 注意,这里父亲节点的顺序是按照输入的variables的顺序排列的,不保证更换测试文件时的正确性 for i in range(nums): for j in range(nums): if graph[i][j] == 1: cpts[j].parents.append(variables[i]) # 测试父节点生成情况 # for i in range(nums): # print(cpts[i].parents) bayesnet = BN(nums, variables, graph, cpts) return bayesnet # 读取需要求取概率的命令 def readEvents(filename, variables): # 条件概率在本程序中的表示: # 对变量分类,2表示待求的变量,3表示隐含的需要被消去的变量,0和1表示条件变量的false和true # 例如变量为[Burglar, Earthquake, Alarm, John, Mary] # 待求的条件概率为P(Burglar | John=true, Mary=false),则event为[2, 3, 3, 1, 0] f = open(filename, 'r') events = [] while True: line = f.readline() event = [] if line == "\n": continue elif not line: break else: for v in variables: index = line.find(v) if index != -1: if line[index+len(v)] == ' ' or line[index+len(v)] == ',': event.append(2) elif line[index+len(v)] == '=': if line[index+len(v)+1] == 't': event.append(1) else: event.append(0) else: event.append(3) # 检查文本错误 if len(event) != len(variables): sys.exit() events.append(event) return events # 主程序 filename1 = "burglarnetwork.txt" bayesnet = readBN(filename1) filename2 = "burglarqueries.txt" events = readEvents(filename2, bayesnet.variables) for event in events: print(bayesnet.calculateProbability(event)) 知识总结

这一部分主要记录在实验过程中参考的博客,方便之后复习

由于没有系统学过python,其中有挺多都是python基本技巧的,看来以后还要系统学一遍

python中判断readline读到文件末尾
这篇博客参考的是读文件时如何判断读完

python 字符串和整数,浮点型互相转换
这篇博客参考的是如何将从文件读进来的文本转化成数据

python-使用列表创建字典
这篇博客参考的是用list创建字典的方式

python在字符串中查找字符
在Python中,如何将一个字符串数组转换成整型数组
Python-8、Python如何将整数转化成二进制字符串
这三篇博客同样是在处理读入数据时参考的

Python3浮点型(float)运算结果不正确处理办法
由于多个浮点数的概率在连乘的时候,导致出现了较大误差,因此查了这篇博客,不过最后没有使用Decimal模块,而是直接乘1000再除1000解决了。

Python 技巧(三)—— list 删除一个元素的三种做法

python numpy查询数组是否有某个数的总个数
这篇博客,我试了一下发现不可以,报错说不可以对布尔类型求和,恐怕是python版本的问题吧,这个我暂时没有深究,自己写了一个count函数

python list中数字与一个数相乘
对于list中一个数字与一个数相乘的方法,网上普遍给出的另一种方法是用numpy库,其生成的数组可以直接与数相乘。然而由于我全程没有用到numpy,不想在这个地方单独用个numpy,所以采用了本篇博客中的方法。

python反转列表的三种方式
由于实验指导书指定的输出结果与我算出来的相反,因此翻转了一次列表

实验总结

用一句话总结该实验的作用:使我对于贝叶斯网络的概率推导过程理解的更加透彻

做完实验才意识到如果没有手推几个贝叶斯网络的概率推导,那几乎相当于没有学,要是放到考试绝对写不出来(想起了之前听觉考试,平时没有练习过手推隐马尔科夫,导致考试的时候给了一个很简单的HMM,最后由于太不熟练导致时间不足而没有写完)

整个实验过程比较顺畅,总时间大致8小时左右,其中写代码时间很短,全程几乎没有遇到bug,花时间的地方在于如何设计表示条件概率。这个东西花了我特别长的时间,最后的形式个人感觉不是特别简洁,但是放在程序里还是挺好用的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpjsf.html