この記事は、交絡らしき共変量が 200 列もあるデータで「処置を強めると、結果はどれだけ動くのか」を推定する回です。機械学習に処置と共変量をまとめて渡すと、予測のための縮み(正則化)が処置の係数に紛れ込みます。処置と結果をそれぞれ機械学習で予測し、残差同士を回帰する Double ML を、真の効果 0.5 を握った合成データで組み立てます。
登場人物
遠藤顧問: データ分析の社外顧問。答えを言わずに問いで返す/さくら: データアナリスト 1 年目。数字を出すのは速いが、相関を因果と読み違える
1. 1 文で言うと
1 文で言うと
Double ML(DML)は、処置 $w$ と結果 $y$ をそれぞれ機械学習で $X$ から予測して残差を取り、残差同士の単回帰で効果 θ を読む推定法です。Day 16 の FWL の「残差を作る回帰」を機械学習に替えたもので、交差適合と組にすると、機械学習の正則化が係数に漏れるバイアスを打ち消せます。
- 今日の数字: 機械学習に丸ごと任せた処置の係数は 0.581 で、真値 0.5 に対して 100 回中 100 回が上振れしました。
2. 今日の問い
今日の問い
交絡らしき共変量が200列ある。素のOLSに全部積むのは心もとない。予測が得意な機械学習に交絡の後始末を任せたい。
では、機械学習が推定した「処置の係数」を、そのまま因果効果と読んでよいか?
答えは「そのままでは読めない」です。機械学習は予測を当てるために、係数を歪める癖(正則化)を意図的に持っています。今日のゴールは、この癖がなぜ因果推定に漏れるのかを機構で言語化し、それを打ち消す2つの手当て、残差化と交差適合をコードで組むことです。組み上がったものがDMLで、正体はDay 16のFWL定理の現代版だと分かります。
読み終えたら、機械学習の係数を効果と読むと上振れする理由と、Double ML が残差化と交差適合でそれを打ち消す仕組みを説明できます。
答えの中心は 3.2 の「残差×残差」です。3.1 で正則化バイアスの機構を押さえ、4 で素朴な読み出しと DML、交差適合の有無を同じ合成データで確かめます。前の回から使うのは次の 2 つです。
- Day 16(回帰とFWL): 回帰の係数は、統制変数で残差化した残差同士の単回帰と一致する
- Day 7(傾向スコアとIPW): 処置が 2 値なら、処置を X で予測する部分 m(X) は傾向スコアそのもの
3. 概念
先に、手元の道具との違いを置きます。A/B テストなら、処置を無作為に割り付けるので、共変量の違いは平均して消え、群の差がそのまま効果になります。回帰や予測モデルなら、処置と共変量 200 列をまとめて渡し、処置の係数を読みたくなります。今日の場面は、割り当てが無作為ではなく、交絡らしき共変量が 200 列あります。機械学習は予測のために係数を縮める癖をもつので、その係数は予測には良くても、効果の読み出しには向きません。DML は、予測と読み出しの役を分けます。
3.1 正則化バイアス:予測のための縮みが、係数への漏れになる
機械学習が予測に強い理由のひとつは、わざとバイアスを入れることです。Lassoは係数をゼロへ縮め、木は枝を刈り、ブースティングは早めに止まる。分散を減らして予測誤差の合計を下げる、理にかなった設計です。ところがこの縮みは、係数を因果として読んだ瞬間に毒になります。
今日の主役の1人目を「素朴プラグイン」と呼びます。処置 $w$ と共変量 $X$ をまとめて機械学習に渡して $y$ を予測させ、出てきた $w$ の係数(や $w$ を動かしたときの予測差)を効果として読む方法です。何がまずいのか。Lassoで言えば、罰則は交絡因子の係数も縮めます。縮んだ分の交絡は消えてなくなるわけではなく、モデルの説明し残しとして残る。そして交絡因子は定義上 $w$ と相関しているので、説明し残した交絡の受け皿に、罰則のかかっていない方向で最も相関の高い $w$ の係数がなるのです。交絡を消すために入れたはずのXの係数が縮んだツケを、θの推定値が肩代わりする。これが正則化バイアスです。
たちが悪いのは、このズレが偶然の誤差ではなく系統的なバイアスであることです。標本を増やしても、機械学習のニュイサンス推定はOLSよりゆっくりとしか真に近づかないため、バイアスは信頼区間の縮む速さより遅くしか消えません。つまり、標本が増えるほど「狭い区間で自信満々に間違える」方向へ進みます。4.2 の Fig 5 で、分布ごと真値から外れる様子を見ます。
3.2 DML:残差×残差、FWLの機械学習版
この小節が今日の主役です。残差で効果を読む式を組み、そのあとで、なぜ正則化バイアスが消えるのかを Neyman 直交性として言葉で押さえます。
3.1 の漏れは、機械学習 1 本に「予測」と「効果の読み出し」の 2 役を兼ねさせたことから来ていました。予測のためには係数を縮めたい、効果を読むためには縮めたくない。それなら役を分ければよいのです。機械学習には $X$ からの予測だけを任せ、処置 $w$ からも結果 $y$ からも「$X$ で説明できる分」を引いてしまう。残った揺れ同士で効果を測れば、縮みが効果の読み出しに直接は入り込みません。この発想を式にします。
処方箋はDay 16で伏線を張ったとおりです。部分線形モデル
$$
y = \theta w + g(X) + \varepsilon, \qquad w = m(X) + v
$$
を考えます。$g(X)$ が結果側、$m(X)$ が処置側のニュイサンス(迷惑関数)です。処置が2値なら $m(X)$ は傾向スコア $e(X)$(Day 7)そのもので、残差化は傾向スコアの親戚にあたります。今日は仕組みが見やすいように処置を連続量(投資の強度)にしますが、考え方は同じです。
式は 2 本で 1 組で、下の式から読みます。この式は 4 つに分けて読みます。
- $w = m(X) + v$ は、処置 $w$ を「$X$ から予測できる部分 $m(X)$」と「$X$ では説明できない揺れ $v$」に分けた式です。
- 上の式は、結果 $y$ を「効果 $\theta$ × 処置 $w$」「$X$ から結果へ来る部分 $g(X)$」「ノイズ $\varepsilon$」に分けています。
- $\theta$ は全員に共通の 1 つの数で、$g$ と $m$ はどんな形でもかまいません。ここが機械学習に任せる部分です。
- 推定では、$w$ から $X$ による予測 $\hat m(X)$ を引いた残差 $\tilde w$($v$ の推定)と、$y$ から $X$ だけによる予測 $\hat\ell(X)$ を引いた残差 $\tilde y$ を作り、$\tilde y$ を $\tilde w$ に単回帰した傾きを $\hat\theta$ と読みます。
式に分けたご利益は、機械学習の仕事と効果の読み出しを切り離せることです。$g$ と $m$ は形を問わないので、Lasso でも勾配ブースティングでも、予測の得意な道具をそのまま使えます。そして $\theta$ は機械学習の係数からは読まず、残差同士の傾きから読む。予測のための縮みは $\hat m$ と $\hat\ell$ の中に閉じ込められ、$\theta$ の読み出しに直接は入り込みません。
FWL定理(Day 16)は「重回帰の係数=統制変数で残差化した残差同士の単回帰」でした。close_collegeでは educ の係数 0.0746 が残差×残差の単回帰と差 1.5e-16 で厳密に一致しましたね。DMLはこの手順の「残差を作る回帰」を、任意の機械学習に置き換えたものです。
なぜ残差×残差だと正則化バイアスが消えるのか。ここが今日いちばんの難所、Neyman直交性です。数式は原典に譲り、直感だけ言葉にします。
素朴プラグインでは、$\hat g$ の誤りがそのまま1次でθの推定誤差に乗ります。ニュイサンスを1割間違えれば、θもそれに比例して動く構造です。一方、残差×残差の推定量では、θの誤差に効くのは「$\hat m$ の誤り × $\hat\ell$ の誤り」の積だけになります。片方のニュイサンスを少しだけ間違えた状況を想像してください。その間違いは、もう片方の残差(平均ゼロで、間違いの方向と無相関)と掛け合わされて消えます。つまりどちらか一方を少し間違えても、1次では推定値が動かない。動くのは両方の誤りの積という2次の項だけで、それぞれが並の精度でも積は十分速く小さくなります。並の予測器2本を掛け算で1本の高精度な推定量に変える設計、と言ってもいいと思います。
ただしこの理屈には前提がひとつあります。残差を作るモデルが、残差化される当のデータを暗記していないことです。ここを守る仕掛けが交差適合で、4.3 で壊してから直します。
4. 手を動かす
4.1 素朴プラグインは分布ごと上振れる
まず高次元の交絡を合成します。共変量200列のうち5列だけが本物の交絡で、wにもyにも係数0.5で効きます。真の効果は θ=0.5。列がここまで増えると、実務ではまず正則化つきのモデルに手が伸びます。その手癖のまま処置の係数を読むと何が起きるかを測ります。
コード
import numpy as np
from sklearn.linear_model import LassoCV
rng = np.random.default_rng(24)
N, P = 2000, 200
X = rng.normal(0, 1, (N, P)) # 共変量200列
beta = np.zeros(P)
beta[:5] = 0.5 # うち5列だけが交絡(wにもyにも効く)
w = X @ beta + rng.normal(0, 1, N) # 処置の強度(例:点検投資)
y = 0.5 * w + X @ beta + rng.normal(0, 1, N) # 真の効果 θ = 0.5
# (1) 何も調整しない単回帰
print("単回帰 y ~ w の傾き = %.3f" % np.polyfit(w, y, 1)[0])
# (2) 素朴プラグイン:Lasso に w と X をまとめて渡し、w の係数を読む
plugin = LassoCV(cv=3, random_state=0, alphas=30).fit(np.column_stack([w, X]), y)
print("素朴プラグインの θ = %.3f (真値 0.5)" % plugin.coef_[0])
print("交絡5列の係数 =", np.round(plugin.coef_[1:6], 2), "(真値 0.5)")
出力
単回帰 y ~ w の傾き = 1.059
素朴プラグインの θ = 0.581 (真値 0.5)
交絡5列の係数 = [0.44 0.38 0.39 0.41 0.43] (真値 0.5)
単回帰の1.06は交絡まみれなので論外として、注目は素朴プラグインの 0.581 です。200列をちゃんとモデルに入れ、交差検証で罰則も選んだのに、真値0.5から系統的に上振れしています。3行目が種明かしで、交絡5列の係数は0.38〜0.44と、真値0.5からそれぞれ縮められています。縮んだ量は5列合計でおよそ0.45。交絡1列あたりの $w$ との共分散が0.5、$w$ の分散が2.25なので、ざっくり 0.45 × 0.5 / 2.25 ≒ 0.10 が $w$ の係数へ流れ込む勘定です。実際の上振れ+0.08とほぼ合います(θ自身にも罰則がかかって少し縮むぶん、勘定ぴったりにはなりません)。3.1 の「縮んだツケの肩代わり」が、そのまま数字で見えました。
4.2 残差×残差の手組みDML、FWLの絵が戻ってくる
同じデータをDMLで推定します。やることは3手順です。wをXから予測して残差を取る、yをXから予測して残差を取る、残差×残差で単回帰する。Day 16の手組みFWLの「回帰」を LassoCV に置き換えただけです。あわせて、後半の主題になる交差適合(ここでは2分割)も先に仕込んでおきます。半分のデータで学んだモデルで、残り半分を残差化する構造です。
コード
from sklearn.model_selection import KFold
def dml_theta(X, w, y, seed=0):
"""手組みDML:2分割の交差適合で残差を作り、残差×残差の傾きを返す"""
rw, ry = np.zeros(len(w)), np.zeros(len(y))
for tr, te in KFold(2, shuffle=True, random_state=seed).split(X):
rw[te] = w[te] - LassoCV(cv=3, random_state=0, alphas=30).fit(X[tr], w[tr]).predict(X[te])
ry[te] = y[te] - LassoCV(cv=3, random_state=0, alphas=30).fit(X[tr], y[tr]).predict(X[te])
return (rw @ ry) / (rw @ rw)
print("手組みDMLの θ = %.3f (真値 0.5)" % dml_theta(X, w, y, seed=24))
出力
手組みDMLの θ = 0.510 (真値 0.5)
素朴プラグインの0.581が 0.510 まで戻りました。使っている道具はまったく同じ LassoCV です。違うのは読み出し方の設計だけ。下の Fig 4b が、200列の交絡を2次元に還元した残差×残差の散布図で、Day 16のFWLの絵がそのまま帰ってきています。
1回の比較では偶然かもしれないので、データ生成から100回繰り返して分布で見ます。
コード
def make_data(seed):
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (N, P))
w = X @ beta + rng.normal(0, 1, N)
y = 0.5 * w + X @ beta + rng.normal(0, 1, N)
return X, w, y
naive_mc, dml_mc = [], []
for r in range(100): # 100回の反復(30秒ほどかかります)
Xr, wr, yr = make_data(r)
naive_mc.append(LassoCV(cv=3, random_state=0, alphas=30)
.fit(np.column_stack([wr, Xr]), yr).coef_[0])
dml_mc.append(dml_theta(Xr, wr, yr, seed=r))
print("素朴プラグイン: 平均 %.3f ± %.3f(100回中%d回が真値より上)"
% (np.mean(naive_mc), np.std(naive_mc), (np.array(naive_mc) > 0.5).sum()))
print("手組みDML : 平均 %.3f ± %.3f" % (np.mean(dml_mc), np.std(dml_mc)))
出力
素朴プラグイン: 平均 0.563 ± 0.023(100回中100回が真値より上)
手組みDML : 平均 0.512 ± 0.023
ばらつき(±0.023)は両者ほぼ同じで、違いはバイアスだけです。素朴プラグインは平均0.563、真値から約2.7標準偏差ぶん離れたところに分布ごと引っ越していて、100回中100回が上振れ。この分布から計算した信頼区間は、狭い顔をして真値を外し続けます。手組みDMLの平均は 0.512 で、分布が真値0.5を囲みます。残る+0.012は 3.2 で言った「両方の誤りの積」の有限標本での残りで、標本を増やせば区間より速く縮んでいく性質のズレです。
4.3 交差適合を外すと、残差は信号ごと消える
3.2 の最後に置いた前提を、今度はわざと壊します。交差適合を省いて、全データで当てはめたモデルで、その同じデータを残差化したらどうなるか。極端な思考実験から入ると分かりやすいです。1近傍法(自分と同じ点を返すモデル)で残差を作れば、残差は全点で厳密にゼロ。残差×残差の回帰は0/0になり、何も推定できません。過学習はこの劣化版で、モデルが交絡だけでなくノイズまで暗記し、残差から本来残るべき信号 $v$ と $\varepsilon$ を削り取ってしまいます。
今度は非線形のニュイサンス(sinとtanh)を仕込み、学習器も勾配ブースティングに替えて確かめます。
出力を開く前に予想してください。交差適合なしで推定した θ は、真値 0.5 の近くに残るでしょうか、それとも大きく外れるでしょうか。
コード
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import cross_val_predict
rng = np.random.default_rng(1)
n = 1000
Z = rng.normal(0, 1, (n, 10)) # 共変量10列(今度は非線形に効く)
m = np.sin(2 * Z[:, 0]) + 1.5 * np.tanh(Z[:, 1]) # 処置側のニュイサンス m(x)
g = 2 * np.sin(2 * Z[:, 0]) + 3.0 * np.tanh(Z[:, 1]) # 結果側のニュイサンス g(x)
w2 = m + rng.normal(0, 1, n)
y2 = 0.5 * w2 + g + rng.normal(0, 1, n) # 真の効果 θ = 0.5
def gb():
return HistGradientBoostingRegressor(max_iter=500, random_state=0)
# (1) 交差適合なし:自分のデータで当てはめたモデルで、自分を残差化する
rw = w2 - gb().fit(Z, w2).predict(Z)
ry = y2 - gb().fit(Z, y2).predict(Z)
print("交差適合なし: θ = %.3f 処置残差の分散 = %.4f(本来は1.0)"
% ((rw @ ry) / (rw @ rw), rw.var()))
# (2) 5分割の交差適合:自分以外のfoldで学んだモデルで残差化する
kf = KFold(5, shuffle=True, random_state=0)
rw = w2 - cross_val_predict(gb(), Z, w2, cv=kf)
ry = y2 - cross_val_predict(gb(), Z, y2, cv=kf)
print("交差適合あり: θ = %.3f 処置残差の分散 = %.3f"
% ((rw @ ry) / (rw @ rw), rw.var()))
交差適合なしでは、処置残差の分散が 0.0001 まで潰れています。設計上、残差には分散1.0のノイズ $v$ が残るはずなので、ブースティングがノイズをほぼ完全に暗記した、ということです。残った0.01%の屑どうしの比を取った推定値が1.523で、これはもう何も測っていません。実際、シードを変えて同じ推定を16回繰り返すと、交差適合なしは0.10から1.52まで暴れます(Fig 7a)。たまたま0.5に近い値が出ることもあるのが、かえって怖いところです。交差適合ありは0.43〜0.59に収まり、真値の周りに素直に集まります。
分割の仕組みはこうです。fold Bの残差はfold Aで学んだモデルで作るので、どのモデルも残差化する相手のデータを見ていません。それでいて、全データが最終的に残差として使われるので、サンプルを捨てる無駄もありません。
最後に実務版です。econml の LinearDML は、今日手組みした「MLで2本残差化 → 残差×残差」をそのまま実装していて、cv 引数が交差適合の分割数、X=None は「効果は定数」の指定です(ここに共変量を渡すと効果の異質性のモデル化に進みます。Day 25の話です)。
コード
from econml.dml import LinearDML
for cv in [1, 5]:
est = LinearDML(model_y=gb(), model_t=gb(), cv=cv, random_state=0)
est.fit(y2, w2, X=None, W=Z)
lo, hi = est.effect_interval()
print("LinearDML cv=%d: θ = %.3f 95%%CI [%.3f, %.3f]"
% (cv, est.effect()[0], lo[0], hi[0]))
出力
LinearDML cv=1: θ = 1.523 95%CI [0.538, 2.509]
LinearDML cv=5: θ = 0.536 95%CI [0.466, 0.607]
cv=1(交差適合なし)は手組みの1.523をそのまま再現し、区間も[0.538, 2.509]と間延びした上に真値を含みません。cv=5は 0.536、95%CI [0.466, 0.607] で真値0.5を狭く囲みます。DMLの漸近理論(普通の $\sqrt{n}$ の信頼区間が使えること)は、直交性と交差適合の2つセットで初めて成立します。片方でも欠くと、点推定だけでなく区間も信用できなくなる、というのが今日の締めの教訓です。
成り立つ場合と成り立たない場合
| 仮定(残差を作るモデルが相手を見ていない) | データに出るもの | 今日の数字の読み方 |
|---|---|---|
| 成り立つ(cv=5) | 処置残差の分散が 1.291 で、本来の 1.0 より少し大きい | θ = 0.536、95%CI [0.466, 0.607] が真値 0.5 を囲み、効果と読める |
| 成り立たない(cv=1) | 処置残差の分散が 0.0001 まで潰れる | θ = 1.523 は何も測っておらず、区間 [0.538, 2.509] も真値を含まない |
5. 判断の基準
DML の推定値を因果効果として報告してよいか、報告するなら何を確かめるか。問いを 3 つに絞りました。上から順にたどり、最初に右へ出たところが、いまやることです。
- Q1 は仮定の話で、データからは検証できません。 DML は交絡を自動で見つけてはくれません。消してくれるのは「共変量に入れた変数を経由するバックドア」だけで、非交絡性が仮定であることは Day 6 から 1 ミリも変わっていません。何を入れるかはバックドア基準(Day 11)で決め、合流点や処置後の変数を 200 列に混ぜれば、DML は高精度にバイアスを推定するだけです。隠れ交絡への耐性は感度分析(Day 9)で別途語ります。
-
Q2 と Q3 はデータで確かめられる診断です。 Q2 は 4.3 のとおりで、交差適合を外すと処置残差の分散が 0.0001 まで潰れ、推定値は 1.523 へ暴走しました。econml なら
cvを 2 以上にします。Q3 はニュイサンスの出来で、ここは fold の外での予測精度のような予測の指標で選んでかまいません。ただし「予測精度が高いモデルほど、因果推定も正確」ではありません。4.1 と 4.2 で使った道具は同じLassoCVで、差を生んだのは精度ではなく係数の読み出し方の設計でした。正則化バイアスは R² や RMSE にいっさい顔を出さないので、予測指標でモデルを磨いても検出できません。ニュイサンスのモデル選択は予測基準で、読み出しは直交化した推定式で、と役割分担で覚えるのが安全です。 - 全部通ったら報告へ。 交差適合つきの点推定に 95%CI を添えます(4.3 の LinearDML cv=5 なら 0.536、[0.466, 0.607])。ただし $\theta$ は「効果は 1 つ」を仮定した要約です(下の注記)。
注記 DML の $\theta$ は「効果は 1 つ」を仮定した平均です。部分線形モデルは全員に同じ $\theta$ が効く書き方で、効果が人によって違うとき、$\hat\theta$ は処置残差の分散で重みづけた加重平均になります。Day 16 で見た「回帰=分散加重平均」の親戚です。誰に効くかが論点なら、メタラーナー(Day 23)や Causal Forest(Day 25)の CATE 系へ進みます。
自分の仕事に当てるなら、次の問いから始められます。いま機械学習の係数や寄与を効果として報告している分析のうち、残差を作るモデルが、残差化する相手のデータを見てしまっているものはどれでしょうか。
6. 確認問題
問 1(自分の言葉で説明する) Double ML が、機械学習の係数をそのまま効果と読む方法より偏りにくい理由を、本文を見ずに 2 文で説明してください。
答えと解説
模範解答: 機械学習には処置と結果を X から予測する役だけを任せ、効果 θ は残差同士の傾きから読むので、予測のための縮みが効果の読み出しに直接は入り込みません。残差は交差適合で、残差化する相手のデータを見ていないモデルから作るので、暗記によって信号が消えることもありません。
次の 2 点のどちらかが抜けたら不十分です。
- θ は機械学習の係数ではなく、処置と結果の残差同士の傾きから読むこと
- 残差は交差適合で、残差化する相手を見ていないモデルから作ること
詰まったら 3.2 と 4.3 に戻ってください。
問 2(別の場面へ移す) ある小売チェーンの 1,000 店舗で、棚の広さが売上に与える効果を DML で推定します。5 分割の交差適合で、ある 1 つの fold(200 店舗)の残差を作るとき、その残差を作るモデルは何店舗のデータで学習したものでしょうか。
- ア 1,000 店舗。残差化する 200 店舗も含めた全店舗
- イ 800 店舗。残差化する 200 店舗を除いた、ほかの 4 つの fold
- ウ 200 店舗。残差化する fold と同じ店舗
- エ 0 店舗。交差適合では、モデルは学習しない
答えと解説
イ。残差を作るモデルは、残差化する fold を除いた 4 つの fold(200 店舗 × 4 = 800 店舗)で学習します。どの店舗の残差も、その店舗を見ていないモデルから作るので、暗記で信号が消えません。全データが最後は残差として使われるので、捨てる店舗もありません。
- ア(交差適合を外す読み違い): 4.3 の「交差適合なし」はこれで、処置残差の分散が 0.0001 まで潰れました。
- ウ(学習と残差化を同じ fold にする読み違い): 自分と同じ fold で学ぶと、その fold を暗記します。
- エ(学習を省く読み違い): 交差適合は学習を省く仕掛けではなく、学習するデータと残差化するデータを分ける仕掛けです。
問 3(出力を読む) 4.3 で次の出力を得ました。交差適合なしの処置残差の分散 0.0001 から読み取れることとして、正しいものはどれでしょうか。
交差適合なし: θ = 1.523 処置残差の分散 = 0.0001(本来は1.0)
交差適合あり: θ = 0.536 処置残差の分散 = 1.291
ア 処置がほぼ $X$ だけで決まっていて、残差化が完璧に効いた イ 交差適合ありの 1.291 のほうが本来の 1.0 から遠いので、交差適合ありのほうが壊れている ウ 残差の分散が小さいほど推定は精密なので、1.523 のほうが信頼できる エ 勾配ブースティングが自分のデータのノイズ $v$ まで暗記し、残差から本来残るべき信号が消えた
答えと解説
エ。設計上、処置の残差には分散 1.0 のノイズ $v$ が残るはずです。それが 0.0001 まで潰れたのは、自分のデータで当てはめたモデルが $v$ まで暗記したからで、残った屑どうしの比 1.523 はもう何も測っていません。シードを変えて 16 回繰り返すと、交差適合なしは 0.10 から 1.52 まで暴れます。
ア: データは $w = m(X) + v$ の形で作っていて、$v$ の分散は 1.0 です。$X$ だけで決まってはいません。イ: 1.291 が 1.0 より少し大きいのは、自分を見ていないモデルの予測の外れが残差に加わるぶんで、暗記による消滅とは逆向きです。交差適合ありの推定は 0.536(95%CI [0.466, 0.607])と真値を囲みます。ウ: 分散が潰れた残差は信号ではなく屑で、その比は暴れます(16 シードで 0.10〜1.52)。
7. おわりに
Double ML(DML)は、処置 $w$ と結果 $y$ をそれぞれ機械学習で $X$ から予測して残差を取り、残差同士の単回帰で効果 θ を読む推定法です。Day 16 の FWL の「残差を作る回帰」を機械学習に替えたもので、交差適合と組にすると、機械学習の正則化が係数に漏れるバイアスを打ち消せます。最後に確かめます。Double ML が、機械学習の係数をそのまま効果と読む方法より偏りにくい理由を、本文を見ずに 2 文で言えますか。詰まったら 3.2 と 4.3 に戻ってください。
8. 参考(本棚)
- Chernozhukov et al. (2018) Double/Debiased Machine Learning for Treatment and Structural Parameters。DMLの原典。正則化バイアス・Neyman直交性・交差適合の3点セットはこの論文の骨格
- Robert Osazuwa Ness『Causal AI』。機械学習と因果推論の接続の見取り図で、今日の下敷き
- Matheus Facure『Causal Inference in Python』。残差化(直交化)とDebiasingの実装視点
-
econml ドキュメント(PyWhy)。
LinearDMLの引数と推定量の仕様 - 図はすべて合成データです。真の効果 θ=0.5 と交絡の構造を私たちが握ることで、素朴プラグインの上振れと交差適合の有無を安全に再現しました。
この記事の位置づけ
因果推論を「本を読んだ」で終わらせず、自分の言葉で説明でき、コードで再現できる状態まで落とす 30 日連載の Day 24 です。
図は縦が分析の工程、横が流派です。この記事は「③ 推定する(数字を出す)」の、ML×因果(誰に効くか)の「Double ML」を扱います(図の黒い札)。前提になるのは Day 16(回帰とFWL)・Day 7(傾向スコアとIPW)。ここで覚える考え方や道具は Day 25(Causal Forest) で再登場します。
9. 次回予告(Day 25)
Day 25(Causal Forest)
今日のDMLは、効果を1つの定数θとして推定しました。でもDay 22で見たとおり、実務の問いはしばしば「平均」ではなく「誰に効くか」です。残差化した世界で木を育て、効果の異質性 τ(x) を信頼区間つきで切り出すのが次回の Causal Forest(econml CausalForestDML)です。分割の規準を予測誤差から「効果の差」に替えるところ、そして信頼区間の生命線になる honesty(標本分割)が今日の交差適合と同じ精神であるところまで、手を動かして確かめます。
















![Fig 7b: econml LinearDML(4.3 と同じデータ)の点推定と 95%CI。cv=1(交差適合なし)は 1.523 [0.538, 2.509] で真値 0.5 を含まず、cv=5 は 0.536 [0.466, 0.607] で真値を狭い区間で囲む](https://qiita-user-contents.imgix.net/https%3A%2F%2Fakiralab.github.io%2Fqiita-images%2Fimages%2Fday24%2Ffig7b_crossfit_econml.png?ixlib=rb-4.1.1&auto=format&gif-q=60&q=75&s=44b0dbae0941db30921d1cf7dee090d7)

![対比の図: 題は「交差適合なしは、真値を外す」。上は交差適合あり(cv=5)で θ は 0.536、95%CI [0.466, 0.607] は真値 0.5 を囲む。下は交差適合なし(cv=1)で θ は 1.523、処置残差の分散は 0.0001、区間 [0.538, 2.509] は真値を含まない](https://qiita-user-contents.imgix.net/https%3A%2F%2Fakiralab.github.io%2Fqiita-images%2Fimages%2Fday24%2Ffig_contrast.png?ixlib=rb-4.1.1&auto=format&gif-q=60&q=75&s=b919a19e74f138705eb4ee897ce81aa4)


