最近在看《数学之美》,提到了贝叶斯网络,于是便简单搜了一下代码练习了【数据挖掘】贝叶斯网络理论及Python实现浪荡子爱自由的博客-CSDN博客贝叶斯网络,不过练习完我反而感觉更疑惑了,因为这些属于手动构建网络关系,要如何实现对数据全自动推算网络关系?先记录如下待后来探寻。
import warnings
warnings.filterwarnings("ignore")
贝叶斯网络是一种模拟人类推理过程中因果关系的不确定性处理模型,也是一些变量的联合概率分布的图形表示。通常包含两个部分,一个是贝叶斯网络结构图,它是一个有向无环图(DAG),其中图中的每个节点代表相应的变量,节点之间的连接关系代表了贝叶斯网络的条件独立语义。另一部分,就是节点和节点之间的条件概率表(CPT),也就是一系列的概率值。如果一个贝叶斯网络提供了足够的条件概率值,足以计算任何给定的联合概率,我们就称,它是可计算的,即可推理的。 什么是贝叶斯推断?使用贝叶斯方法处理不确定性,需要利用贝叶斯定理将先验分布更新至后验分布中,这无疑是最流行的方法之一。但还存在其他非贝叶斯方法,例如集中不等式就是非贝叶斯方法,它们允许计算置信区间和不确定性集合。
贝叶斯网络随机变量的连接方式主要有顺连、分连、汇连这三种连接形式。
1.针对已知结构及参数,先采用BayesianModel构造贝叶斯网结构
基于python的pgmpy库构建贝叶斯网络,其步骤是先建立网络结构, 然后填入相关参数。 1.针对已知结构及参数,先采用BayesianModel构造贝叶斯网结构
构建网络
from pgmpy.models import BayesianModel
cancer_model = BayesianModel([('Pollution', 'Cancer'),
('Smoker', 'Cancer'),
('Cancer', 'Xray'),
('Cancer', 'Dyspnoea')])
这个贝叶斯网络中有五个节点: Pollution, Cancer, Smoker, Xray, Dyspnoea.
(‘Pollution’, ‘Cancer’): 一条有向边, 从 Pollution 指向 Cancer, 表示环境污染有可能导致癌症.
(‘Smoker’, ‘Cancer’): 吸烟有可能导致癌症.
(‘Cancer’, ‘Xray’): 得癌症的人可能会去照X射线.
(‘Cancer’, ‘Dyspnoea’): 得癌症的人可能会呼吸困难.
cancer_model
<pgmpy.models.BayesianModel.BayesianModel at 0x7f57c7f593d0>
2.通过TabularCPD构造条件概率分布CPD(condition probability distribution)表格,最后将CPD数据添加到贝叶斯网络结构中,完成贝叶斯网络的构造。
from pgmpy.factors.discrete import TabularCPD
cpd_poll = TabularCPD(variable='Pollution', variable_card=2,
values=[[0.9], [0.1]])
cpd_smoke = TabularCPD(variable='Smoker', variable_card=2,
values=[[0.3], [0.7]])
cpd_cancer = TabularCPD(variable='Cancer', variable_card=2,
values=[[0.03, 0.05, 0.001, 0.02],
[0.97, 0.95, 0.999, 0.98]],
evidence=['Smoker', 'Pollution'],
evidence_card=[2, 2])
cpd_xray = TabularCPD(variable='Xray', variable_card=2,
values=[[0.9, 0.2], [0.1, 0.8]],
evidence=['Cancer'], evidence_card=[2])
cpd_dysp = TabularCPD(variable='Dyspnoea', variable_card=2,
values=[[0.65, 0.3], [0.35, 0.7]],
evidence=['Cancer'], evidence_card=[2])
cancer_model.add_cpds(cpd_poll, cpd_smoke, cpd_cancer, cpd_xray, cpd_dysp)
这部分代码主要是建立一些概率表, 然后往表里面填入了一些参数.
Pollution: 有两种概率, 分别是 0.9 和 0.1.
Smoker: 有两种概率, 分别是 0.3 和 0.7. (意思是在一个人群里, 有 30% 的人吸烟, 有 70% 的人不吸烟)
Cancer: envidence 表示有 Smoker 和 Pollution 两个节点指向 Cancer 节点;
3.验证模型数据的正确性
测试网络结构是否正确
print(cancer_model.check_model())
True
4.贝叶斯网络
在构建了贝叶斯网之后, 我们使用贝叶斯网来进行推理. 推理算法分精确推理和近似推理. 精确推理有变量消元法和团树传播法; 近似推理算法是基于随机抽样的算法.
变量消除法是精确推断的一种方法.
from pgmpy.inference import VariableElimination
asia_infer = VariableElimination(cancer_model)
q = asia_infer.query(variables=['Cancer'], evidence={
'Smoker': 0})
print(q)
Finding Elimination Order: : 100%|██████████| 1/1 [00:00<00:00, 1096.55it/s]
Eliminating: Pollution: 100%|██████████| 1/1 [00:00<00:00, 888.25it/s]
+-----------+---------------+
| Cancer | phi(Cancer) |
+===========+===============+
| Cancer(0) | 0.0320 |
+-----------+---------------+
| Cancer(1) | 0.9680 |
+-----------+---------------+
案例2:学生成绩贝叶斯网络
from pgmpy.models import BayesianModel
from pgmpy.factors.discrete import TabularCPD
通过边来定义贝叶斯网络结构
stu_model = BayesianModel([('D', 'G'), ('I', 'G'), ('G', 'L'), ('I', 'S')])
定义条件概率分布
cpd_d = TabularCPD(variable='D', variable_card=2, values=[[0.6], [0.4]])
cpd_i = TabularCPD(variable='I', variable_card=2, values=[[0.7],[0.3]])
# variable:变量
# variable_card:基数
# values:变量值
# evidence:
cpd_g = TabularCPD(variable='G', variable_card=3,
values=[[0.3, 0.05, 0.9, 0.5],
[0.4, 0.25, 0.08, 0.3],
[0.3, 0.7, 0.02, 0.2]],
evidence=['I', 'D'],
evidence_card=[2, 2])
cpd_l = TabularCPD(variable='L', variable_card=2,
values=[[0.1, 0.4, 0.99],
[0.9, 0.6, 0.01]],
evidence=['G'],
evidence_card=[3])
cpd_s = TabularCPD(variable='S', variable_card=2,
values=[[0.95, 0.2],
[0.05, 0.8]],
evidence=['I'],
evidence_card=[2])
将有向无环图与条件概率分布表关联
stu_model.add_cpds(cpd_d, cpd_i, cpd_g, cpd_l, cpd_s)
验证模型:检查网络结构和CPD,并验证CPD是否正确定义和总和为1
print(stu_model.check_model())
True
import numpy as np
import pandas as pd
from pgmpy.models import BayesianModel
from pgmpy.estimators import MaximumLikelihoodEstimator, BayesianEstimator
raw_data = np.random.randint(low=0, high=2, size=(1000, 5))
data = pd.DataFrame(raw_data, columns=['D', 'I', 'G', 'L', 'S'])
model = BayesianModel([('D', 'G'), ('I', 'G'), ('I', 'S'), ('G', 'L')])
model.fit(data, estimator=MaximumLikelihoodEstimator)
for cpd in model.get_cpds():
print ("CPD of {variable}:".format(variable=cpd.variable))
print(cpd)
CPD of D:
+------+------+
| D(0) | 0.49 |
+------+------+
| D(1) | 0.51 |
+------+------+
CPD of G:
+------+---------------------+-----+---------------------+
| D | D(0) | ... | D(1) |
+------+---------------------+-----+---------------------+
| I | I(0) | ... | I(1) |
+------+---------------------+-----+---------------------+
| G(0) | 0.46320346320346323 | ... | 0.519650655021834 |
+------+---------------------+-----+---------------------+
| G(1) | 0.5367965367965368 | ... | 0.48034934497816595 |
+------+---------------------+-----+---------------------+
CPD of I:
+------+-------+
| I(0) | 0.512 |
+------+-------+
| I(1) | 0.488 |
+------+-------+
CPD of S:
+------+----------+---------------------+
| I | I(0) | I(1) |
+------+----------+---------------------+
| S(0) | 0.515625 | 0.48770491803278687 |
+------+----------+---------------------+
| S(1) | 0.484375 | 0.5122950819672131 |
+------+----------+---------------------+
CPD of L:
+------+--------------------+---------------------+
| G | G(0) | G(1) |
+------+--------------------+---------------------+
| L(0) | 0.5424430641821946 | 0.46034816247582205 |
+------+--------------------+---------------------+
| L(1) | 0.4575569358178054 | 0.539651837524178 |
+------+--------------------+---------------------+
这个有什么用?
网友评论