この連載について
因果推論を「本を読んだ」で終わらせず、自分の言葉で説明でき、コードで再現できる状態まで落とす30日連載です。Day 1 では「相関が因果に化ける3つの罠(疑似相関・交絡・選択バイアス)」をやりました。今日はその土台になる共通言語を入れます。
※Claudeと伴奏しながら自分の理解度を深めよう!ということでの1人アドベントカレンダー企画です。学習計画や下書きなどはClaudeに全面的に協力していただいていますが、あくまでも自分の理解を深めるための企画です。
Day 1–3:全体像(相関≠因果/潜在的結果/3つの流派)← いまここ
Day 4–9:Rubin流(潜在的結果・傾向スコア)
Day 10–15:Pearl流(DAG・バックドア基準・do演算子)
Day 16–21:計量経済の準実験(回帰・IV・DID・RDD)
Day 22–27:ML×因果(CATE・Double ML・Causal Forest)
Day 28–30:空間データ×因果/ベイズ×因果/総括
今回は「潜在的効果」についてやっていきます。
TL;DR(3行)
- 因果は「その人が受けた結果 Y(1) と受けなかった結果 Y(0) の引き算」で定義する。この2つを潜在的結果と呼ぶ。
- でも現実に見えるのは片方だけ(受けた人の Y(1) か、受けない人の Y(0))。もう片方=反事実は永遠に欠測 ← これが因果推論の根本問題。
- だから個人の効果は測れず、平均で攻める。ただし平均にも種類がある — ATE(全員)/ATT(受けた人)/CATE(ある属性の人)は別の問いで、効果が人によって違うほど答えが食い違う。
今日の問い
Day 1で「アイスを止めても溺死は減らない」と分かった。では逆に、本当に効くもの——たとえば「職業訓練を受けたら年収は上がるか」——を、私たちはどう厳密に言えばいいのか?
「訓練を受けた人の年収が高かった」だけでは足りません(それは Day 1 の交絡・選択バイアスの餌食です)。同じ人が「受けた場合」と「受けなかった場合」を比べたい。 この当たり前の願いを数式にすると、因果推論の全体像が一気に見通せます。
潜在的結果:因果の最小単位
ある人 $i$ に、2つの起こりえた結果を考えます。
- $Y_i(1)$ … その人が処置を受けたら得られる結果
- $Y_i(0)$ … その人が受けなかったら得られる結果
この2つを**潜在的結果(potential outcomes)**と呼びます。「潜在的」なのは、最終的に実現するのは片方だけだからです。個人にとっての因果効果は、素直にこの引き算で定義します。
$$\tau_i = Y_i(1) - Y_i(0)$$
アスピリンの例(Imbens & Rubin 第1章)なら「飲んだら頭痛が消えるか/飲まなかったら残るか」の比較。訓練の例なら「受けたら年収いくら/受けなかったら年収いくら」の差。因果とは、事実と反事実の差です。
ポイントは、$\tau_i$ の定義が 「どちらを実際に観測したか」に一切依存しないことです(Imbens & Rubin 1.3節)。効果はその人の中に最初から2つ揃っている、と考える。ここが Pearl の DAG(Day 10〜)とはスタート地点の違う、Rubin流の入り方です。
因果推論の根本問題:片方しか見えない
ところが——$Y_i(1)$ と $Y_i(0)$ の両方を同時に観測することは絶対にできません。訓練を受けた人については $Y_i(1)$ しか手に入らず、「もし受けていなかったら」の $Y_i(0)$ は永遠に分かりません。逆もまた然り。実際に観測できる結果は
$$Y_i^{\text{obs}} = \begin{cases} Y_i(1) & (W_i = 1:処置を受けた)\ Y_i(0) & (W_i = 0:受けなかった)\end{cases}$$
で、もう片方 $Y_i(\text{もう一方})$ は反事実(counterfactual)=欠測になります。これを Holland (1986) は**因果推論の根本問題(the fundamental problem of causal inference)**と呼びました。「因果推論は本質的に欠測データ問題である」(Imbens & Rubin)という有名な一言はここから来ます。
左が「神の視点」。本当は各人に $Y(0)$(青)と $Y(1)$(橙)の2点があり、その差が個体の効果です。ところが右の「現実」では、受けた人は橙だけ・受けない人は青だけが見え、もう片方は白丸(?)=欠測。私たちはいつも右の世界にいます。
手を動かす①:オラクルを作って「片方を隠す」
反事実は現実では観測できません。だからこそシミュレーションが効きます——私たちが神になって2つの世界線が見れる気持ちになってみます。
両方の潜在的結果を作れば、「片方を隠すと何が失われるか」を安全に観察できます。
まずは、「研修トレーニングを受けた場合の年収(万円)」で潜在的効果の推定を実施してみましょう。効果は若年ほど大きい設定にしておきます(あとで効く伏線です)。
import numpy as np, pandas as pd
rng = np.random.default_rng(2)
N = 500
young = rng.integers(0, 2, N) # 1=若年, 0=それ以外
base = 200 + 100*(1-young) + rng.normal(0, 20, N) # Y(0): 訓練を受けない年収
eff = np.where(young==1, 80, 20) + rng.normal(0, 8, N) # 個体の訓練効果(若年ほど大)
Y0, Y1 = base, base + eff
ite = Y1 - Y0 # 個体因果効果(神だけが知る)
p = np.where(young==1, 0.6, 0.3) # 若年ほど自発的に受講しやすい
W = (rng.random(N) < p).astype(int) # 実際に受けたか
Yobs = np.where(W==1, Y1, Y0) # 現実に観測できる結果
tb = pd.DataFrame({"若年": young, "Y0": Y0.round(), "Y1": Y1.round(),
"効果": ite.round(), "受講W": W, "観測Yobs": Yobs.round()})
print(tb.head(7).to_string(index=False))
若年 Y0 Y1 効果 受講W 観測Yobs
1 217.0 295.0 78.0 1 295.0
0 283.0 304.0 21.0 1 304.0
0 275.0 306.0 31.0 0 275.0
0 264.0 294.0 30.0 0 264.0
0 293.0 315.0 21.0 0 293.0
1 215.0 289.0 74.0 0 215.0
0 297.0 314.0 17.0 1 314.0
効果 列(Y1 - Y0)はきれいに定義できています。若年(個人1・6)は +78, +74 と大きく、高年は +20 前後。でも現実に手に入るのは 観測Yobs の1列だけ。 各行で Y0・Y1 のどちらか片方は、本当は見えていません。個人1なら「受けた(295)」は分かるが「受けなかったら(217)」は永遠の反事実です。個体効果 +78 は、神にしか計算できない——これが根本問題の手触りです。
推定対象(estimand):どの平均を答えるのか
個体効果が測れないなら、平均に逃げます。ただし「平均」と一口に言っても、誰の上で平均するかで意味が変わります。代表的な3つを定義します。
| 記号 | 名前 | 定義 | 答える問い |
|---|---|---|---|
| ATE | 平均処置効果 | $E[Y(1) - Y(0)]$ | 母集団全員に施したら平均どれだけ効く? |
| ATT | 処置群の平均処置効果 | $E[Y(1) - Y(0) \mid W = 1]$ | 実際に受けた人たちにとって効いた? |
| CATE | 条件付き平均処置効果 | $E[Y(1) - Y(0) \mid X = x]$ | ある属性 $x$ の人にはどれだけ効く? |
効果が人によって違う(異質効果)とき、この3つは一致しません。 さっきのオラクルは効果を若年80・高年20で作ったので、割付や属性でどこを平均するかによって答えがズレます。
左は個体効果 $Y_i(1)-Y_i(0)$ の分布。若年(橙)と高年(青)で2つの山に割れています。ここで注目は赤い破線の ATE=50。これは2つの山の谷間に落ちていて、実際にはほとんど誰もこの効果ではありません。「平均は集団の要約であって、個人の予測ではない」を絵にするとこうなります。右のバーは4つの推定対象の比較で、ATT(57)>ATE(50) になっています。理由は、受講者が若年に偏る(自発的選択)ぶん、受講者集団の効果が全体平均より大きく出るからです。
「どの数字を出すか」は分析設計の最初の意思決定です。政策を全国民に広げるなら ATE、参加者への効果を検証したいなら ATT、若年に絞るべきかを知りたいなら CATE。同じデータでも問いが違えば答えが違う——ここを曖昧にすると議論が噛み合いません。
手を動かす②:3つを計算して食い違いを見る
オラクルは神の視点なので、3つとも正解を直接計算できます(現実にはできません。だから練習になります)。
print("ATE 全員 = %.1f" % ite.mean())
print("CATE 若年 = %.1f" % ite[young==1].mean())
print("CATE 高年 = %.1f" % ite[young==0].mean())
print("ATT 受講者だけ = %.1f" % ite[W==1].mean())
ATE 全員 = 50.3
CATE 若年 = 79.6
CATE 高年 = 19.7
ATT 受講者だけ = 56.9
若年と高年で効果が4倍違い(79.6 vs 19.7)、全員平均の ATE=50.3 はそのどちらでもない。受講者に絞った ATT=56.9 は若年寄りに引っ張られている。「効果は50でした」と一言で片づける危うさが数字で見えます。
手を動かす③:実データでATEを推定する(無作為化のご褒美)
ここまでは合成データでした。最後に本物のデータで、根本問題を抱えたまま ATE を推定します。因果推論の教科書で必ず登場する LaLonde の NSW(National Supported Work)——就労支援プログラムを無作為に割り当てた実験データ(445名)を使います。causaldata パッケージですぐ手に入ります。
import statsmodels.formula.api as smf
from causaldata import nsw_mixtape
df = nsw_mixtape.load_pandas().data # NSW 実験標本 445名(treat, re78 ほか)
print(df.groupby("treat")["re78"].agg(["size", "mean"]).round(1))
model = smf.ols("re78 ~ treat", data=df).fit() # 収入(1978) を 処置ダミーに回帰
print("推定ATE = %.1f USD" % model.params["treat"])
print("95%%CI = [%.1f, %.1f]" % tuple(model.conf_int().loc["treat"]))
size mean
treat
0 260 4554.8
1 185 6349.1
推定ATE = 1794.3 USD
95%CI = [550.6, 3038.1]
このデータでも、1人につき観測できるのは片方の腕だけです(訓練を受けた185名は $Y(1)$、受けない260名は $Y(0)$)。個体の反事実は相変わらず欠測。それでも群の平均差=約1,794ドルという平均効果は推定できました。statsmodels の単回帰 re78 ~ treat の係数は、まさに処置群平均−対照群平均そのもので、ついでに95%信頼区間(約550〜3,038ドル)まで出ます。
なぜ単純な引き算が ATE になるのか? カギは無作為割付です。処置を誰が受けるかをコインで決めると、割付 $W$ が潜在的結果と独立($W \perp!!!\perp (Y(0), Y(1))$)になります。すると
$$E[Y^{\text{obs}} \mid W=1] = E[Y(1)], \qquad E[Y^{\text{obs}} \mid W=0] = E[Y(0)]$$
が成り立ち、観測できる群平均の差がそのまま $E[Y(1)] - E[Y(0)] = \text{ATE}$ になります。Day 1 で暴れた交絡や選択バイアスを、割付の設計で根こそぎ殺している——これが無作為化実験(RCT)が黄金律と呼ばれる理由で、Day 4 で正面から掘ります。
逆に言えば、無作為化されていない観察データでは、この引き算は ATE からズレます(=Day 1 の交絡)。そのズレをどう埋めるか(傾向スコア・回帰・IV・DID…)が、連載の残り四半分の主戦場です。
つまづき・誤解しやすい点
- 「反事実は予測すればいいのでは?」は半分正解・半分危険。 機械学習で $Y_i(0)$ を予測して差を取る発想(メタラーナー)は Day 23 で扱いますが、予測が当たる保証=交絡が無い保証があって初めて因果になります。予測精度と因果の正しさは別物です。
- ATE・ATT・CATE を混同しない。 論文やダッシュボードで「効果は◯◯」と言うとき、それが全員平均なのか参加者平均なのかで意思決定が変わります。効果が異質なら、平均は誰も代表しない(fig2 の谷間)。
- SUTVA という隠れた前提。 「$Y_i(1), Y_i(0)$ が他人の割付に影響されない(干渉なし)」を暗黙に仮定しています。ワクチンの集団免疫や、隣の地域への波及があると崩れます。空間データでは特に効いてくる前提で、Day 28 で本気で扱います。
実務での使いどころ(空間データ)
私の本業は衛星データ×水道インフラ×AIで、「この施策(配管更新・センサ設置)は本当に効いたのか」を問う場面が多くあります。ここで潜在的結果の言葉が効きます。
- まず estimand を決める。 「全自治体に展開したらの効果(ATE)」なのか「導入した自治体での効果(ATT)」なのか。ダッシュボードに出す数字の意味が変わります。
- 反事実は“隣の似た地域”では代用できない。 似た立地の未導入地域を対照に使うのは自然ですが、Day 1 の空間交絡(立地が共通原因)が乗ります。潜在的結果の枠組みは「本当は同じ地域の受けなかった姿と比べたい」という理想を明示してくれるので、代用のズレを意識できる。
- 干渉(SUTVA違反)に敏感になる。 ある地域の対策が上下流の隣接地域に染み出すと、個体の潜在的結果が他人の割付で動きます。空間データでは日常茶飯事です。
「効果があった」と言う前に、それは誰のどの潜在的結果の比較なのか。今日の言葉は、その一行を書けるようにするための道具です。
参考
- Imbens & Rubin『Causal Inference for Statistics, Social, and Biomedical Sciences』第1章』— 潜在的結果・根本問題・SUTVA・estimand
- Pearl「Causal Inference in Statistics」潜在的結果の節」 — 反事実 $Y_x$ を確率変数として扱う視点
- 伊藤公一朗『データ分析の力』 — 「本当に知りたいのは反事実」を数式なしで
- LaLonde (1986) / Dehejia & Wahba (1999) NSW 実験標本(
causaldataパッケージ, MIT ライセンス)
次回予告(Day 3)
因果推論には3つの流派があります——潜在的結果(Rubin)/構造的因果モデル・DAG(Pearl)/計量経済の準実験。同じ「因果」を違う言葉で攻めるこの3つを、1枚のマップで俯瞰します。今日の潜在的結果は、その1つ目の言語でした。


