Mímisbrunnr知恵の泉

← 因果推論 一覧

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

📎 前提:バックドア基準と識別 | 識別の仮定 | 傾向スコア

要点(BLUF)


1. 概念:重みで疑似母集団を作る

傾向スコアでは層別・マッチングで「傾向スコアの近い人どうし」を比べた。IPW は別のやり方で同じ交絡を消す。処置を受けにくかった人ほど重く、受けやすかった人ほど軽く数え直すのだ。

処置群のある個体の傾向スコアが e=0.2e=0.2 なら、その人は「自分のような共変量を持つ5人に1人しか処置されない」希少な存在。重み 1/0.2=51/0.2=5 を与えて5人分として数えれば、観測されなかった同類を埋め合わせ、共変量の偏りが相殺される。


2. 識別:なぜ不偏になるか

IPW(Horvitz–Thompson 型)の ATE 推定量は

τ^HT=1ni=1nXiYie^(Ci)1ni=1n(1Xi)Yi1e^(Ci)\hat\tau_{\mathrm{HT}} = \frac{1}{n}\sum_{i=1}^{n}\frac{X_i Y_i}{\hat e(C_i)} - \frac{1}{n}\sum_{i=1}^{n}\frac{(1-X_i)Y_i}{1-\hat e(C_i)}

第1項が E[Y(1)]E[Y(1)] に一致することを示そう。識別の仮定の条件付き交換可能性 Y(1)XCY(1)\perp X\mid C を使うと、CC で条件づけた期待値は

E ⁣[XYe(C)|C]=E[XC]E[Y(1)C]e(C)=e(C)E[Y(1)C]e(C)=E[Y(1)C]E\!\left[\frac{X\,Y}{e(C)}\,\middle|\,C\right] = \frac{E[X\mid C]\,E[Y(1)\mid C]}{e(C)} = \frac{e(C)\,E[Y(1)\mid C]}{e(C)} = E[Y(1)\mid C]

となり、外側で CC について平均すれば E[Y(1)]E[Y(1)]。同様に第2項は E[Y(0)]E[Y(0)]。差し引きが ATE。ポイントは、重み付けの分母に現れる e(C)e(C) が、X=1X=1 となる確率 e(C)e(C) とちょうど打ち消し合うことだ。ここでも正値性 e(C)>0e(C)>0(と 1e(C)>01-e(C)>0)が分母として効いている。

安定化重み

素の重み 1/e1/e は変動が大きく分散が膨らみやすい。安定化重み (stabilized weights) は分子に周辺処置確率を掛けて変動を抑える。

swi=XiP(X=1)e^(Ci)+(1Xi)P(X=0)1e^(Ci)sw_i = X_i\,\frac{P(X{=}1)}{\hat e(C_i)} + (1-X_i)\,\frac{P(X{=}0)}{1-\hat e(C_i)}

推定対象(ATE)は変えずに重みの散らばりだけを小さくするので、分散が下がる。実装では分母を重みの総和で割る**自己正規化(Hájek 型)**と組み合わせるのが定番。


3. 実証:効果の回収と、正値性が苦しいときの分散爆発

真の効果 ATE=2.0\text{ATE}=2.0 を仕込んだデータで、(1) 正値性に余裕がある場合と (2) 正値性ギリギリ(強い交絡で ee が 0/1 に張り付く)場合を、200回反復で比較する。

import warnings
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
from sklearn.linear_model import LogisticRegression

warnings.filterwarnings("ignore")


# === IPW で ATE を回収。正値性が苦しいと重みが暴れ分散が爆発することを示す ===
def estimate_ipw(confound_strength, seed):
    rng = np.random.default_rng(seed)
    n = 2000
    X1 = rng.normal(0, 1, size=n)
    # confound_strength を上げると e(x) が 0/1 に張り付く(正値性が苦しい)
    prop = 1.0 / (1.0 + np.exp(-confound_strength * X1))
    T = rng.binomial(1, prop)
    ATE_true = 2.0
    Y = 1.0 + ATE_true * T + 2.0 * X1 + rng.normal(0, 1, size=n)
    e = LogisticRegression().fit(X1.reshape(-1, 1), T).predict_proba(X1.reshape(-1, 1))[:, 1]
    # IPW (Horvitz-Thompson)
    ht = (T * Y / e).mean() - ((1 - T) * Y / (1 - e)).mean()
    # 安定化重み(分子に周辺処置確率 P(T))+ 自己正規化(Hajek)
    p_treat = T.mean()
    sw1 = T * p_treat / e
    sw0 = (1 - T) * (1 - p_treat) / (1 - e)
    stabilized = (sw1 * Y).sum() / sw1.sum() - (sw0 * Y).sum() / sw0.sum()
    max_weight = np.maximum(T / e, (1 - T) / (1 - e)).max()
    return ht, stabilized, max_weight


def run_many(confound_strength):
    ht, sw, mw = [], [], []
    for seed in range(200):
        a, b, c = estimate_ipw(confound_strength, seed)
        ht.append(a); sw.append(b); mw.append(c)
    return np.array(ht), np.array(sw), np.array(mw)


ht_n, sw_n, mw_n = run_many(0.8)   # 正値性に余裕
ht_t, sw_t, mw_t = run_many(4.0)   # 正値性ギリギリ

print("真の ATE = 2.000   (200回反復の平均と標準偏差)\n")
print("--- 正値性に余裕 (係数0.8) ---")
print(f"IPW(HT)    平均 {ht_n.mean():.3f}  標準偏差 {ht_n.std():.3f}")
print(f"安定化重み 平均 {sw_n.mean():.3f}  標準偏差 {sw_n.std():.3f}")
print(f"最大重みの中央値 {np.median(mw_n):.1f}")
print("\n--- 正値性ギリギリ (係数4.0) ---")
print(f"IPW(HT)    平均 {ht_t.mean():.3f}  標準偏差 {ht_t.std():.3f}")
print(f"安定化重み 平均 {sw_t.mean():.3f}  標準偏差 {sw_t.std():.3f}")
print(f"最大重みの中央値 {np.median(mw_t):.1f}")

# 推定値のばらつきを可視化
fig, ax = plt.subplots(figsize=(7, 4))
bins = np.linspace(0, 5, 40)
ax.hist(ht_n, bins=bins, alpha=0.6, label="正値性に余裕 (係数0.8)", color="tab:blue")
ax.hist(ht_t, bins=bins, alpha=0.6, label="正値性ギリギリ (係数4.0)", color="tab:red")
ax.axvline(2.0, color="black", ls="--", label="真の ATE = 2.0")
ax.set_xlabel("IPW(Horvitz-Thompson)推定値")
ax.set_ylabel("頻度")
ax.set_title("正値性が苦しいと IPW 推定値が大きくばらつく")
ax.legend(fontsize=9)
fig.tight_layout()
plt.show()

実行結果は次の通り。

真の ATE = 2.000   (200回反復の平均と標準偏差)

--- 正値性に余裕 (係数0.8) ---
IPW(HT)    平均 2.006  標準偏差 0.061
安定化重み 平均 2.008  標準偏差 0.061
最大重みの中央値 10.4

--- 正値性ギリギリ (係数4.0) ---
IPW(HT)    平均 2.200  標準偏差 1.078
安定化重み 平均 2.495  標準偏差 0.672
最大重みの中央値 165.6

出力の意味:正値性に余裕があるとき(上段)、IPW は平均 2.006 と真値をほぼ当て、標準偏差も 0.061 と小さい。ところが交絡を強めて ee が 0/1 に張り付くと(下段)、最大重みの中央値が 10 → 166 へと跳ね上がり、HT 推定の標準偏差は 0.061 → 1.078 へ約18倍に爆発する。安定化重みは標準偏差を 1.078 → 0.672 へ大きく下げてくれるが、平均は 2.495 と真値からずれたまま。つまり安定化は分散を抑える対症療法であって、正値性が本質的に破れた領域のバイアスまでは救えない。ヒストグラムでも、余裕がある場合(青)は 2.0 付近に鋭く集中するのに対し、ギリギリ(赤)は 0〜4超に広く散らばり右に偏る。


4. なぜ正値性が要るのか(直観)

IPW の重みは 1/e1/eee が 0 に近い個体は重みが無限大に発散する。これは「その共変量を持つ人はほとんど処置されない=処置群の同類が観測されない」状況で、観測されない反事実を1〜2人の希少なサンプルから無理やり外挿していることを意味する。少数の極端な重みが推定全体を支配し、分散が発散する。

これは識別の仮定正値性が崩れている直接の症状だ。重みのトリミング(上限でカット)や安定化はその場しのぎにはなるが、本質的には「データにない比較を作れない」という識別の限界。正値性は推定技術で埋められないことを、この爆発が教えてくれる。


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


関連ノート