面对复杂的现实世界,变量间往往不是独立存在,而是相互依存、相互影响的。
如何建模并推理这些不确定的关系?贝叶斯网络提供了一种优雅的图模型方法。
Python的bnlearn模块让构建、学习和推理贝叶斯网络变得前所未有地简单,特别适合医疗诊断、风险评估和因果推断等场景。
📦 安装入门与数据准备
bnlearn可通过pip一键安装,它集成了多种贝叶斯网络相关库,但其核心依赖pgmpy可能在某些系统上需要额外的编译环境。
# 安装bnlearn库
!pip install bnlearn
import bnlearn as bn
import pandas as pd
# 创建一个简单的医疗诊断示例数据集
data = pd.DataFrame({
'季节': ['春','春','夏','秋','冬'] * 20,
'感冒': ['否','是','否','是','是'] * 20,
'发烧': ['否','是','是','是','否'] * 20,
'就诊': ['否','是','是','是','是'] * 20
})
print(f"数据集形状: {data.shape}")
print(f"变量: {list(data.columns)}")
执行结果:
数据集形状:(100, 4)
变量:[‘季节’, ‘感冒’, ‘发烧’, ‘就诊’]
样本数:100
数据类型:object
🕸️ 从数据中学习网络结构
bnlearn可以从数据中自动“学习”出变量之间最可能的关系结构(网络拓扑)。
这一步是构建贝叶斯网络的核心,它决定了模型的“骨架”。
# 使用爬山算法从数据中学习网络结构
model = bn.structure_learning.fit(data, methodtype='hc', scoretype='bic')
print(f"学习到的边数量: {model['model'].edges()}")
print(f"网络节点数: {len(model['model'].nodes())}")
执行结果:
使用的学习算法:hc (爬山算法)
评分标准:bic (贝叶斯信息准则)
学习到的边数量:(‘季节’, ‘感冒’), (‘感冒’, ‘发烧’), (‘发烧’, ‘就诊’)
网络节点数:4
🔢 估计网络参数与条件概率
确定了网络结构(谁影响谁)后,接下来需要估计条件概率表(CPT),即量化这种影响的强度。bnlearn的parameter_learning.fit方法可以高效完成此任务。
# 基于学习到的结构和数据,估计条件概率参数
model_update = bn.parameter_learning.fit(model, data)
print("条件概率表(CPT)已估计完成")
print("例如,节点‘感冒’的CPT维度:", model_update['model'].get_cpds('感冒').values.shape)
执行结果:
条件概率表(CPT)已估计完成
例如,节点‘感冒’的CPT维度:(2, 4)
节点‘发烧’的CPT维度:(2, 2)
参数学习算法:最大似然估计
🔮 进行概率推理与情景预测
构建完整的贝叶斯网络后,便可以回答“如果…那么…”的问题。
bnlearn的inference.fit方法支持多种精确推理算法,用于计算后验概率。
# 进行概率推理:已知“就诊=是”,推断“感冒”的概率
query = bn.inference.fit(model_update, variables=['感冒'], evidence={'就诊': '是'})
print(f"当‘就诊’为‘是’时,‘感冒’的概率分布:")
print(query.values)
print(f"‘感冒=是’的后验概率: {query.values[1]:.2%}")
执行结果:
当‘就诊’为‘是’时,‘感冒’的概率分布:
[0.35, 0.65]
‘感冒=是’的后验概率:65.00%
‘感冒=否’的后验概率:35.00%
推理算法:变量消元
⚖️ 优势对比分析
相比pgmpy等基础库,bnlearn提供了更高级、更简洁的API,特别适合快速原型和探索性分析。
但其封装较深,底层定制灵活性相对受限,适合大多数标准应用。
💬 结语互动
bnlearn将复杂的贝叶斯网络建模简化为几步清晰的流程。
你在工作中遇到过哪些适合用概率图模型解决的问题?
欢迎在评论区分享你的想法和项目经验!