目录
Treatment Is Easy to Model
Treatment Is Easy to Model
第一个例子中,治疗分配的模型相当容易建立,但干预结果的模型却比较复杂。具体来说,干预遵循伯努利分布,其概率由以下倾向得分给出:
如果您没有意识到,这正是逻辑回归所采用的形式,因此应该很容易对其进行估计。此外,由于 很容易建模,IPW 分数在这里找到真正的 ATE 应该没有问题,因为它接近 2。相比之下,由于结果 Y 比较棘手,回归模型可能会遇到一些麻烦:
np.random.seed(123)n = 10000x = np.random.beta(1,1, n).round(2)*2e = 1/(1+np.exp(-(1+1.5*x)))t = np.random.binomial(1, e)y1 = 1y0 = 1 - 1*x**3y = t*(y1) + (1-t)*y0 + np.random.normal(0, 1, n)df_easy_t = pd.DataFrame(dict(y=y, x=x, t=t))print("True ATE:", np.mean(y1-y0))True ATE: 2.0056243152
下面两幅图显示了这些数据的情况。值得注意的是数据中的效应异质性,这在第二幅图中很容易看到。请注意,当 x 值较低时,效应为 0,而随着 x 值的增加,效应呈非线性增加。这种异质性往往是回归很难做到的:
现在,让我们看看回归在这个数据中的作用。在这里,我再次分别拟合m1和m0,并将ATE估计为整个数据集中不同预测的平均值,
m0 = smf.ols("y~x", data=df_easy_t.query("t==0")).fit()m1 = smf.ols("y~x", data=df_easy_t.query("t==1")).fit()regr_ate = (m1.predict(df_easy_t) - m0.predict(df_easy_t)).mean()print("Regression ATE:", regr_ate)Regression ATE: 1.786678396833022
如果将预测值与原始数据进行对比,您就会发现原因所在。回归模型未能捕捉到对照组的曲率:
说白了,这并不意味着无法用回归法正确估计 ATE。如果您知道数据的真实曲率,您几乎可以建立正确的模型:
m = smf.ols("y~t*(x + np.power(x, 3))", data=df_easy_t).fit()regr_ate = (m.predict(df_easy_t.assign(t=1))- m.predict(df_easy_t.assign(t=0))).mean()print("Regression ATE:", regr_ate)Regression ATE: 1.9970999747190072
当然,在现实中,你并不知道数据是如何产生的。因此,回归结果很可能会让你失望。相比之下,让我们看看 IPW 的表现如何。同样,由于建立干预分配模型相当容易,你应该会期望 IPW 在此数据上表现相当出色:
est_fn = partial(est_ate_with_ps, ps_formula="x", T="t", Y="y")print("Propensity Score ATE:", est_fn(df_easy_t))print("95% CI", bootstrap(df_easy_t, est_fn))Propensity Score ATE: 2.00235038847401195% CI [1.80802227 2.22565667]
最后,就是您期待已久的时刻,让我们来看看 DR 估计的实际效果。请记住,DR 要求 P T X 或 E YtX 模型中的一个正确,但不一定两个都正确。在这个数据中,P T X 的模型是正确的,但 E Yt X 的模型是错误的:
est_fn = partial(doubly_robust, formula="x", T="t", Y="y")print("DR ATE:", est_fn(df_easy_t))print("95% CI", bootstrap(df_easy_t, est_fn))DR ATE: 2.00161793426311695% CI [1.87088771 2.145382]
不出所料,DR 在这里的表现相当出色,也恢复了真正的 ATE。但还不止这些。请注意,95% CI 比纯 IPW 估计值要小,这意味着 DR 估计值更精确。这个简单的例子说明,当 很容易建模时,即使 DR 估算出的 是错误的,它也能表现出色。但反过来呢?