首页
学习
活动
专区
圈层
工具
发布

让我康康是谁还不会DML?

从观察数据(非AB实验数据)尝试获得因果效应的方法,我们之前学习了一种方法PSM。大致思想是从观察数据里找到各方面比较相似的两批人,观察他们在接受/不接受某种影响的结果差异,近似认为差异就是这种影响带来的。如从高中生中找到上大学/不上大学的人,进一步找到家庭、智商、性别等比较相似的两批人,对比工作后的收入差异,可以近似认为这个差异就是上大学的因果效应。

除非你有奇异博士的能力,可以浏览不同平行时空的结果

但如果我们的干预变量是连续变量呢?如想衡量健身时长对寿命的影响,如果我们需要控制的混淆变量非常多呢?如混淆变量超过50个,倾向得分模型准确性会下降,匹配质量也会下降。这个时候本次的主角DML就出来救场了!

1.DML基本思想和原理

基本原理

DML全称为Double Machine Learning,中文名为双重机器学习。不管用什么方法评估因果效应遇到的最大难题其实都是一致的:即如何尽可能地降低或消除混淆变量对因果效应估计的影响。

混淆变量的含义其实很简单,就是会同时影响干预变量和结果变量。举个例子,夏天天气热->可口可乐销量上升,夏天天气热->溺水事故数上升,如果我们去考察可口可乐销量对溺水事故数的因果效应时,如果不控制天气这个因素,则会错误地得到1个荒谬的结论:可口可乐销量上升->溺水事故数上升。但其实基于我们的生活常识,这两者完全没有因果效应。这个过程中捣蛋的就是混淆变量。这个例子里我们尚可以基于已有的常识判断结果不对,而在更多的因果效应推断中都是未知的影响链路,因此控制混淆变量对于正确地估计因果效应更为重要。

可口可乐躺枪

AB实验简单粗暴且有效地通过随机化干预消除了混淆变量;PSM是通过匹配相似的个体达到降低混淆变量对因果效应估计的影响;DML则是把混淆变量放入方程中。基于某个数学定理(Frisch-Waugh-Lovell(FWL)定理)通过残差正交化消除混淆变量对因果效应估计的影响。

方法步骤

简单来说就是,分别对结果变量和干预变量做2次拟合,对2次拟合得到的残差再做1次拟合就可以得到因果效应。

1.基于机器学习模型使用

拟合

,得到

,计算可得残差

2.基于机器学习模型使用

拟合

,得到

,计算可得残差

3.用机器学习模型拟合

,得到参数

,即认为是T和Y之间的真正因果效应值。

2.DML实现

2.1自定义实现

0.生成数据

from causalml.dataset import synthetic_data

# 使用synthetic_data生成数据

  y, X, treat, _, _, _ = synthetic_data(mode=1, n=10000, p=8, sigma=1.0)

model参数控制数据生成的结构类型,不同模式对应不同的因果效应(CATE)与特征关系:

mode=1:线性关系,处理效应(Treatment Effect)恒定

mode=2:非线性关系,处理效应随特征变化

mode=3:包含交互项的非线性关系

mode=4:异质性处理效应(HTE),效应大小依赖特征

mode=5:复杂非线性关系,含高阶项和交互作用

2.n(样本数量)

3.p(特征维度),每个样本的特征数量(即特征向量的维度)

4.sigma(噪声标准差),添加到结果变量 y的高斯噪声的标准差,控制数据噪声水平,值越大,数据噪声越强,模型拟合难度越高

1.计算y的残差

from sklearn.ensemble import RandomForestRegressor

# 计算y的残差

rf_y = RandomForestRegressor()

rf_y.fit(X, y)

y_res = y - rf_y.predict(X)

2.计算t的残差

# 计算treat的残差

rf_t = RandomForestRegressor()

rf_t.fit(X, treat)

treat_res = treat - rf_t.predict(X)

3.拟合2个残差计算因果效应

最终得到ATE=0.4565,AUUC=0.5852。

from causalml.metrics import auuc_score, plot_gain

from sklearn.linear_model import LinearRegression

# 计算因果效果

lr = LinearRegression(fit_intercept=False).fit(treat_res.reshape(-1, 1), y_res.reshape(-1, 1))

theta = lr.coef_[0, 0]  # 回归系数θ

# 计算ITE:θ * 个体处理残差

ite_estimates = theta * treat_res

# 使用dataframe组织计算AUUC的必要数据

df = pd.DataFrame({

  'y': y,

  'treat': treat,

  'self_lr_dml': ite_estimates

})

# 计算AUUC值

auuc = auuc_score(df, outcome_col='y', treatment_col='treat', normalize=True, tmle=False)

print(auuc)

# 绘制gain曲线

plot_gain(df, outcome_col='y', treatment_col='treat', normalize=True, random_seed=10, n=100, figsize=(8, 8))

auuc= 0.585222.2 调包实现半自动

实现上调用econml.dml.DML,但在计算计算残差和残差拟合时可以自定义机器学习模型。

LR是在最终2个残差回归阶段使用线性回归模型,得到的ATE=0.4817,AUUC=0.4864

RF是在最终2个残差回归阶段使用随机森林模型,得到的ATE=0.4457,AUUC=0.5281

# dml + 线性

lr_dml = DML(model_y=RandomForestRegressor(),

  model_t=RandomForestRegressor(),

  model_final=LinearRegression(fit_intercept=False))

lr_dml.fit(y, treat, X=X)

print('lr_dml: {}'.format(lr_dml.ate(X)))

# dml + 非线性

rf_dml = DML(model_y=RandomForestRegressor(),

  model_t=RandomForestRegressor(),

  model_final=RandomForestRegressor())

rf_dml.fit(y, treat, X=X)

print('rf_dml: {}'.format(rf_dml.ate(X)))

lr_dml,auuc=0.486423

rf_dml,auuc=0.528143全自动

直接使用因果森林DML,最终CF得到的ATE=0.4679,AUUC=0.7144

# 因果森林DML

cf_dml = CausalForestDML()

cf_dml.fit(y, treat, X=X)

print('CausalForestDML: {}'.format(cf_dml.ate(X)))

cf_dml,auuc=0.714414

下课!点赞!

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OxudOkmjg4EUhiEgbpYHgFGw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。
领券