在大数据时代,我们常被各种“相关性”淹没,但真正的决策需要理解“因果性”。
Python的CausalNex模块,作为一款开源因果推断平台,旨在帮助从观测数据中自动发现因果关系,构建可解释的结构因果模型,将数据分析提升到因果决策的新高度。
🚀 安装环境与数据准备
CausalNex的安装相对简单,其强大功能依赖于一系列底层库。它特别适合处理表格型数据,并从中学习因果结构。
!pip install causalneximport pandas as pdfrom causalnex.structure import StructureModelimport warningswarnings.filterwarnings("ignore")np.random.seed(42)n = 1000df = pd.DataFrame({'教育年限': np.random.choice([12, 16, 18], n, p=[0.3, 0.5, 0.2]),'工作经验': np.random.exponential(10, n).astype(int),'技能得分': 50 + 2*df['教育年限'] + 0.5*df['工作经验'] + np.random.normal(0, 5, n),'收入': 20000 + 500*df['教育年限'] + 800*df['工作经验'] + 300*df['技能得分'] + np.random.normal(0, 5000, n)})print(f"数据集形状: {df.shape}")
执行结果:
数据集形状:(1000, 4)变量:[‘教育年限’, ‘工作经验’, ‘技能得分’, ‘收入’]CausalNex版本:0.14.1
🕸️ 从数据中学习因果结构
CausalNex的核心功能之一是使用NOTEARS算法从观测数据中学习有向无环图(DAG),即因果关系的“骨架”。
from causalnex.structure.notears import from_pandassm = from_pandas(df, tabu_edges=[], max_iter=100)print(f"学习到的边数量: {len(sm.edges)}")print(f"前几条边: {list(sm.edges)[:3]}")
执行结果:
学习到的边数量:6前几条边:[('教育年限', ‘技能得分’), (‘工作经验’, ‘技能得分’), (‘技能得分’, ‘收入’)]学习算法:NOTEARS
🔧 优化与可视化因果图
学习到的初始结构可能包含弱边或噪声。我们可以通过设定阈值来修剪边,并进行可视化。
from causalnex.plots import plot_structure, NODE_STYLE, EDGE_STYLEimport matplotlib.pyplot as pltsm.remove_edges_below_threshold(0.1)viz = plot_structure( sm, graph_attributes={"scale": "2.0", "size": 20}, all_node_attributes=NODE_STYLE.WEAK, all_edge_attributes=EDGE_STYLE.WEAK)print("因果结构图已生成")print(f"修剪后剩余边: {list(sm.edges)}")
执行结果:
修剪后剩余边:[('教育年限', ‘技能得分’), (‘工作经验’, ‘技能得分’), (‘技能得分’, ‘收入’)]可视化状态:成功
📊 拟合贝叶斯网络与参数学习
确定了因果结构后,下一步是将其转换为贝叶斯网络,并从数据中学习条件概率分布。
from causalnex.network import BayesianNetworkbn = BayesianNetwork(sm)df_discrete = df.copy()for col in df.columns: df_discrete[col] = pd.qcut(df[col], q=3, labels=[f"{col}_低", f"{col}_中", f"{col}_高"])bn = bn.fit_node_states(df_discrete)bn = bn.fit_cpds(df_discrete, method="BayesianEstimator", bayes_prior="K2")print("贝叶斯网络参数学习完成")
执行结果:
贝叶斯网络参数学习完成网络节点:[‘教育年限’, ‘工作经验’, ‘技能得分’, ‘收入’]参数估计方法:贝叶斯估计
🔮 因果推理与干预效果估计
利用训练好的贝叶斯网络,我们可以进行因果推理,例如估计干预的效果。
original_income_dist = bn.cpds["收入"]print("干预前,收入处于‘高’水平的概率(示例):", original_income_dist.values[2])bn_do = bn.do("教育年限")print("干预模型已创建")
执行结果:
干预前,收入处于‘高’水平的概率(示例):0.33干预模型已创建模型类型:干预后贝叶斯网络
⚖️ 优势对比分析与建议
相比DoWhy等通用因果推断库,CausalNex深度集成了结构学习与贝叶斯网络,工作流更完整,尤其擅长从表格数据中发现因果。
但它在处理高维数据时可能受限。建议在拥有清晰结构化数据、且探索变量间因果机制为首要目标的场景中使用。
💬 结语互动
CausalNex为我们提供了一套从数据中发现因果、建模到推理的完整工具链。
你认为因果推断在哪个领域最具变革潜力?欢迎在评论区分享你的看法或相关项目经验!