【python因果库实战20】causallib 评估图表概述3
这里写目录标题
- 共同支持
- 结果模型图表 (二分类)
- ROC、PR 和校准图
- 非倾向权重模型图表
- 协变量平衡
- 权重分布
共同支持
理想情况下,我们希望绘制潜在结果 Y 0 Y^0 Y0、 Y 1 Y^1 Y1 来检查交换性假设 Y 0 Y^0 Y0, Y 1 ⊥ A Y^1 \perp A Y1⊥A 是否成立。不幸的是,我们无法获取真实的潜在结果,所以我们最好的模仿方法就是使用反事实预测。我们通过绘制散点图(每个点是一个单位)并着色为观察到的处理分配,来视觉上检验 Y ^ 0 \hat{Y}^0 Y^0, Y ^ 1 ⊥ A \hat{Y}^1 \perp A Y^1⊥A。如果两者不重叠,可能意味着我们的模型在处理组之间的一致性存在问题,因此我们需要更加谨慎地解读因果结果。
fig, [a0, a1] = plt.subplots(1, 2, figsize=(12, 6))
cont_std_results.plot_common_support(phase="train", ax=a0)
cont_std_results.plot_common_support(phase="valid", ax=a1)
for ax, suffix in [(a0, "Train"), (a1 ,"Validation")]:
ax.set_title(ax.get_title() + ": " + suffix)
_ = plt.tight_layout()
结果模型图表 (二分类)
# We generate some simple binary outcomes based on the original data
y = 1 / (1 + np.exp(-data.y))
y = np.random.binomial(1, y)
y = pd.Series(y, index=data.a.index)
bin_std = StratifiedStandardization(LogisticRegression(max_iter=2000))
bin_std.fit(data.X, data.a, y)
bin_std_results = evaluate(bin_std, data.X, data.a, y, cv="auto")
bin_std_results.all_plot_names
frozenset({'calibration', 'pr_curve', 'roc_curve'})
ROC、PR 和校准图
用于评估二分类结果模型预测的质量。这些图表与倾向得分模型的图表相同,因为处理分配本质上可以视为一个二分类预测问题。然而,它们的解释有所不同且更直观——我们可以像解释常规分类任务那样来解释这些图表。
分类结果按处理组划分,以帮助识别是否对两个组进行了相似建模。建模完整的响应面是一项艰巨的任务,并且很可能在一个组上出现模型设定不当的情况。
f, axes = plt.subplots(3, 2, figsize=(10, 12))
row1, row2, row3 = axes
bin_std_results.plot_pr_curve(phase="train", ax=row1[0])
bin_std_results.plot_pr_curve(phase="valid", ax=row1[1])
bin_std_results.plot_roc_curve(phase="train", ax=row2[0])
bin_std_results.plot_roc_curve(phase="valid", ax=row2[1])
bin_std_results.plot_calibration_curve(phase="train", ax=row3[0])
bin_std_results.plot_calibration_curve(phase="valid", ax=row3[1])
plt.tight_layout()
# to add the train validation annotation to the titles:
for row in axes:
for idx, suffix in [(0, "Train"), (1 ,"Validation")]:
row[idx].set_title(row[idx].get_title() + ": " + suffix)
非倾向权重模型图表
有些权重模型并非基于逆倾向加权 (IPW),例如 AdversarialBalancing 模型。对于这种模型,评估处理分配二分类预测质量的图表并不适用,但权重图表仍然相关。在这个演示中,我们将 AdversarialBalancing 模型的图表与 IPW 模型的图表进行比较。
from causallib.contrib.adversarial_balancing import AdversarialBalancing
ipw_model = IPW(LogisticRegression(solver="liblinear"))
ipw_model.fit(data.X, data.a, data.y)
ipw_evaluate = evaluate(ipw_model, data.X, data.a, data.y, cv="auto")
ab_model = AdversarialBalancing(LogisticRegression(solver="liblinear"))
ab_model.fit(data.X, data.a, data.y)
ab_evaluate = evaluate(ab_model, data.X, data.a, data.y, cv="auto", metrics_to_evaluate={})
ab_evaluate.all_plot_names
frozenset({'covariate_balance_love',
'covariate_balance_slope',
'weight_distribution'})
协变量平衡
我们可以看到 AdversarialBalancing 模型成功地在训练阶段将协变量不平衡降低至 0,但在验证阶段不一定能保持同样的效果。
f, [row1, row2] = plt.subplots(2, 2, figsize=(12,12))
thresh=0.1
ab_evaluate.plot_covariate_balance(phase="train", thresh=thresh, ax=row1[0])
row1[0].set_title("AdversarialBalancing: train")
ab_evaluate.plot_covariate_balance(phase="valid", thresh=thresh, ax=row1[1])
row1[1].set_title("AdversarialBalancing: valid")
ipw_evaluate.plot_covariate_balance(phase="train", thresh=thresh, ax=row2[0])
row2[0].set_title("IPW: train")
ipw_evaluate.plot_covariate_balance(phase="valid", thresh=thresh, ax=row2[1])
row2[1].set_title("IPW: valid");
plt.tight_layout()
进一步分析表明,在训练和验证阶段,IPW 模型的不平衡特征数量几乎总是少于 AdversarialBalancing 模型,尽管这两种模型在验证阶段的表现非常接近。尝试不同的学习器可能会产生不同的结果。
def unbalanced_feature_count(covbalance, thresh=0.1, phase="valid"):
return sum(covbalance.loc[phase].groupby(level=1).mean()["weighted"] > thresh)
thresh_range = np.linspace(0, 0.2)
plt.plot(thresh_range, [unbalanced_feature_count(ipw_evaluate.evaluated_metrics.covariate_balance, t) for t in thresh_range], label="IPW (valid)", color="C1")
plt.plot(thresh_range, [unbalanced_feature_count(ab_evaluate.evaluated_metrics.covariate_balance, t) for t in thresh_range], label="AdversarialBalancing (valid)", color="C2")
plt.plot(thresh_range, [unbalanced_feature_count(ipw_evaluate.evaluated_metrics.covariate_balance, t, "train") for t in thresh_range], label="IPW (train)", color="C1", ls="--")
plt.plot(thresh_range, [unbalanced_feature_count(ab_evaluate.evaluated_metrics.covariate_balance, t, "train") for t in thresh_range], label="AdversarialBalancing (train)", color="C2", ls="--")
plt.ylabel("number of unbalanced features (validation)")
plt.xlabel("threshold")
plt.legend()
_ = plt.tight_layout()
权重分布
对于非倾向权重,绘制权重略显复杂,但我们仍可寻找处理组之间的重叠。
f, [row1, row2] = plt.subplots(2, 2, figsize=(12,12))
ab_evaluate.plot_weight_distribution(phase="train", ax=row1[0])
row1[0].set_title("AdversarialBalancing: train")
ab_evaluate.plot_weight_distribution(phase="valid", ax=row1[1])
row1[1].set_title("AdversarialBalancing: valid")
ipw_evaluate.plot_weight_distribution(phase="train", ax=row2[0])
row2[0].set_title("IPW: train")
ipw_evaluate.plot_weight_distribution(phase="valid", ax=row2[1])
row2[1].set_title("IPW: valid")
_ = plt.tight_layout()