Mímisbrunnr知恵の泉

← 因果推論 一覧

🎓 レベル:発展 | 重要度:B(標準)

📎 前提:構造的因果モデルとdo演算子 | 潜在結果モデル

要点(BLUF)


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 関連見るP(yx)P(y\mid x)XX を見たら YY はどうか」観測データ
2 介入するP(ydo(x))P(y\mid do(x))XXしたら YY はどうか」DAG + 識別の仮定
3 反事実想像するP(yxx,y)P(y_x\mid x',y')「実際は xx'yy' だったが、もし xx だったら」完全な SCM

第2段は構造的因果モデルとdo演算子dodo 演算子で扱いました。第3段はその上です。記号 P(yxx,y)P(y_x\mid x',y') は「実際には X=xX{=}x'Y=yY{=}y' を観測した、その条件のもとで、もし X=xX{=}x だったときの YY=yx=y_x)の分布」を表します。実際に起きた事実(x,yx',y')を条件に入れたまま、起きなかった世界を問う——これが反事実です。

なぜ第3段が最上段なのか。第2段 P(ydo(x))P(y\mid do(x))母集団の問い(全員に xx をしたらの平均)でした。第3段は、すでに結果が分かっている特定の個体について、その個体固有の事情を保ったまま処置だけを変えた世界を問います。介入分布をいくら集めても、「この個体がどんな外れ値だったか」という個体情報は復元できないため、第2段から第3段へは原理的に登れません。


2. 反事実は個体レベル:SCM が要る理由

潜在結果モデルで、個体 ii には2つの潜在結果 Yi(1),Yi(0)Y_i(1),Y_i(0) があり、その差 τi=Yi(1)Yi(0)\tau_i=Y_i(1)-Y_i(0)個体処置効果(ITE) でした。反事実とは、まさにこの観測できなかった方の潜在結果を名指しすることです。Xi=0X_i{=}0YiY_i を観測した個体について、Yi(1)Y_i(1) が反事実にあたります。

DAG と dodo だけでは個体の反事実は出せません。P(Ydo(X=1))P(Y\mid do(X{=}1)) は母集団平均で、「全員を治療した世界の平均回復」を返すだけ。この個体が平均より幸運だったか不運だったかは、その個体の外生ノイズ UiU_i に入っています。UiU_i を取り出すには、各変数がノイズからどう生成されたか——すなわち構造方程式 fif_i まで指定した完全な SCM構造的因果モデルとdo演算子)が必要なのです。


3. abduction → action → prediction

SCM が手元にあれば、反事実は3手順で機械的に計算できます。観測した証拠を E=eE{=}e(個体の観測値)とします。

  1. Abduction(遡及):観測 ee を使って外生ノイズの分布を更新する。P(U)P(UE=e)P(U)\to P(U\mid E{=}e)。決定的で可逆な構造方程式なら、UU1点に定まります
  2. Action(介入):知りたい処置 do(X=x)do(X{=}x) をモデルに施す。XX の構造方程式を X=xX{=}x に置き換える(構造的因果モデルとdo演算子のグラフ手術)。
  3. Prediction(予測):更新したノイズ P(Ue)P(U\mid e) を、介入後のモデルに流して目的変数 YY を計算する。

直観はこうです。Abduction でその個体の「持って生まれた事情」を観測から逆算し、それを固定したまま処置だけを反転させて結果を引き直す。だから反事実は「他人の平均」ではなく「この個体がこの個体のまま、処置だけ違っていたら」を返します。鍵は外生ノイズ UU を共有したまま処置を変える点で、これが反事実と母集団介入(毎回ノイズを引き直す)を分ける一線です。


4. 1個体の反事実を計算する

加法ノイズの SCM を作ります。結果は Y=1+τ(C)X+3C+UYY=1+\tau(C)\,X+3C+U_Y で、効果 τ(C)=2+C\tau(C)=2+C は個体ごとに異なります(異質効果)。「治療せず・たまたま結果が良かった」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つとも違う答えが返ります。

個体の因果効果(反事実 - 観測 =3.00=3.00)は母集団 ATE(2.502.50)とも一致しません。「平均的に効く量」と「この人に効く量」は別物で、後者を出すには Abduction で個体ノイズを取り出す必要がある——これが反事実が最上段にいる理由です。


5. 仮定の直観的意味:なぜ介入では足りないのか

第2段 dodo と第3段 反事実の差は、外生ノイズ UU を引き直すか固定するかにあります。

コードでは介入(Rung2)が rng.normal(0,1,n)毎回ノイズを引き直すのに対し、反事実(Rung3)は観測から復元した u_i固定したまま使っています。この一点が母集団の問いと個体の問いを分けます。だからこそ反事実は SCM(fif_iUU)を要求し、DAG と介入だけでは登れないのです。

潜在結果の言葉でいえば、反事実 YX=1(ui)Y_{X=1}(u_i) は個体 ii の潜在結果 Yi(1)Y_i(1) そのもの。潜在結果モデルの「因果推論の根本問題」(片方しか観測できない)を、SCM は「観測した方から UU を逆算し、構造方程式で欠測側を埋める」という形でモデル依存に解きます。埋め合わせの正しさは SCM の正しさに完全に依存する——ここが反事実の強さであり、もろさでもあります。


⚠️ よくある誤解・落とし穴


関連ノート