网易首页 > 网易号 > 正文 申请入驻

Python因果分析选哪个?六个贝叶斯推断库实测对比(含代码示例)

0
分享至

Python 生态里能用的因果库有很多选哪个往往要看你对模型的理解程度,以及项目对“可解释性”的要求。这篇文章将对比了六个目前社区中最常用的因果推断库:Bnlearn、Pgmpy、CausalNex、DoWhy、PyAgrum 和 CausalImpact

贝叶斯因果模型

在因果推断里所有变量可以粗略分成两种:驱动变量(driver variables)乘客变量(passenger variables)
驱动变量会直接影响结果,而乘客变量虽然跟结果有关但并不直接影响结果。区分这两者是整个因果分析的关键。比如在预测性维护或设备故障分析里,如果能识别出“导致故障”的那几个变量,后续的监控与优化策略就能有针对性地落地。

有时候,看似无关的变量其实藏着重要的效应。比如说假设某个工厂的发动机故障率在不同地区差异很大,你可能认为这是地理差异,其实真正的原因可能是工厂里湿度、保养周期或人员经验这样的隐含驱动因子。因果推断的价值就在这里——它帮助区分“看上去相关”和“真正原因”的区别。

相比纯预测模型,因果推断更像是在回答“为什么”,而不是“多少”。通过找出系统中真正起作用的变量,才能解释模型的行为,也才能对系统做出有效干预。

数据集与整体实验思路

为了让对比更直观,所有实验都使用相同的数据:Census Income 数据集。这个经典的数据集包含48,842 条记录14 个变量,多数为离散特征。
目标也很简单:拥有研究生(postgraduate)学历是否能显著提高年收入超过 50K 美元的概率?

下面的代码用于载入和清理数据。连续变量与敏感特征(如性别、种族等)被移除,以便专注在离散特征的因果结构学习上。

# 安装
pip install datazets
# 导入库
import datazets as dz
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 导入数据集并删除连续型与敏感特征
df = dz.import_example(data='census_income')
# 数据清洗
drop_cols = ['age', 'fnlwgt', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week', 'race', 'sex']
df.drop(labels=drop_cols, axis=1, inplace=True)
# 打印样本
df.head()

1、Bnlearn

bnlearn 是一个封装度很高的贝叶斯网络库,几乎把因果分析的标准流程都集成在一套 API 里。它支持离散、连续和混合类型数据,可以进行 结构学习参数学习(CPD 估计)推理(inference)合成数据生成(synthetic data generation)。
更重要的是,它把常用的独立性检验、评分函数、拓扑排序、模型比较和可视化都做成了开箱即用的函数。



下面是使用 HillClimbSearch 和 BIC 评分方法学习结构的完整流程代码

# 安装
pip install bnlearn
# 加载库
import bnlearn as bn
# 结构学习
model = bn.structure_learning.fit(df, methodtype='hillclimbsearch', scoretype='bic')
# 检验边显著性并剪枝
model = bn.independence_test(model, df, test="chi_square", alpha=0.05, prune=True)
# 参数学习(可选)
model = bn.parameter_learning.fit(model, df)
# 绘制图形
G = bn.plot(model, interactive=False)
dotgraph = bn.plot_graphviz(model)
dotgraph.view(filename=r'c:/temp/bnlearn_plot')

模型学得的 DAG(有向无环图)结构如下:



静态图展示了 bnlearn 学出的Census Income因果结构图。交互式版本可以直接查看每条边的条件概率分布。



DAG 学成之后,可以直接执行推理。例如计算当教育水平为博士时,收入大于 50K 的后验概率:

# 开始推理
query = bn.inference.fit(model, variables=['salary'], evidence={'education':'Doctorate'})
print(query)

结果如下:

salary <=50K : 29.1%
salary >50K : 70.9%

这个概率几乎符合我们的理解:博士学历的确带来更高的收入区间。

换成高中毕业(HS-grad)再试一次:

query = bn.inference.fit(model, variables=['salary'], evidence={'education':'HS-grad'})

得到:

salary <=50K : 83.8%
salary >50K : 16.2%

还可以组合多个条件,例如:

# 当 education=Doctorate 且 marital-status=Never-married 时,预测 workclass
query = bn.inference.fit(model, variables=['workclass'], evidence={'education':'Doctorate', 'marital-status':'Never-married'})

从整体来看,bnlearn 适合快速构建因果结构并做概率推理,功能完整。输入数据可为离散、连续或混合类型。对于想在业务场景中快速验证因果假设的人,这个库的学习曲线非常平缓。

2、 Pgmpy

Pgmpy 是一个更偏底层的概率图模型库,如果说 bnlearn 是“开箱即用”那 pgmpy 更像是一套“拼装工具箱”。他的灵活性非常高,但也意味着需要较强的贝叶斯建模功底。

这两个库的功能其实有重叠,因为 bnlearn 的底层实现部分依赖 pgmpy。但在 pgmpy 中,所有步骤都要自己搭建:数据处理、建模、参数估计、推理、可视化都要自己写。

下面是用 HillClimbSearch 和 BIC 评分方法做结构学习的例子:

# 安装 pgmpy
pip install pgmpy
# 导入函数
from pgmpy.estimators import HillClimbSearch, BicScore, BayesianEstimator
from pgmpy.models import BayesianNetwork, NaiveBayes
from pgmpy.inference import VariableElimination
# 导入数据并删除连续与敏感特征
df = bn.import_example(data='census_income')
drop_cols = ['age', 'fnlwgt', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week', 'race', 'sex']
df.drop(labels=drop_cols, axis=1, inplace=True)
# 创建估计器与评分方法
est = HillClimbSearch(df)
scoring_method = BicScore(df)
# 建立模型并打印边
model = est.estimate(scoring_method=scoring_method)
print(model.edges())

建好结构后需要手动拟合条件概率分布(CPD):

vec = {
'source': ['education', 'marital-status', 'occupation', 'relationship', 'relationship', 'salary'],
'target': ['occupation', 'relationship', 'workclass', 'education', 'salary', 'education'],
'weight': [True, True, True, True, True, True]
}
vec = pd.DataFrame(vec)
# 创建贝叶斯模型
bayesianmodel = BayesianNetwork(vec)
# 拟合模型
bayesianmodel.fit(df, estimator=BayesianEstimator, prior_type='bdeu', equivalent_sample_size=1000)
# 推理
model_infer = VariableElimination(bayesianmodel)
query = model_infer.query(variables=['salary'], evidence={'education':'Doctorate'})
print(query)

输出结果与 bnlearn 基本一致:

salary <=50K : 29.1%
salary >50K : 70.9%

不同的是,这个过程需要你自己定义 DAG、参数估计和推理方式。这个库灵活性很高,但显然更适合研究者或开发自定义因果框架的场景,而不是想“直接上手跑”的业务人员。

3、CausalNex

CausalNex 是一个专注于从数据中学习因果图并量化因果效应的 Python 库。它只支持离散分布,这点很重要。
所以在建模前必须把所有连续变量或高基数特征离散化,否则模型无法拟合。

文档里也明确提到,如果特征太多、状态太复杂,模型效果会明显下降。不过好处是,它提供了一些便捷函数来帮助降低类别数量和处理标签编码。

下面是一个完整的示例,仍然使用同样的 Census Income 数据。第一步需要把所有类别变量转为数值型(因为 NOTEARS 算法要求矩阵计算):

# 安装
pip install causalnex
# 导入库
from causalnex.structure.notears import from_pandas
from causalnex.network import BayesianNetwork
import networkx as nx
import datazets as dz
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt
le = LabelEncoder()
# 导入数据并删除连续与敏感特征
df = dz.get(data='census_income')
drop_cols = ['age', 'fnlwgt', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week', 'race', 'sex']
df.drop(labels=drop_cols, axis=1, inplace=True)
# 转换为数值型
df_num = df.copy()
for col in df_num.columns:
df_num[col] = le.fit_transform(df_num[col])

结构学习部分用的是 NOTEARS 算法,可以自动从相关矩阵中推导 DAG。不过输出可能太密集,需要设定阈值过滤掉弱边:

# 结构学习
sm = from_pandas(df_num)
# 阈值剪枝
sm.remove_edges_below_threshold(0.8)
# 绘图
plt.figure(figsize=(15,10))
edge_width = [d['weight']*0.3 for (u,v,d) in sm.edges(data=True)]
nx.draw_networkx(sm, node_size=400, arrowsize=20, alpha=0.6, edge_color='b', width=edge_width)



上图是 CausalNex 学出的结构图。没有标签的节点表示因为阈值太高被剪掉的弱边。也可以通过调整参数 w_threshold 控制网络稀疏度,或者用 tabu_edges 禁止某些边生成。

建好结构后,需要学习节点的条件概率分布:

# 第一步:创建 BayesianNetwork 实例
bn = BayesianNetwork(sm)
# 第二步:降低分类特征基数(可选)
# 第三步:定义每个节点的状态字典
# 第四步:拟合节点状态
bn = bn.fit_node_states(df)
# 第五步:拟合条件概率分布
bn = bn.fit_cpds(df, method="BayesianEstimator", bayes_prior="K2")
# 输出某个节点的 CPD
result = bn.cpds["education"]
print(result)

CausalNex 的可解释性和结构学习能力都不错,但预处理要求多、类型限制严格,对 Python 版本也挑剔(仅兼容 3.6–3.10)。如果只想跑标准数据,它表现稳定,但要集成到更复杂的生产环境,需要额外工作。

4、DoWhy

DoWhy 是一个专注于因果推断验证的库,设计理念与前面提到的贝叶斯网络工具完全不同。它并不尝试从数据中直接学习因果图,而是要求用户显式定义因果假设,包括:

  • 结果变量(outcome variable)
  • 处理变量(treatment variable)
  • 潜在混杂变量(common causes)

也就是说DoWhy 更像是一个验证框架用来系统地质疑和检验你提出的因果假设,而不是生成因果结构。

如果没有提供 DAG(因果图),它会自动把所有变量连接到结果与处理变量上。但实际使用中最好结合领域知识自行定义 DAG,否则模型会过度简化。

使用同样的 Census Income 数据集,只是处理变量定义为“是否拥有博士学位”:

# 安装
pip install dowhy
# 导入库
from dowhy import CausalModel
import dowhy.datasets
import datazets as dz
from sklearn.preprocessing import LabelEncoder
import numpy as np
le = LabelEncoder()
# 导入数据并删除连续和敏感特征
df = dz.get(data='census_income')
drop_cols = ['age', 'fnlwgt', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week', 'race', 'sex']
df.drop(labels=drop_cols, axis=1, inplace=True)
# 处理变量必须为二元
df['education'] = df['education']=='Doctorate'
# 将数据转换为数值型
df_num = df.copy()
for col in df_num.columns:
df_num[col] = le.fit_transform(df_num[col])
# 指定处理变量、结果变量和潜在混杂变量
treatment = "education"
outcome = "salary"
# Step 1: 创建因果图
model = CausalModel(
data=df_num,
treatment=treatment,
outcome=outcome,
common_causes=list(df.columns[~np.isin(df.columns, [treatment, outcome])]),
graph_builder='ges',
alpha=0.05,
)
# 查看模型
model.view_model()



上图展示了 DoWhy 自动生成的 DAG,结果变量为“salary”,处理变量为“education”。可以看到,模型假设教育水平会影响薪资,并且两者都可能受婚姻状态、工作类型等混杂因素的干扰。

接下来是识别和估计因果效应的步骤:

# Step 2: 识别因果效应
identified_estimand = model.identify_effect(proceed_when_unidentifiable=True)
print(identified_estimand)

一旦模型识别出可估计的因果效应,就可以计算平均处理效应(ATE):

# Step 3: 估计效应
estimate = model.estimate_effect(identified_estimand, method_name="backdoor.propensity_score_stratification")
print(estimate)

输出的平均效应值约为0.47,说明博士学位与高收入存在明显的正向因果关系。最后再做稳健性检验:

# Step 4: 稳健性验证
refute_results = model.refute_estimate(identified_estimand, estimate, method_name="random_common_cause")

DoWhy在学术界非常常见,优点是框架清晰、假设透明、验证逻辑完备; 缺点是对输入要求高(变量需二值化、分类需数值编码),且不能从数据自动学习结构。

换句话说,它假设你已经知道潜在的因果关系,现在只想验证这个假设是否合理。

5、PyAgrum

PyAgrum 是另一个功能相对完整的概率图模型库。它支持贝叶斯网络、马尔可夫网络以及决策图的构建,能做结构学习、参数学习、推理和可视化。并且语法偏工程化,比 pgmpy 直观一些,但要求所有变量都必须是离散型。

如果数据里有缺失值或连续变量需要进行处理,否则算法会直接报错。下面的例子展示了从数据清洗到结构学习的完整流程:

# 安装
pip install pyagrum
# 可选:安装可视化依赖
pip install setgraphviz
import datazets as dz
import pandas as pd
import pyagrum as gum
import pyagrum.lib.notebook as gnb
import pyagrum.lib.explain as explain
import pyagrum.lib.bn_vs_bn as bnvsbn
# 导入可视化设置
from setgraphviz import setgraphviz
setgraphviz()
# 导入数据并删除连续与敏感特征
df = dz.get(data='census_income')
drop_cols = ['age', 'fnlwgt', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week', 'race', 'sex']
df.drop(labels=drop_cols, axis=1, inplace=True)
# 清理缺失值
df2 = df.dropna().copy()
df2 = df2.fillna("missing").replace("?", "missing")
# 所有列转换为分类类型
for col in df2.columns:
df2[col] = df2[col].astype("category")
# 创建学习器
learner = gum.BNLearner(df2)
learner.useScoreBIC()
learner.useGreedyHillClimbing()
# 学习结构
bn = learner.learnBN()
# 学习参数
bn2 = learner.learnParameters(bn.dag())
# 可视化结果
gnb.showBN(bn2)



上图展示了 PyAgrum 学到的贝叶斯网络结构。节点之间的箭头表示潜在的因果方向。

它提供了一系列辅助模块,可以比较不同结构(bn_vs_bn)、解释单个节点(explain)或生成报告。

PyAgrum 的特点是:学习过程透明、支持约束学习(可指定禁止/强制边),但代价是输入准备相对繁琐。
没有自动缺失值处理、连续特征必须离散化,而且某些函数依赖 Graphviz 进行可视化。

6、CausalImpact

CausalImpact 原本是 Google 的开源项目,用于通过贝叶斯结构时间序列模型来衡量干预效果。 它与前面几个库不同,不学习因果图而是针对时间序列数据计算干预带来的量化影响。

常见场景是评估营销活动、价格调整或新功能上线的效果。比如,一个电商网站想知道广告活动是否带来了实际销售提升。CausalImpact 会先用干预前的数据建立基线模型,再将干预后的实际观测值与预测值比较,计算“反事实差异”。

下面是一个简洁的示例,构造 100 个样本点,并在第 71 个时间点之后人为引入干预效应:

# 安装
pip install causalimpact
# 导入库
import numpy as np
import pandas as pd
from statsmodels.tsa.arima_process import arma_generate_sample
import matplotlib.pyplot as plt
from causalimpact import CausalImpact
# 生成样本
x1 = arma_generate_sample(ar=[0.999], ma=[0.9], nsample=100) + 100
y = 1.2 * x1 + np.random.randn(100)
y[71:] = y[71:] + 10
data = pd.DataFrame(np.array([y, x1]).T, columns=["y","x1"])
# 初始化模型
impact = CausalImpact(data, pre_period=[0,69], post_period=[71,99])
# 执行推断
impact.run()
# 绘图与结果
impact.plot()
impact.summary()



图中上半部分显示实际值与模型预测值的对比;中间部分是两者的差值(即时效应);下半部分是累计效应。

结果显示,干预带来了显著提升,概率为 100%,P 值为 0。这种方法假设干预前后协变量与响应变量的关系稳定,且协变量本身不受干预影响。若满足这些假设,CausalImpact 在定量评估干预效应方面非常可靠。

总结

六个库的思路差异很大。从整体来看,可以分成两类:

结构学习型:Bnlearn、Pgmpy、CausalNex、PyAgrum 用于发现变量间的潜在因果关系,适合探索性分析与结构建模。

因果效应型:DoWhy、CausalImpact 侧重在给定结构或时间序列下量化干预效果,适合政策分析或实验验证。





从工程角度看:
Bnlearn 的易用性最高,接口友好、兼容性强,是入门和快速验证的好工具;
Pgmpy 灵活性最强,适合深度研究与自定义算法;
CausalNex 拥有良好的可解释图形界面,但依赖特定 Python 版本;
DoWhy 是学术研究常用工具,强调理论严谨性;
PyAgrum 稳定、透明,但数据准备较重;
CausalImpact 专注时间序列因果评估。

六个因果库覆盖了从结构学习到因果效应估计的完整路径。

Bnlearn、Pgmpy、CausalNex 和 PyAgrum 负责构建网络、识别驱动因素;

DoWhy 和 CausalImpact 则更像“量化工具”,用于评估处理或干预带来的实际影响。

https://avoid.overfit.cn/post/dc97c8f709bc4c56bfec860dd800d75c

作者:Erdogan T

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
出乎意料!继王曼昱后,陈梦也避开跟孙颖莎打比赛,放弃女单一号

出乎意料!继王曼昱后,陈梦也避开跟孙颖莎打比赛,放弃女单一号

侃球熊弟
2025-11-19 17:44:51
杭州官宣取消灵隐寺门票

杭州官宣取消灵隐寺门票

界面新闻
2025-11-19 10:37:00
美国制裁即将生效 俄罗斯原油价格暴跌至每桶40美元以下!

美国制裁即将生效 俄罗斯原油价格暴跌至每桶40美元以下!

财联社
2025-11-19 16:11:19
54.3万人取消赴日机票,俄罗斯泰国争抢中国客源

54.3万人取消赴日机票,俄罗斯泰国争抢中国客源

21世纪经济报道
2025-11-19 20:20:05
施一公:这是中国潜伏的最大危机!(发人深省)

施一公:这是中国潜伏的最大危机!(发人深省)

霹雳炮
2025-11-18 20:38:34
击败吴艳妮的 “黑马” 刘景扬是谁?

击败吴艳妮的 “黑马” 刘景扬是谁?

后体工队长
2025-11-19 23:09:38
黄晓明和杨颖的结婚照,当时真是挺大胆的

黄晓明和杨颖的结婚照,当时真是挺大胆的

可乐谈情感
2025-11-20 01:26:37
中日在联合国爆发激战,联合国通告全日本:台湾是中国的一个省

中日在联合国爆发激战,联合国通告全日本:台湾是中国的一个省

时时有聊
2025-11-19 07:35:18
可耻的是,捅郭伟马蜂窝的是个学生

可耻的是,捅郭伟马蜂窝的是个学生

关尔东
2025-11-19 17:13:25
为什么越南女子劫法场,却让全世界刮目相看?

为什么越南女子劫法场,却让全世界刮目相看?

历史总在押韵
2025-11-20 00:17:37
男女食堂里亲热:肮脏画面流出,全过程披露,女方一动作令人作呕

男女食堂里亲热:肮脏画面流出,全过程披露,女方一动作令人作呕

博士观察
2025-11-19 10:45:17
加入CPTPP:关乎未来的“高难度闯关”搏杀

加入CPTPP:关乎未来的“高难度闯关”搏杀

墨心人
2025-11-19 19:42:48
中方暂停进口日本水产品 外交部:即使日本水产品向中国出口也不会有市场

中方暂停进口日本水产品 外交部:即使日本水产品向中国出口也不会有市场

每日经济新闻
2025-11-19 17:41:46
日官员沉默离华,日媒称中方一个举动罕见,这次会谈信息有点多

日官员沉默离华,日媒称中方一个举动罕见,这次会谈信息有点多

之乎者也小鱼儿
2025-11-19 15:50:30
荷兰政府:已暂停对安世半导体的干预

荷兰政府:已暂停对安世半导体的干预

半导体产业纵横
2025-11-19 18:27:31
排面!40岁C罗造访白宫+微笑握手特朗普,美国总统宣布:他是GOAT

排面!40岁C罗造访白宫+微笑握手特朗普,美国总统宣布:他是GOAT

我爱英超
2025-11-19 07:10:18
中日关系高度紧张:大量中国游客赴日!网友:富士山下都是中国人

中日关系高度紧张:大量中国游客赴日!网友:富士山下都是中国人

大国纪录
2025-11-19 15:52:44
请做好充分准备,世界即将变天!

请做好充分准备,世界即将变天!

水木然
2025-11-17 23:56:09
韩媒警告:一旦东亚开战,韩国导弹将降落北京,同时摧毁中国海军

韩媒警告:一旦东亚开战,韩国导弹将降落北京,同时摧毁中国海军

优趣纪史记
2025-11-20 00:06:12
浙江16岁小将陈妤颉夺女子200米冠军,成为本届全运会双冠王

浙江16岁小将陈妤颉夺女子200米冠军,成为本届全运会双冠王

懂球帝
2025-11-19 20:44:03
2025-11-20 04:12:49
deephub incentive-icons
deephub
CV NLP和数据挖掘知识
1834文章数 1437关注度
往期回顾 全部

科技要闻

一夜封神,Gemini 3让谷歌找回“碾压感”

头条要闻

日方要求解释为何未告知磋商后会有媒体拍摄 中方回应

头条要闻

日方要求解释为何未告知磋商后会有媒体拍摄 中方回应

体育要闻

世界杯最小参赛国诞生!15万人岛国的奇迹

娱乐要闻

史林子出轨对方前妻放锤!

财经要闻

重磅!中金公司拟收购东兴与信达证券

汽车要闻

此刻价格不重要 第5代帝豪本身就是价值

态度原创

手机
教育
艺术
公开课
军事航空

手机要闻

OPPO Find X9系列海外卖爆!销量接近上代2倍

教育要闻

lsa伦敦占星学院是什么

艺术要闻

惊呆了!外国画家如何颠覆水浒108将的形象?

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

量大管饱 中国军网在海外发布备战视频

无障碍浏览 进入关怀版