DoWhy | An end-to-end library for causal inference
Getting started with DoWhy: A simple example
使用因果推理的四个步骤来动手估计因果效应:建模model
、识别identify
、估计 estimate
和反驳 refute
。
因果关系定义
假设我们想要找到采取行动A对结果y的因果影响,要定义因果影响,考虑两个世界:
- 世界1(真实世界): 行动A被采取,观察到Y
- 世界2(反事实世界): 没有采取行动A,但其他一切都相同
因果效应是在现实世界与反事实世界中Y 值之间的差异。换句话说,其他一切都保持不变,当 A 改变导致 Y 改变时,A 是Y的原因. 在保持其他一切不变的情况下更改 A 称为干预,并由符号 d o ( A ) do(A) do(A) 表示.
形式上,将因果效应定义为结果(Y
) 因 原因(A
) 的单位干预变化而变化的幅度:
E
[
Y
∣
d
o
(
A
=
1
)
]
−
E
[
Y
∣
d
o
(
A
=
0
)
]
E[Y|do(A=1)] - E[Y|do(A=0)]
E[Y∣do(A=1)]−E[Y∣do(A=0)]
为了估计效果,黄金标准是进行一个随机实验,其中一半做动作(A=1)而另一半不做动作(A=0)。 这些子集近似于模拟真实世界和反事实世界,随机化两个子集之间没有系统差异(“保持其他一切不变”,即除了A没有其他不同)。然而,进行随机实验并不总是可行的。 为了回答因果问题,我们通常需要依靠观察或记录的数据。 观察到的数据因相关性和未观察到的混杂而存在偏差,因此容易存在系统差异。 例如,新的营销活动可能会在假日季节部署,新功能可能仅适用于高活动用户,或者年龄较大的患者可能更有可能接受新药,等等。 因果推理方法的目标是从数据中消除这些相关性和混淆,并估计一个动作的真实效果,如上面的等式所示。
因果推理的两个基本挑战:
我们观察不到反事实世界:- 无法直接计算因果关系
- 必须估计反事实
- 验证中的挑战
单个数据分布 可能有多个因果机制
- 仅数据不足以进行因果推理
- 需要领域知识和假设
因果推理的四个步骤
0 导入包& 数据集
下载两个库:DoWhy 和 EconML。 两者都可以通过以下命令安装:
pip install dowhy econml
导入包
# Required libraries
import dowhy
from dowhy import CausalModel
import dowhy.datasets
# Avoiding unnecessary log messges and warnings
import logging
logging.getLogger("dowhy").setLevel(logging.WARNING)
import warnings
from sklearn.exceptions import DataConversionWarning
warnings.filterwarnings(action='ignore', category=DataConversionWarning)
加载数据
# Load some sample data
data = dowhy.datasets.linear_dataset(
beta=10,
num_common_causes=5,
num_instruments=2,
num_samples=10000,
treatment_is_binary=True,
stddev_treatment_noise=10)
会提示 stddev_treatment_noise=10
有错,删去
# Load some sample data
data = dowhy.datasets.linear_dataset(
beta=10,
num_common_causes=5,
num_instruments=2,
num_samples=10000,
treatment_is_binary=True)
treatment_name
指定行动编号outcome_name
指定结果编号common_causes_names
对行动和结果同时有直接影响的编号instrument_names
只对行动有直接影响的编号gml_grapg
定义了边和点
1. Modeling
将数据集中的数据转换成图,涉及指定两种类型的变量:
混杂因素(common_causes
):会同时对行动和结果产生影响的变量。
因此,任何观察到的行动与结果之间的相关性都可能仅仅是由于混杂变量,而不是由于行动与结果之间的任何因果关系。
工具变量(instruments
):这些是不直接影响结果,但是会对行动产生影响的特殊变量。
它们不受任何影响结果的变量的影响。 如果以正确的方式使用,工具变量可以帮助减少偏差。
从数据和领域知识中建图
model = CausalModel(
data=data["df"],
treatment=data["treatment_name"],
outcome=data["outcome_name"],
common_causes=data["common_causes_names"],
instruments=data["instrument_names"])
可视化
model.view_model(layout="dot")
from IPython.display import Image, display
display(Image(filename="causal_model.png"))
2.Identification
在给定因果图和目标量(如a对B的影响)的情况下,识别的过程是检查目标量是否可以根据观察变量估计出来。重要的是,标识只考虑被观测数据中可用变量的名称;它不需要访问数据本身。针对上述两类变量,因果推理主要有两种识别方法。
- 后门准则
如果观察到动作 A 和结果 Y 的所有常见原因,则后门标准意味着可以通过改变常见原因来识别因果关系。 这是一个简化的定义(有关正式定义,请参阅 CausalML 书的第 3 章)。
E [ Y ∣ d o ( A = a ) ] = E W E [ Y ∣ A = a , W = w ] E[Y|do(A=a)] = E_WE[Y|A=a,W=w] E[Y∣do(A=a)]=EWE[Y∣A=a,W=w]
W W W指 A A A和 Y Y Y的共同原因(混杂)的集合 - 工具变量 (IV) 识别
如果有可用的工具变量,那么即使没有观察到任何(或没有)行动和结果的共同原因,我们也可以估计效果。 下面代码识别利用了工具仅直接影响动作的事实,因此工具对结果的影响可以分解为两个连续的部分:工具对动作的影响&动作对结果的影响。
然后,它依靠估计工具对行动和结果的影响来估计行动对结果的影响。 对于二元结果,效果估计由下式给出,
E [ Y ∣ d o ( A = 1 ) ] − E [ Y ∣ d o ( A = 0 ) ] = E [ Y ∣ Z = 1 ] − E [ Y ∣ Z = 0 ] E [ A ∣ Z = 1 ] − E [ A ∣ Z = 0 ] E[Y \mid d o(A=1)]-E[Y \mid d o(A=0)]=\frac{E[Y \mid Z=1]-E[Y \mid Z=0]}{E[A \mid Z=1]-E[A \mid Z=0]} E[Y∣do(A=1)]−E[Y∣do(A=0)]=E[A∣Z=1]−E[A∣Z=0]E[Y∣Z=1]−E[Y∣Z=0]
识别因果效应并返回目标估计值
identified_estimand = model.identify_effect(proceed_when_unidentifiable=True)
print(identified_estimand)
3.Estimation
顾名思义,估计步骤涉及构建一个统计估计器,该估计器可以计算上一步中确定的目标估计值。 已经提出了许多用于因果推断的估计量。 DoWhy 实现了一些标准估计器,而 EconML 实现了一组使用机器学习的强大估计器。
分别使用 DoWhy 使用倾向得分分层的示例&使用 EconML 的基于机器学习的方法,称为 Double-ML
- 使用 DoWhy 使用倾向得分分层的示例,统计学方法
propensity_strat_estimate = model.estimate_effect(identified_estimand,
method_name="backdoor.dowhy.propensity_score_stratification")
print(propensity_strat_estimate)
- 使用 EconML 的基于机器学习的方法,称为 Double-ML
import econml
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LassoCV
from sklearn.ensemble import GradientBoostingRegressor
dml_estimate = model.estimate_effect(identified_estimand,
method_name="backdoor.econml.dml.DML",
method_params={
'init_params': {'model_y':GradientBoostingRegressor(),
'model_t': GradientBoostingRegressor(),
'model_final':LassoCV(fit_intercept=False), },
'fit_params': {}
})
print(dml_estimate)
4.Refutation
最后,检查估计的稳健性可能是因果分析中最重要的一步。
我们使用步骤 1-3 获得了一个估计值,但每个步骤都可能做出了某些可能不正确的假设。
在没有适当的验证数据——“测试”集的情况下,此步骤依赖于反驳测试,该测试旨在使用良好估计器的属性来反驳所获得估计的正确性。
例如,反驳测试 (placebo_treatment_refuter) 检查当动作变量被随机变量替换时,估计器是否返回估计值 0,与所有其他变量无关。
refute_results = model.refute_estimate(identified_estimand, propensity_strat_estimate,
method_name="placebo_treatment_refuter")
print(refute_results)