【因果推論】ATEからCATEへ ~教育訓練RCTデータをCausal Forestを用いてPythonで効果検証~

2024/10/25に公開

はじめに

ある施策の効果を検証するためにA/Bテストが行われています。また経済学の文脈でも、ランダム化比較実験を行って政府の施策(教育、労働訓練など)の効果を検証する論文がトップジャーナルに多く掲載されています。
こうした効果検証において、ビジネスで往々にして議題に挙がるのは、平均処置効果ではなく条件付き平均処置効果(CATE)、すなわち 「属性ごとの施策効果の異質性」 ではないでしょうか。実験の結果を次のアクションに落としこむ際に、より収益性の高いユーザーに施策を絞ろうとするのはとても自然だと思います。
本記事では、条件付き平均処置効果を推定するためのフレームワークの一つであるCausal ForestをPythonで実装することを目的とします。現時点でもPythonでCausal Forestを推定する記事は散見されますが、これらのデータの多くは実験データではなく観察データで、RCTが行われていないものとなっています。そこで今回はLalonde(1986)で使用されている職業訓練に関するRCTデータを使用し、年齢や人種といった共変量で条件付けした平均処置効果を取得することを目指します。
なお、今回は一連の推定をPythonで実行することを目的とするため、Causal Forestに関する理論的な説明や精度に関する議論等には踏み込みません。

Causal Forestとは

Causal Forestとは、条件付き平均処置効果(CATE)を推定するためのノンパラメトリック手法の一つである。
Causal Forestは、潜在結果の条件付独立(共変量Xで条件づけたとき、割り当てが潜在結果と独立であること)の仮定、および重なりの仮定(条件付き正値性、共変量で条件付けしたときに各処置に割り当てられる確率が0ではないこと)が満たされる場合において、データを複数(サブセット)に分割し、それぞれの部分で介入効果を推定する決定木(Causal Tree)を複数作成し、それらの結果を統合することでモデルを構築し、推定量を算出します。
回帰や分類の予測で用いられているRandom Forestとの違いは、その分割方法にあります。Wager and Athey(2018)が発表したHonestyアプローチは、訓練データを工夫して分割することによって推定量の一致性や漸近正規性が得られるというもので、今回使用する手法でも活用されています。

Causal Forestの詳しい説明に関しては、下記の参考文献内の書籍や記事を参照いただきたいと思います。

使用するデータ

本記事では、Lalonde(1986)で使用されている職業訓練に関するRCTデータを使用しています。このデータはNational Supported Work (NSW) Demonstrationという労働訓練プログラムのデータで、訓練の参加がランダムに振り分けられ、プログラム参加後の賃金に効果があるかを検証することができます。
本データセットは、このデータを使った追試論文(Dehejia and Wahba (1998)等)を発表している著者のサイトで公開されており、そちらから取得しました。訓練の詳細等は、参考文献に挙げている論文を参照いただきたいと思います。
https://users.nber.org/~rdehejia/nswdata2.html

Pythonコード

パッケージの取得

!pip install econml
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import lightgbm as lgb
import seaborn as sns
import numpy as np
from econml.dml import CausalForestDML
import japanize_matplotlib
from scipy import stats
import statsmodels.api as sm
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import RandomForestClassifier
import shap
from econml.cate_interpreter import SingleTreeCateInterpreter

データの取得

df = pd.read_stata('https://users.nber.org/~rdehejia/data/nsw_dw.dta')

データセットは以下のようになっています。

格納されている変数のうち、推定に使用する変数は以下の通りです。

  • treat : 処置ダミー
  • age : 年齢
  • education : 教育年数
  • black : 人種ダミー①
  • hispanic : 人種ダミー②
  • married : 婚姻ダミー
  • nodegree : 高卒ダミー
  • re78 : 1978年の収入

今回は被説明変数にre78, 共変量に年齢、教育年数、人種ダミー、婚姻ダミー、高卒ダミーを用います。

ATEの算出

まずは、平均処置効果(ATE)を算出します。
今回RCTのため、Treatment Groupの被説明変数の平均とControl Groupの被説明変数の平均との差がATEとなります。

df[df['treat'] == 1]['re78'].mean() - df[df['treat'] == 0]['re78'].mean()

1794.3433

これは先に紹介した元の論文の値と一致します。また、以下のようにP値を計算すると、5%有意水準で有意な結果であることが確認できます。

u_test = stats.mannwhitneyu(df[df['treat'] == 1]['re78'], df[df['treat'] == 0]['re78'], alternative="two-sided")
print(f"p値: {u_test.pvalue}")

p値: 0.010946644504522724

Causal Forestの実装

今回はEconMLを用いてCausal Forestを実装します。実装に当たって、公式ドキュメントを参照しました。
https://econml.azurewebsites.net/_autosummary/econml.dml.CausalForestDML.html

X = df[['age','married','nodegree','black','education']].values#.reshape(-1, 1) #説明変数
W = None
T = df[['treat']].values #処置変数
Y = df['re78'].values #目的変数

#ランダムシードを指定
random_seed = 42

#CausalForestDML推定器を設定
est = CausalForestDML(
    model_y=RandomForestRegressor(
        n_estimators=10, 
        min_samples_leaf=10, 
        random_state=random_seed 
    ),
    model_t=RandomForestClassifier(
        n_estimators=10, 
        min_samples_leaf=10, 
        random_state=random_seed 
    ),
    honest=True,
    discrete_treatment=True,
    n_estimators=100,  #木の数
    criterion='mse',  #評価指標
    max_depth=5,  #木の最大の深さ
    min_samples_split=10,  #ノードを分割するのに必要な最小限のサンプル数
    min_samples_leaf=5,  #各葉のノードに必要な最低限のサンプル数
    random_state=random_seed  
)

# データに基づいてモデルをフィット
est.fit(Y, T, X=X, W=W, cache_values=True)

結果

est.summary(alpha=0.05)


"Doubly Robust ATE on Training Data Results"の結果から、Causal Forestを用いた推定から得たATEが従来の手法で取得したATEと近似することが確認できました。

次に、効果の異質性を考察する。効果の異質性を可視化するにあたって、同じく公式ドキュメント内の"interpret"を参照しました。
https://econml.azurewebsites.net/spec/interpretability.html
ここでは、SHAPを用いて可視化します。

shap_values = est.shap_values(X)
shap.plots.beeswarm(shap_values['Y0']['T0_1.0'])

この結果から、X0(age)やX4(married)について、効果の異質性があることが分かります。これは、年齢や婚姻状態が異なると、教育訓練が賃金に与える効果が異なることを示唆しています。

おわりに

今回は教育訓練のRCTデータを使い、Causal Forestを実装して賃金に与える効果の異質性を推定しました。結果として、年齢や婚姻の有無に関して、教育訓練の効果に異質性があることが分かりました。施策効果の異質性を明らかにすることは、ビジネスにおいて施策を打った時により収益があがるターゲットを理解したいときに重宝されると思うので、CATEの取得方法を理解して正しく実装できるようになりたいと思います。
今後は、公式ドキュメントで紹介されていた"policy interpreter"という可視化方法を学習し、紹介できたらと思います。

今回用いたCausal ForestはCATEを推定する手法として注目されていますが、その精度に関して議論が存在し、確立した手法として定着するまで道半ばであると認識しております。今回はその精度に関する議論には立ち入りませんが、今後の発展に注目していこうと思います。

参考文献

Discussion