Skip to content

2.4 平均处理效应(ATE/ATT/LATE)

"The central role of the randomized experiment in statistical inference is beyond dispute.""随机实验在统计推断中的核心地位是无可争议的。"— Guido Imbens, 2021 Nobel Laureate in Economics (2021年诺贝尔经济学奖得主)

理解不同因果效应的含义与估计


本节目标

  • 区分 ATE、ATT、ATU、LATE 等不同效应
  • 理解意向性分析(ITT)
  • 掌握处理效应异质性(CATE)
  • 学习不依从问题的处理方法

平均处理效应的类型

核心问题

为什么需要区分不同的平均效应?

因为在现实中:

  • 并非所有人都接受分配的处理(不依从,Non-compliance)
  • 处理效应可能因人而异(异质性,Heterogeneity)
  • 我们关心的总体可能不同(全样本 vs 处理组 vs 依从者)

1️⃣ ATE:平均处理效应

定义

Average Treatment Effect(ATE):全样本的平均因果效应

含义:如果随机抽取一个人接受处理,平均会有多大效应

案例:教育培训

python
# 假设有"上帝视角"数据
data = pd.DataFrame({
    'id': range(5),
    'Y0': [5000, 6000, 5500, 7000, 6500],  # 不培训的收入
    'Y1': [6500, 7200, 6800, 8000, 7800],  # 培训后的收入
})

data['tau'] = data['Y1'] - data['Y0']  # 个体因果效应

ATE = data['tau'].mean()
print(f"ATE = {ATE:.0f} 元")  # ATE = 1400 元

适用场景

  • 政策普遍推广:如果要在全国推广某政策,我们关心 ATE
  • 随机抽样实验:RCT 中随机分配,自然估计 ATE

2️⃣ ATT:处理组的平均效应

定义

Average Treatment Effect on the Treated(ATT):接受处理者的平均因果效应

含义:对于实际接受处理的人,平均效应是多少

与 ATE 的区别

继续上面的例子:

python
# 假设只有前 3 人接受了处理
data['D'] = [1, 1, 1, 0, 0]

# ATT:只计算处理组的平均效应
ATT = data[data['D'] == 1]['tau'].mean()
print(f"ATT = {ATT:.0f} 元")  # ATT = 1433 元

# ATE:全样本的平均效应
ATE = data['tau'].mean()
print(f"ATE = {ATE:.0f} 元")  # ATE = 1400 元

何时 ATT ≠ ATE?

条件:处理效应存在异质性

案例:职业培训

  • 主动参加培训的人可能更有动力
  • 他们的培训效应可能更大
  • 因此 ATT > ATE

适用场景

  • 项目评估:评估已经参与项目的人获得了多少收益
  • 志愿者项目:参与者自选择,我们关心他们的收益

3️⃣ ATU:未处理组的平均效应

定义

Average Treatment Effect on the Untreated(ATU):未接受处理者的平均反事实效应

含义:如果让没接受处理的人接受处理,平均效应是多少

案例

python
# ATU:只计算对照组的平均效应(反事实)
ATU = data[data['D'] == 0]['tau'].mean()
print(f"ATU = {ATU:.0f} 元")  # ATU = 1350 元

政策含义

  • 扩展项目:如果要扩大项目覆盖面,新参与者的效应可能是 ATU
  • 边际效应:项目从当前参与者扩展到非参与者,边际收益是 ATU

4️⃣ LATE:局部平均效应

问题:不依从(Non-compliance)

完美 RCT 的假设

  • 分配到处理组 → 100% 接受处理
  • 分配到对照组 → 0% 接受处理

现实

  • 单边不依从(One-sided non-compliance)
    • 分配到处理组,部分人不接受
    • 分配到对照组,无人接受
  • 双边不依从(Two-sided non-compliance)
    • 分配到处理组,部分人不接受
    • 分配到对照组,部分人自己获得处理

案例:药物临床试验

python
# RCT 数据
rct_data = pd.DataFrame({
    'id': range(10),
    'Z': [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],  # Z = 随机分配
    'D': [1, 1, 0, 1, 1, 0, 1, 0, 0, 0],  # D = 实际服药
    'Y': [120, 115, 95, 125, 118, 90, 105, 88, 92, 85]  # 血压
})

print(rct_data)

观察

  • ID 2:分配到处理组(Z=1),但未服药(D=0)→ 不依从者
  • ID 6:分配到对照组(Z=0),但服药了(D=1)→ 双边不依从

四种人群类型

根据潜在处理状态 ,人群可分为:

类型描述英文
依从者10分配到什么就接受什么Compliers
总是接受11无论如何都接受处理Always-takers
总不接受00无论如何都不接受Never-takers
反叛者01做与分配相反的事Defiers

假设单调性(Monotonicity)— 无反叛者

LATE 的定义

Local Average Treatment Effect(LATE):依从者的平均因果效应

含义:对于会响应随机分配的人,平均效应是多少

LATE 的估计:工具变量(IV)

关键洞察:随机分配 可以作为实际处理 的工具变量

IV 估计量

分子:意向性效应(ITT) 分母:依从率

python
# 计算 LATE
ITT_Y = (rct_data[rct_data['Z'] == 1]['Y'].mean() -
         rct_data[rct_data['Z'] == 0]['Y'].mean())

ITT_D = (rct_data[rct_data['Z'] == 1]['D'].mean() -
         rct_data[rct_data['Z'] == 0]['D'].mean())

LATE = ITT_Y / ITT_D

print(f"ITT (Y): {ITT_Y:.2f}")
print(f"ITT (D): {ITT_D:.2f}")
print(f"LATE: {LATE:.2f}")

Python 实现:2SLS(两阶段最小二乘)

python
import statsmodels.api as sm
from statsmodels.sandbox.regression.gmm import IV2SLS

# 第一阶段:D ~ Z
X1 = sm.add_constant(rct_data['Z'])
first_stage = sm.OLS(rct_data['D'], X1).fit()
print("第一阶段 F 统计量:", first_stage.fvalue)

# 第二阶段:Y ~ D_hat (using Z as instrument)
iv_model = IV2SLS(
    endog=rct_data['Y'],
    exog=sm.add_constant(np.ones(len(rct_data))),
    instrument=sm.add_constant(rct_data['Z'])
).fit()

print(iv_model.summary())

5️⃣ ITT:意向性分析

定义

Intention-to-Treat(ITT):按随机分配(而非实际处理)分组的效应

含义:被分配到处理组(无论是否实际接受)vs 对照组的平均差异

ITT 的重要性

优点说明
保留随机化分析单位是随机分配 ,无选择偏误
政策相关反映了"提供机会"的效应(而非"强制接受")
保守估计ITT < ATE(稀释偏误,Dilution bias)

ITT vs LATE

推导

案例:药物试验

python
# 依从率 = 80%
compliance_rate = 0.8

# 真实 LATE = 25 (对依从者的效应)
true_LATE = 25

# ITT = LATE × 依从率
ITT = true_LATE * compliance_rate
print(f"ITT: {ITT:.2f}")  # ITT = 20

# 解读:提供药物(无论是否服用)平均降低血压 20 点
# 但对实际服药的人,效应是 25 点

处理效应异质性(CATE)

定义

Conditional Average Treatment Effect(CATE):给定协变量 的条件平均效应

含义:不同子群的处理效应可能不同

案例:教育培训的异质性

python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 生成数据
np.random.seed(42)
n = 1000

data = pd.DataFrame({
    'baseline_skill': np.random.normal(50, 15, n),
    'treatment': np.random.binomial(1, 0.5, n)
})

# 异质性效应:基础好的人效应更大
data['tau'] = 5 + 0.3 * data['baseline_skill']  # 个体效应
data['Y0'] = 50 + 0.8 * data['baseline_skill'] + np.random.normal(0, 10, n)
data['Y1'] = data['Y0'] + data['tau']
data['Y_obs'] = np.where(data['treatment'] == 1, data['Y1'], data['Y0'])

# CATE 估计:分组回归
# 将基础技能分为三组
data['skill_group'] = pd.cut(data['baseline_skill'], bins=3,
                              labels=['低', '中', '高'])

cate_results = []
for group in ['低', '中', '高']:
    group_data = data[data['skill_group'] == group]
    ATE_group = (group_data[group_data['treatment'] == 1]['Y_obs'].mean() -
                 group_data[group_data['treatment'] == 0]['Y_obs'].mean())
    cate_results.append({'组别': group, 'CATE': ATE_group})

cate_df = pd.DataFrame(cate_results)
print(cate_df)

# 可视化
plt.figure(figsize=(8, 6))
plt.bar(cate_df['组别'], cate_df['CATE'], color=['#3498db', '#2ecc71', '#e74c3c'])
plt.xlabel('基础技能组别')
plt.ylabel('CATE(处理效应)')
plt.title('处理效应异质性:基础越好,培训效应越大')
plt.grid(axis='y', alpha=0.3)
plt.show()

机器学习估计 CATE

Causal Forest(因果森林):

python
# 使用 EconML 库(微软开发)
from econml.dml import CausalForestDML

# 训练因果森林
causal_forest = CausalForestDML(
    model_y=RandomForestRegressor(),
    model_t=RandomForestClassifier(),
    n_estimators=1000
)

X = data[['baseline_skill']]
causal_forest.fit(Y=data['Y_obs'], T=data['treatment'], X=X)

# 预测每个人的 CATE
data['cate_pred'] = causal_forest.effect(X)

# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(data['baseline_skill'], data['cate_pred'], alpha=0.3, s=10)
plt.xlabel('基础技能')
plt.ylabel('预测的 CATE')
plt.title('因果森林估计的个体处理效应')
plt.show()

不同效应的关系

数学关系

可视化

python
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(10, 6))

# 效应值
effects = {
    'ATE': 10,
    'ATT': 12,
    'ATU': 8,
    'LATE': 15,
    'ITT': 9
}

colors = ['#3498db', '#2ecc71', '#e74c3c', '#f39c12', '#9b59b6']
bars = ax.barh(list(effects.keys()), list(effects.values()), color=colors)

# 添加数值标签
for i, (k, v) in enumerate(effects.items()):
    ax.text(v + 0.5, i, f'{v}', va='center', fontweight='bold')

ax.set_xlabel('处理效应大小')
ax.set_title('不同平均效应的对比')
ax.set_xlim(0, 17)
ax.grid(axis='x', alpha=0.3)

# 添加注释
ax.annotate('LATE > ATT:依从者效应更大',
            xy=(15, 3), xytext=(13, 4.5),
            arrowprops=dict(arrowstyle='->', color='gray'))

ax.annotate('ITT < ATE:不依从导致稀释',
            xy=(9, 4), xytext=(11, 3.5),
            arrowprops=dict(arrowstyle='->', color='gray'))

plt.tight_layout()
plt.show()

Python 实战:完整案例

案例:在线课程 RCT(含不依从)

python
import pandas as pd
import numpy as np
from scipy import stats
import statsmodels.api as sm
from linearmodels.iv import IV2SLS

# ==== 1. 生成数据 ====
np.random.seed(42)
n = 1000

# 个体特征
data = pd.DataFrame({
    'id': range(n),
    'motivation': np.random.normal(50, 15, n),  # 学习动机
    'baseline_score': np.random.normal(60, 10, n)  # 基线成绩
})

# 随机分配(RCT)
data['Z'] = np.random.binomial(1, 0.5, n)

# 实际参与(不依从)
# 高动机的人更可能依从
prob_comply = 1 / (1 + np.exp(-(data['motivation'] - 50) / 10))
data['comply'] = np.random.binomial(1, prob_comply)

# 实际接受处理
data['D'] = data['Z'] * data['comply']

# 潜在结果
# 效应异质性:动机越高,效应越大
data['tau'] = 5 + 0.2 * data['motivation']
data['Y0'] = 60 + 0.3 * data['motivation'] + 0.5 * data['baseline_score']
data['Y1'] = data['Y0'] + data['tau'] + np.random.normal(0, 5, n)
data['Y_obs'] = np.where(data['D'] == 1, data['Y1'], data['Y0'])

# ==== 2. 估计不同效应 ====
print("=" * 60)
print("不同平均效应的估计")
print("=" * 60)

# (1) 真实 ATE(上帝视角)
true_ATE = data['tau'].mean()
print(f"\n真实 ATE: {true_ATE:.2f}")

# (2) 简单对比(有偏!因为有自选择进入处理)
naive = (data[data['D'] == 1]['Y_obs'].mean() -
         data[data['D'] == 0]['Y_obs'].mean())
print(f"简单对比: {naive:.2f} (有偏!)")

# (3) ITT:按随机分配比较
ITT_Y = (data[data['Z'] == 1]['Y_obs'].mean() -
         data[data['Z'] == 0]['Y_obs'].mean())
print(f"ITT: {ITT_Y:.2f}")

# (4) 依从率
compliance_rate = (data[data['Z'] == 1]['D'].mean() -
                   data[data['Z'] == 0]['D'].mean())
print(f"依从率: {compliance_rate:.2%}")

# (5) LATE(IV 估计)
LATE = ITT_Y / compliance_rate
print(f"LATE: {LATE:.2f}")

# ==== 3. 回归估计 ====
print("\n" + "=" * 60)
print("回归估计")
print("=" * 60)

# ITT 回归
X_itt = sm.add_constant(data['Z'])
itt_model = sm.OLS(data['Y_obs'], X_itt).fit(cov_type='HC3')
print("\nITT 回归:")
print(f"  系数: {itt_model.params['Z']:.2f}")
print(f"  SE: {itt_model.bse['Z']:.2f}")
print(f"  p-value: {itt_model.pvalues['Z']:.4f}")

# 2SLS(LATE)
iv_model = IV2SLS(
    dependent=data['Y_obs'],
    exog=sm.add_constant(np.ones(n)),
    endog=data[['D']],
    instruments=data[['Z']]
).fit(cov_type='robust')

print("\n2SLS (LATE):")
print(f"  系数: {iv_model.params['D']:.2f}")
print(f"  SE: {iv_model.std_errors['D']:.2f}")
print(f"  F-stat (第一阶段): {iv_model.f_statistic.stat:.2f}")

# ==== 4. CATE 估计 ====
print("\n" + "=" * 60)
print("异质性分析(CATE)")
print("=" * 60)

# 按动机分组
data['motivation_group'] = pd.qcut(data['motivation'], q=3,
                                    labels=['低动机', '中动机', '高动机'])

for group in ['低动机', '中动机', '高动机']:
    group_data = data[data['motivation_group'] == group]

    # ITT by group
    itt_group = (group_data[group_data['Z'] == 1]['Y_obs'].mean() -
                 group_data[group_data['Z'] == 0]['Y_obs'].mean())

    # 依从率 by group
    comp_group = (group_data[group_data['Z'] == 1]['D'].mean() -
                  group_data[group_data['Z'] == 0]['D'].mean())

    # LATE by group
    late_group = itt_group / comp_group if comp_group > 0 else np.nan

    print(f"\n{group}:")
    print(f"  ITT: {itt_group:.2f}")
    print(f"  依从率: {comp_group:.2%}")
    print(f"  LATE: {late_group:.2f}")

# ==== 5. 可视化 ====
fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 子图 1:不依从情况
comply_counts = data.groupby(['Z', 'D']).size().unstack(fill_value=0)
comply_counts.plot(kind='bar', ax=axes[0, 0], color=['skyblue', 'salmon'])
axes[0, 0].set_xlabel('随机分配(Z)')
axes[0, 0].set_ylabel('人数')
axes[0, 0].set_title('不依从情况')
axes[0, 0].legend(['未接受处理', '接受处理'])
axes[0, 0].set_xticklabels(['对照组', '处理组'], rotation=0)

# 子图 2:ITT vs LATE
effects = ['ITT', 'LATE', '真实ATE']
values = [ITT_Y, LATE, true_ATE]
axes[0, 1].bar(effects, values, color=['#3498db', '#e74c3c', '#2ecc71'])
axes[0, 1].set_ylabel('效应大小')
axes[0, 1].set_title('不同效应估计对比')
axes[0, 1].grid(axis='y', alpha=0.3)

# 子图 3:异质性(CATE)
cate_data = []
for group in ['低动机', '中动机', '高动机']:
    group_data = data[data['motivation_group'] == group]
    itt = (group_data[group_data['Z'] == 1]['Y_obs'].mean() -
           group_data[group_data['Z'] == 0]['Y_obs'].mean())
    cate_data.append(itt)

axes[1, 0].bar(['低动机', '中动机', '高动机'], cate_data,
               color=['#3498db', '#2ecc71', '#e74c3c'])
axes[1, 0].set_ylabel('ITT')
axes[1, 0].set_title('处理效应异质性')
axes[1, 0].grid(axis='y', alpha=0.3)

# 子图 4:散点图(动机 vs 效应)
treated = data[data['Z'] == 1]
control = data[data['Z'] == 0]
axes[1, 1].scatter(treated['motivation'], treated['Y_obs'],
                   alpha=0.3, s=10, label='处理组', color='salmon')
axes[1, 1].scatter(control['motivation'], control['Y_obs'],
                   alpha=0.3, s=10, label='对照组', color='skyblue')
axes[1, 1].set_xlabel('学习动机')
axes[1, 1].set_ylabel('最终成绩')
axes[1, 1].set_title('动机 vs 成绩(按分配组)')
axes[1, 1].legend()

plt.tight_layout()
plt.savefig('ate_analysis.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n 分析完成!")

小结

核心概念对比

效应定义估计量适用场景
ATE全样本平均效应简单差分(RCT)政策普遍推广
ATT处理组平均效应匹配、DID项目评估
ATU对照组平均效应匹配项目扩展
LATE依从者平均效应IV/2SLS有不依从的 RCT
ITT意向性效应按分配分组政策效应(保守)
CATE条件平均效应分组/机器学习异质性分析

关键洞察

  1. 不依从问题

    • ITT 保留随机化,但低估真实效应
    • LATE 通过 IV 估计依从者效应
    • 依从率 = ITT / LATE
  2. 异质性分析

    • CATE 揭示不同子群的差异效应
    • 有助于精准施策、优化资源配置
  3. 效应选择

    • 政策制定者关心 ITT(提供机会的效应)
    • 研究者关心 LATE(真实机制)
    • 实践者关心 CATE(个性化干预)

思考题

  1. 理解题:为什么说 ITT 是"保守估计"?在什么情况下 ITT 可能更有政策意义?

  2. 计算题:某教育 RCT 发现:

    • ITT = 0.2 个标准差
    • 依从率 = 60%

    问:LATE 是多少?如果强制所有人参与(100% 依从),预期效应是多少?

  3. 设计题:你在研究"健身 APP 对减重的因果效应"。

    • (a) 定义 ATE、ATT、LATE
    • (b) 如何估计 CATE(年龄、性别、基线 BMI)
    • (c) 预期哪个效应最大?为什么?
点击查看答案提示

问题 1

  • ITT "保守"是因为包含了不依从者(稀释效应)
  • 政策意义:反映"提供项目机会"的实际效应(不能强迫所有人参与)

问题 2

  • LATE = ITT / 依从率 = 0.2 / 0.6 = 0.33 标准差
  • 100% 依从的预期效应 ≈ LATE = 0.33(假设 LATE = ATE)

问题 3

  • (c) 预期 ATT > ATE > ATU(自选择效应:主动使用 APP 的人效果更好)

下一步

下一节我们将学习 识别策略与有效性,深入理解因果推断的核心假设(SUTVA、独立性等)。

继续!


参考文献

  • Angrist, J. D., Imbens, G. W., & Rubin, D. B. (1996). "Identification of causal effects using instrumental variables". JASA.
  • Imbens, G. W., & Angrist, J. D. (1994). "Identification and estimation of local average treatment effects". Econometrica.
  • Athey, S., & Imbens, G. (2016). "Recursive partitioning for heterogeneous causal effects". PNAS.

基于 MIT 许可证发布。内容版权归作者所有。