🎓 レベル:発展 | 重要度:B(標準)
📎 前提:構造的因果モデルとdo演算子 | 潜在結果モデル
要点(BLUF)
- Pearl の因果の階梯(Ladder of Causation) は因果の問いを3段に分けます。第1段 関連(見る) 、第2段 介入(する) 、第3段 反事実(想像する) 。上の段は下の段の情報だけからは答えられません。
- 反事実は個体レベルの問いです。「この患者が、実際には薬を飲まず回復したが、もし飲んでいたらどうなっていたか」。これは潜在結果 (潜在結果モデル)そのもので、計算には DAG だけでなく完全な SCM(構造方程式と外生ノイズ)が要ります。
- SCM での反事実は3手順 abduction → action → prediction(観測から外生ノイズを復元 → 介入 → 予測)で計算できます。1個体について「観測 ≠ 介入 ≠ 反事実」を数値で確かめます。
1. 因果の階梯:3つの段
因果の問いは難易度の異なる3段に分かれ、それぞれ別の情報を要求します。
flowchart TB
R1["第1段 関連・見る: P(y∣x) — 観測・相関"]
R2["第2段 介入・する: P(y∣do(x)) — 実験・介入"]
R3["第3段 反事実・想像する: P(y_x∣x',y') — 後悔・責任"]
R1 --> R2 --> R3
| 段 | 行為 | 記号 | 典型の問い | 必要なもの |
|---|---|---|---|---|
| 1 関連 | 見る | 「 を見たら はどうか」 | 観測データ | |
| 2 介入 | する | 「 をしたら はどうか」 | DAG + 識別の仮定 | |
| 3 反事実 | 想像する | 「実際は で だったが、もし だったら」 | 完全な SCM |
第2段は構造的因果モデルとdo演算子の 演算子で扱いました。第3段はその上です。記号 は「実際には で を観測した、その条件のもとで、もし だったときの ()の分布」を表します。実際に起きた事実()を条件に入れたまま、起きなかった世界を問う——これが反事実です。
なぜ第3段が最上段なのか。第2段 は母集団の問い(全員に をしたらの平均)でした。第3段は、すでに結果が分かっている特定の個体について、その個体固有の事情を保ったまま処置だけを変えた世界を問います。介入分布をいくら集めても、「この個体がどんな外れ値だったか」という個体情報は復元できないため、第2段から第3段へは原理的に登れません。
2. 反事実は個体レベル:SCM が要る理由
潜在結果モデルで、個体 には2つの潜在結果 があり、その差 が個体処置効果(ITE) でした。反事実とは、まさにこの観測できなかった方の潜在結果を名指しすることです。 で を観測した個体について、 が反事実にあたります。
DAG と だけでは個体の反事実は出せません。 は母集団平均で、「全員を治療した世界の平均回復」を返すだけ。この個体が平均より幸運だったか不運だったかは、その個体の外生ノイズ に入っています。 を取り出すには、各変数がノイズからどう生成されたか——すなわち構造方程式 まで指定した完全な SCM(構造的因果モデルとdo演算子)が必要なのです。
3. abduction → action → prediction
SCM が手元にあれば、反事実は3手順で機械的に計算できます。観測した証拠を (個体の観測値)とします。
- Abduction(遡及):観測 を使って外生ノイズの分布を更新する。。決定的で可逆な構造方程式なら、 は1点に定まります。
- Action(介入):知りたい処置 をモデルに施す。 の構造方程式を に置き換える(構造的因果モデルとdo演算子のグラフ手術)。
- Prediction(予測):更新したノイズ を、介入後のモデルに流して目的変数 を計算する。
直観はこうです。Abduction でその個体の「持って生まれた事情」を観測から逆算し、それを固定したまま処置だけを反転させて結果を引き直す。だから反事実は「他人の平均」ではなく「この個体がこの個体のまま、処置だけ違っていたら」を返します。鍵は外生ノイズ を共有したまま処置を変える点で、これが反事実と母集団介入(毎回ノイズを引き直す)を分ける一線です。
4. 1個体の反事実を計算する
加法ノイズの SCM を作ります。結果は で、効果 は個体ごとに異なります(異質効果)。「治療せず・たまたま結果が良かった」1個体を選び、その反事実を abduction→action→prediction で計算します。
import numpy as np
# === SCMで1個体の反事実を計算する: abduction(外生ノイズ推定)→action→prediction ===
rng = np.random.default_rng(303)
n = 50000
a, b = 1.0, 3.0 # 切片と交絡Cの係数
# 構造方程式
C = rng.binomial(1, 0.5, size=n) # 交絡(0/1)
prob_treat = np.where(C == 1, 0.7, 0.3)
X = rng.binomial(1, prob_treat) # 処置(Cに依存)
tau_indiv = 2.0 + 1.0 * C # 個体ごとの効果(C=0で2, C=1で3): 異質
U_Y = rng.normal(0.0, 1.0, size=n) # 結果の外生ノイズ(個体固有)
Y = a + tau_indiv * X + b * C + U_Y
ATE_pop = tau_indiv.mean() # 母集団の平均処置効果(=do効果)
# --- ある1個体を選ぶ: 「治療せず(X=0)・C=1・たまたま結果が良かった(U_Yが大)」人 ---
mask = (X == 0) & (C == 1)
candidate_idx = np.where(mask)[0]
i = candidate_idx[np.argmax(Y[candidate_idx])] # その中で観測Yが最大の個体
c_i, x_i, y_i = C[i], X[i], Y[i]
# (Rung3) Abduction: 観測(c_i, x_i, y_i)と構造方程式から、この個体の外生ノイズU_Yを逆算
tau_i = 2.0 + 1.0 * c_i
u_i = y_i - (a + tau_i * x_i + b * c_i)
# (Rung3) Action + Prediction: この個体だけ処置を反転(do(X=1))し、u_iは固定したままYを再計算
y_counterfactual = a + tau_i * 1 + b * c_i + u_i
indiv_effect = y_counterfactual - y_i # この人個人の因果効果
# (Rung1) 関連=見る: 治療した人の平均結果(交絡で偏る周辺量)
rung1_assoc = Y[X == 1].mean()
# (Rung2) 介入=する: 全員を治療/非治療した母集団平均(介入分布)
do1 = a + tau_indiv * 1 + b * C + rng.normal(0, 1, n)
do0 = a + tau_indiv * 0 + b * C + rng.normal(0, 1, n)
rung2_do1, rung2_do0 = do1.mean(), do0.mean()
print(f"選んだ個体 i: C={c_i}, X={x_i}(未治療), 観測Y={y_i:.2f}")
print(f" Abductionで復元した外生ノイズ U_Y = {u_i:.2f}")
print("-- Pearlの因果の階梯(同じ個体への3つの問い) --")
print(f"Rung1 関連 E[Y|X=1] : {rung1_assoc:.2f} (治療した人を「見る」)")
print(f"Rung2 介入 E[Y|do(1)] / do(0) : {rung2_do1:.2f} / {rung2_do0:.2f} (全員に「する」)")
print(f"Rung3 反事実 この個体が治療されていたら: {y_counterfactual:.2f} (この人を「想像」)")
print("-- 効果の比較 --")
print(f"母集団ATE(=do(1)-do(0)) : {ATE_pop:.2f}")
print(f"この個体の因果効果(反事実-観測) : {indiv_effect:.2f} (=tau_i={tau_i:.0f})")
実行すると次のように印字されます。
選んだ個体 i: C=1, X=0(未治療), 観測Y=7.53
Abductionで復元した外生ノイズ U_Y = 3.53
-- Pearlの因果の階梯(同じ個体への3つの問い) --
Rung1 関連 E[Y|X=1] : 5.80 (治療した人を「見る」)
Rung2 介入 E[Y|do(1)] / do(0) : 4.99 / 2.50 (全員に「する」)
Rung3 反事実 この個体が治療されていたら: 10.53 (この人を「想像」)
-- 効果の比較 --
母集団ATE(=do(1)-do(0)) : 2.50
この個体の因果効果(反事実-観測) : 3.00 (=tau_i=3)
出力の意味:同じ1個体に3段の問いを当てると、3つとも違う答えが返ります。
- Rung1 関連 :「治療した人を見る」と平均 。ただし治療群は に偏るので、これは交絡で歪んだ周辺量です(構造的因果モデルとdo演算子)。
- Rung2 介入 (治療)/(非治療):全員を治療/非治療した母集団平均。差 が母集団 ATE です。これは「平均的な人」の話で、特定個体の事情は含みません。
- Rung3 反事実 :この個体( で、Abduction により外生ノイズ と判明した幸運な人)がもし治療されていたら 。母集団平均 よりずっと高いのは、この人の が大きいからです。観測 に、その人自身の効果 がちょうど乗っています。
個体の因果効果(反事実 観測 )は母集団 ATE()とも一致しません。「平均的に効く量」と「この人に効く量」は別物で、後者を出すには Abduction で個体ノイズを取り出す必要がある——これが反事実が最上段にいる理由です。
5. 仮定の直観的意味:なぜ介入では足りないのか
第2段 と第3段 反事実の差は、外生ノイズ を引き直すか固定するかにあります。
- 介入 :母集団に対する操作。各個体の は から新たに引かれるものと考え、 と について期待を取ります。だから「平均的な人」の答えになります。
- 反事実 :観測した個体の を、その観測から逆算して固定します(Abduction)。同じ のまま処置だけ変えるので、「この個体がこの個体のまま」の答えになります。
コードでは介入(Rung2)が rng.normal(0,1,n) で毎回ノイズを引き直すのに対し、反事実(Rung3)は観測から復元した u_i を固定したまま使っています。この一点が母集団の問いと個体の問いを分けます。だからこそ反事実は SCM( と )を要求し、DAG と介入だけでは登れないのです。
潜在結果の言葉でいえば、反事実 は個体 の潜在結果 そのもの。潜在結果モデルの「因果推論の根本問題」(片方しか観測できない)を、SCM は「観測した方から を逆算し、構造方程式で欠測側を埋める」という形でモデル依存に解きます。埋め合わせの正しさは SCM の正しさに完全に依存する——ここが反事実の強さであり、もろさでもあります。
⚠️ よくある誤解・落とし穴
- 反事実は SCM 抜きには検証不能。Abduction で復元した も、その後の予測も、構造方程式の関数形に依存します。関数形が違えば反事実の値も変わり、データだけでは確かめられません(観測できるのは片方だけ)。反事実の主張は SCM の仮定に乗っていることを忘れないこと。
- 個体効果 ≠ 母集団効果。「ATE が正なら誰にでも効く」ではありません。効果が異質なら、ある個体には逆効果ということもあり得ます(上の例でも個体効果 は母集団 ATE と違いました)。
- 第2段の情報で第3段を答えない。RCT は介入(第2段)を与えますが、特定個体の反事実(第3段)までは特定しません。「後悔(もし違う選択をしていたら)」「因果の帰属(その薬が原因で治ったか)」は反事実の問いで、追加のモデル仮定が要ります。
- 加法ノイズだから Abduction が1点で済んだ。一般の非可逆な構造方程式では、 は1点でなく分布になり、反事実も分布で返ります。本ノートの「点で復元」は加法・可逆という特別な場合です。
関連ノート
- 因果:構造的因果モデルとdo演算子(第2段=介入と SCM)/潜在結果モデル(反事実=観測されない潜在結果)/識別の仮定(一致性と反事実の関係)/異質処置効果とメタ学習器(S/T/X-learner)(個体・条件付き効果 CATE の推定)/媒介分析(反事実で定義される自然直接・間接効果)
- ベイズ:事前・尤度・事後・周辺尤度(Abduction=事後でノイズを更新する見方)
- 第6章 ベイズと構造的因果 目次