Mímisbrunnr知恵の泉

← 因果推論 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:バックドア基準と識別 | 識別の仮定 | 数理:重回帰分析(統計)

要点(BLUF)


1. 識別:回帰調整は g公式の一実装

処置 X{0,1}X\in\{0,1\}、結果 YY、共変量 CC が下図の関係にあるとする。バックドアパス XCYX \leftarrow C \rightarrow Y が開いているので、素朴な平均差 E[YX=1]E[YX=0]E[Y\mid X{=}1]-E[Y\mid X{=}0] は因果効果ではない。

flowchart LR
    C["交絡 C"] --> X["処置 X"]
    C --> Y["結果 Y"]
    X --> Y

CCバックドア基準を満たす(XX の非子孫で、すべてのバックドアパスを塞ぐ)なら、バックドア基準と識別より平均処置効果は

τ=EC[E[YX=1,C]E[YX=0,C]]\tau = E_C\big[\,E[Y\mid X{=}1,C]-E[Y\mid X{=}0,C]\,\big]

で識別できる。これを g公式(標準化) と呼ぶ。前提は識別の仮定条件付き交換可能性 (Y(1),Y(0))XC(Y(1),Y(0))\perp X\mid C正値性 0<e(C)<10<e(C)<1、そして SUTVA

回帰調整は、内側の条件付き期待値 E[YX,C]E[Y\mid X,C] を回帰モデルで推定し、外側の期待値を標本平均で置き換える実装にすぎない。線形モデル

E[YX,C]=α+τX+βCE[Y\mid X,C] = \alpha + \tau X + \beta^{\top} C

を当てはめれば、XX の係数 τ\tau がそのまま ATE の推定値になる。ただしこの式が成り立つのは、条件付き期待値が本当に線形で、かつ処置効果が CC に依らず均一なときだけである。

❓ ここで一度立ち止まろう:「CC を回帰に入れた」ことと「E[YX,C]E[Y\mid X,C] を正しくモデル化した」ことは同じだろうか? 同じではない。前者は変数を入れただけ、後者は関数形まで合っていることを要求する。この差がこの節の主題だ。


2. 破綻:交絡が非線形に効くと線形調整は塞げない

真の効果を仕込んだ擬似データで確かめる。交絡 CC2乗で結果に効き、しかも処置割り当ても C2C^2 に依存する(C|C| が大きいほど処置されやすい)状況を作る。真の処置効果は均一で ATE=2.0\text{ATE}=2.0 とする。

import numpy as np
import pandas as pd
import statsmodels.formula.api as smf

# === 交絡が2乗で効くデータで、線形回帰調整が ATE を外すことを確かめる ===
rng = np.random.default_rng(42)
n = 4000
C = rng.uniform(-2, 2, size=n)

# 処置割り当て: |C| が大きい(両端)ほど処置されやすい = C^2 に依存(非線形)
logit_treat = 2.0 * (C**2 - 1.3)
prop = 1.0 / (1.0 + np.exp(-logit_treat))
X = rng.binomial(1, prop)

# 結果: 交絡 C は2乗で効く。真の処置効果は均一
ATE_true = 2.0
Y = 1.0 + ATE_true * X + 3.0 * C**2 + rng.normal(0, 1.0, size=n)

df = pd.DataFrame({"Y": Y, "X": X, "C": C})

# (1) 素朴比較(調整なし)
naive = Y[X == 1].mean() - Y[X == 0].mean()

# (2) 線形回帰調整: C を1次でしか入れない(= 関数形の誤特定)
beta_linear = smf.ols("Y ~ X + C", data=df).fit().params["X"]

# (3) 正しい関数形: C の2乗項まで入れる
beta_quad = smf.ols("Y ~ X + C + I(C**2)", data=df).fit().params["X"]

print(f"真の ATE                : {ATE_true:.3f}")
print(f"(1) 素朴比較            : {naive:.3f}")
print(f"(2) 線形回帰調整 Y~X+C  : {beta_linear:.3f}")
print(f"(3) 正しい関数形 +C^2   : {beta_quad:.3f}")
print(f"E[C^2|X=1]={ (C[X==1]**2).mean():.3f}, E[C^2|X=0]={ (C[X==0]**2).mean():.3f}")

実行すると次のように印字される。

真の ATE                : 2.000
(1) 素朴比較            : 7.127
(2) 線形回帰調整 Y~X+C  : 7.129
(3) 正しい関数形 +C^2   : 2.009
E[C^2|X=1]=2.247, E[C^2|X=0]=0.539

出力の意味:素朴比較は 7.127 と真値 2.0 を大きく上回る(処置群は C2C^2 が大きい個体に偏り、C2C^2YY を押し上げる正のバイアス:E[C2X=1]=2.25E[C^2\mid X{=}1]=2.25E[C2X=0]=0.54E[C^2\mid X{=}0]=0.54)。ところが CC を入れて「調整」した線形回帰も 7.129 とほとんど変わらない。なぜか。CC は2乗で YY に効くため、CC1次項と YY はほぼ無相関(E[C]=0E[C]=0 なので Cov(C,Y)0\text{Cov}(C,Y)\approx0)で、線形回帰は CC をほぼ無視してしまう。交絡の効き方(C2C^2)が直線でない限り、CC を1次で入れても残差交絡は残ったままなのだ。C2C^2 項まで入れて初めて 2.009 と真値が回収できる。

下のコードはこの理由を可視化する(実行は任意)。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import statsmodels.formula.api as smf

rng = np.random.default_rng(42)
n = 4000
C = rng.uniform(-2, 2, size=n)
prop = 1.0 / (1.0 + np.exp(-2.0 * (C**2 - 1.3)))
X = rng.binomial(1, prop)
Y = 1.0 + 2.0 * X + 3.0 * C**2 + rng.normal(0, 1.0, size=n)
df = pd.DataFrame({"Y": Y, "X": X, "C": C})

grid = np.linspace(-2, 2, 100)
lin = smf.ols("Y ~ X + C", data=df).fit()
quad = smf.ols("Y ~ X + C + I(C**2)", data=df).fit()
pred_lin = lin.params["Intercept"] + lin.params["C"] * grid
pred_quad = quad.params["Intercept"] + quad.params["C"] * grid + quad.params["I(C ** 2)"] * grid**2

fig, ax = plt.subplots(figsize=(7, 4.5))
ax.scatter(C[X == 0], Y[X == 0], s=6, alpha=0.3, label="対照群 X=0", color="tab:blue")
ax.scatter(C[X == 1], Y[X == 1], s=6, alpha=0.3, label="処置群 X=1", color="tab:orange")
ax.plot(grid, pred_lin, color="red", lw=2.5, label="線形フィット(誤特定)")
ax.plot(grid, pred_quad, color="green", lw=2.5, ls="--", label="2次フィット(正しい)")
ax.set_xlabel("交絡 C")
ax.set_ylabel("結果 Y")
ax.set_title("交絡が2乗で効く: 線形フィットは曲線を捉えられない")
ax.legend(fontsize=9)
fig.tight_layout()
plt.show()

得られる図では、データが U字型に並び(処置群=オレンジが両端の高 C2C^2 領域に偏る)、線形フィット(赤)はほぼ水平で曲線を全く捉えていないのに対し、2次フィット(緑破線)は U字に沿う。線形回帰が交絡を塞げない理由が一目で分かる。


3. なぜこの仮定が要るのか(直観)

回帰調整が正しく働くには、暗黙のうちに2つの条件が要る。

  1. 関数形の正しさ(本節の主題)E[YX,C]E[Y\mid X,C]CC への依存を正しくモデル化していること。上の例のように非線形なら、線形項だけでは残差交絡が残る。
  2. 効果の均一性:処置効果が CC に依らず一定であること。効果が CC に依存する(効果修飾)と、Y=α+τX+βCY = \alpha + \tau X + \beta^\top Cτ\tau は、処置群・対照群の CC 分布で重みづけされた量に偏り、母集団 ATE とずれる。
  3. 共通サポート(正値性):処置群と対照群の CC 分布が重なっていること。重ならない領域では回帰が外挿で値を埋め、データではなくモデルの形が結論を決める。

線形回帰が「ダメ」なのではない。真の関数形を知っていれば(あるいは2次・交互作用・スプラインで十分柔軟に近似すれば)回帰調整は一致推定量になる。問題は、現実には真の関数形を知らないこと。だからこそ「処置の確率」だけをモデル化すればよい傾向スコアや、関数形を機械学習に委ねるMLをそのまま使うと因果を誤る理由二重頑健推定AIPWが必要になる。


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


関連ノート