1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

因果推論 Day 24/全30回 Double ML、機械学習の当てはめ癖を打ち消す

1
Last updated at Posted at 2026-09-08

この記事は、交絡らしき共変量が 200 列もあるデータで「処置を強めると、結果はどれだけ動くのか」を推定する回です。機械学習に処置と共変量をまとめて渡すと、予測のための縮み(正則化)が処置の係数に紛れ込みます。処置と結果をそれぞれ機械学習で予測し、残差同士を回帰する Double ML を、真の効果 0.5 を握った合成データで組み立てます。

登場人物

遠藤顧問: データ分析の社外顧問。答えを言わずに問いで返す/さくら: データアナリスト 1 年目。数字を出すのは速いが、相関を因果と読み違える

依頼の会話: 顧問が共変量 200 列のデータを説明し、さくらに「処置の強さを上げると結果がいくつ動くか」の分析を頼む。さくらの「Lasso に処置ごと全部入れて処置の係数を読む」案に、顧問が「真の効果 0.5 の合成データで練習し、交絡の係数も一緒に見ておく」という観点を添える

冒頭の会話: さくら「200 列ぜんぶ入れて罰則も交差検証で選んで、処置の係数は 0.581 です!」顧問「交絡の 5 列の係数は、いくつだった?」さくら「0.38〜0.44、真値の 0.5 よりどれも縮んでます……」顧問「縮んだぶんの交絡は消えたと思う? その 0.581、まだ効果とは呼べない」

冒頭の会話(翌日): データを 100 回作り直して「平均 0.563、ばらつき ±0.023、安定してます」と喜ぶさくらに、顧問が「真値 0.5 より上に出たのは何回?」。答えは 100 回中 100 回。ばらつきではなく、何回やり直しても同じ側に外れるずれで、それを直すのが今日の道具

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.2): 「Double ML とは、一言でいうと「両方を予測して、残差同士で回帰する」推定法です」。板書は、w と y を ML で X から予測・残った揺れ同士の傾きが θ・Day 16 の FWL の ML 版

3.1 の漏れは、機械学習 1 本に「予測」と「効果の読み出し」の 2 役を兼ねさせたことから来ていました。予測のためには係数を縮めたい、効果を読むためには縮めたくない。それなら役を分ければよいのです。機械学習には $X$ からの予測だけを任せ、処置 $w$ からも結果 $y$ からも「$X$ で説明できる分」を引いてしまう。残った揺れ同士で効果を測れば、縮みが効果の読み出しに直接は入り込みません。この発想を式にします。

Fig 1: 式の誕生 4 コマ(2×2)。① ML に丸ごと任せると、Lasso は予測のために交絡 5 列の係数を真値 0.5 から 0.38〜0.44 へ縮める → ② 縮んだぶんの交絡は消えず、w と相関するので w の係数が肩代わりして 0.581 に上振れ → ③ ML には予測だけを任せ、w からも y からも X で説明できる分を引いて残差にする(w − m̂(X) = w̃、y − ℓ̂(X) = ỹ) → ④ 残った揺れ同士の傾きを θ̂ と読み、この読み方に付けた名前が Double ML

処方箋は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 つに分けて読みます。

  1. $w = m(X) + v$ は、処置 $w$ を「$X$ から予測できる部分 $m(X)$」と「$X$ では説明できない揺れ $v$」に分けた式です。
  2. 上の式は、結果 $y$ を「効果 $\theta$ × 処置 $w$」「$X$ から結果へ来る部分 $g(X)$」「ノイズ $\varepsilon$」に分けています。
  3. $\theta$ は全員に共通の 1 つの数で、$g$ と $m$ はどんな形でもかまいません。ここが機械学習に任せる部分です。
  4. 推定では、$w$ から $X$ による予測 $\hat m(X)$ を引いた残差 $\tilde w$($v$ の推定)と、$y$ から $X$ だけによる予測 $\hat\ell(X)$ を引いた残差 $\tilde y$ を作り、$\tilde y$ を $\tilde w$ に単回帰した傾きを $\hat\theta$ と読みます。

Fig 2: 注釈付き数式。上に y = θw + g(X) + ε と w = m(X) + v の 2 本があり、下の式(処置)から読む。記号は上から、θ は知りたい効果で全員に共通の 1 つの数、g(X) は X から結果へ来る部分で形は問わない(ML に任せる)、m(X) は X から予測できる処置の部分(2 値なら傾向スコア、Day 7)、v は X では説明できない処置の揺れで、残差 w̃ はこれを推定したもの。読み下しは「処置を「X で予測できる部分」と「揺れ v」に分ける。θ は、X を除いた揺れ同士の傾きで読む」

式に分けたご利益は、機械学習の仕事と効果の読み出しを切り離せることです。$g$ と $m$ は形を問わないので、Lasso でも勾配ブースティングでも、予測の得意な道具をそのまま使えます。そして $\theta$ は機械学習の係数からは読まず、残差同士の傾きから読む。予測のための縮みは $\hat m$ と $\hat\ell$ の中に閉じ込められ、$\theta$ の読み出しに直接は入り込みません。

中間の会話: 式を音読して「2 本あって、どこから読めば」と止まるさくらに、顧問が「下の式から読んでごらん。v って、w のどんな部分?」。X からは予測できない処置の揺れで、θ はその揺れと y の揺れから読む。g と m は ML に任せ、式は 2 本で 1 組

FWL定理(Day 16)は「重回帰の係数=統制変数で残差化した残差同士の単回帰」でした。close_collegeでは educ の係数 0.0746 が残差×残差の単回帰と差 1.5e-16 で厳密に一致しましたね。DMLはこの手順の「残差を作る回帰」を、任意の機械学習に置き換えたものです。

Fig 3: DML の 3 手順(縦)。① 処置 w を X から ML で予測し、残差 w̃ = w − m̂(X)(X で説明できない w の揺れ)を取る。② 結果 y を X から ML で予測し、残差 ỹ = y − ℓ̂(X) を取る。③ 残差×残差の単回帰で、θ̂ = Σ w̃ỹ / Σ w̃²(4.2 のコードの (rw @ ry) / (rw @ rw))。下の注記は、Day 16 の FWL と同じ絵で、残差を作る回帰を ML に替えただけ

なぜ残差×残差だと正則化バイアスが消えるのか。ここが今日いちばんの難所、Neyman直交性です。数式は原典に譲り、直感だけ言葉にします。

素朴プラグインでは、$\hat g$ の誤りがそのまま1次でθの推定誤差に乗ります。ニュイサンスを1割間違えれば、θもそれに比例して動く構造です。一方、残差×残差の推定量では、θの誤差に効くのは「$\hat m$ の誤り × $\hat\ell$ の誤り」の積だけになります。片方のニュイサンスを少しだけ間違えた状況を想像してください。その間違いは、もう片方の残差(平均ゼロで、間違いの方向と無相関)と掛け合わされて消えます。つまりどちらか一方を少し間違えても、1次では推定値が動かない。動くのは両方の誤りの積という2次の項だけで、それぞれが並の精度でも積は十分速く小さくなります。並の予測器2本を掛け算で1本の高精度な推定量に変える設計、と言ってもいいと思います。

ただしこの理屈には前提がひとつあります。残差を作るモデルが、残差化される当のデータを暗記していないことです。ここを守る仕掛けが交差適合で、4.3 で壊してから直します。

読み違いの図: よくある読み違いは「θ は機械学習の係数から読めばよい」。実際は、θ は残差同士の傾きから読み、ML の係数は予測にだけ使う。上の絵は ML の係数から θ へ太い矢印、下の絵は残差同士の傾きから θ へ太い矢印


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の絵がそのまま帰ってきています。

Fig 4a: 単回帰 y ~ w の散布図と傾き 1.06。共変量200列は放置したままで、傾きは交絡まみれ

Fig 4b: LassoCV で残差化した残差×残差の単回帰。傾き 0.510 ≒ 真値 0.5。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 で言った「両方の誤りの積」の有限標本での残りで、標本を増やせば区間より速く縮んでいく性質のズレです。

Fig 5: 素朴プラグインと DML の推定分布(モンテカルロ100回)。素朴プラグインは平均 0.563 で 100 回中 100 回が上振れし、手組み DML は平均 0.512 で真値 0.5 の赤い破線を囲む

4.3 交差適合を外すと、残差は信号ごと消える

3.2 の最後に置いた前提を、今度はわざと壊します。交差適合を省いて、全データで当てはめたモデルで、その同じデータを残差化したらどうなるか。極端な思考実験から入ると分かりやすいです。1近傍法(自分と同じ点を返すモデル)で残差を作れば、残差は全点で厳密にゼロ。残差×残差の回帰は0/0になり、何も推定できません。過学習はこの劣化版で、モデルが交絡だけでなくノイズまで暗記し、残差から本来残るべき信号 $v$ と $\varepsilon$ を削り取ってしまいます。

今度は非線形のニュイサンス(sinとtanh)を仕込み、学習器も勾配ブースティングに替えて確かめます。

出力を開く前に予想してください。交差適合なしで推定した θ は、真値 0.5 の近くに残るでしょうか、それとも大きく外れるでしょうか。

予想の図(問い): 題は「交差適合を外すと、θ はどうなる?」。交差適合なしの θ(真値は 0.5)と処置残差の分散(本来は 1.0)は伏せてある。選択肢は、ア 0.5 の近くに残る、イ 0.5 より大きく外れる、ウ 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()))
出力
交差適合なし: θ = 1.523  処置残差の分散 = 0.0001(本来は1.0)
交差適合あり: θ = 0.536  処置残差の分散 = 1.291

予想の図(答え): 答えはイ(0.5 より大きく外れる)。交差適合なしの θ は 1.523、処置残差の分散は 0.0001(本来は 1.0)

交差適合なしでは、処置残差の分散が 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で学んだモデルで作るので、どのモデルも残差化する相手のデータを見ていません。それでいて、全データが最終的に残差として使われるので、サンプルを捨てる無駄もありません。

Fig 6: 交差適合(2 分割の場合)。データを無作為に fold A と fold B に分け、fold A で学んだモデルで fold B の残差を、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つセットで初めて成立します。片方でも欠くと、点推定だけでなく区間も信用できなくなる、というのが今日の締めの教訓です。

Fig 7a: 同じ推定を 16 シードで反復した θ。交差適合なしは 0.10〜1.52 と暴れ、交差適合ありは 0.43〜0.59 で真値 0.5 の周りに集まる

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] で真値を狭い区間で囲む

中間の会話: 「交差適合なしでもシードによっては 0.5 に近い値が出る、当たりのシードを使えば」と言うさくらに、顧問が「当たりかどうかは、真値を知らないと分かる?」。実データに真値は無い。だから処置残差の分散を見る。0.0001 なら暗記で信号ごと消えた合図

対比の図: 題は「交差適合なしは、真値を外す」。上は交差適合あり(cv=5)で θ は 0.536、95%CI [0.466, 0.607] は真値 0.5 を囲む。下は交差適合なし(cv=1)で θ は 1.523、処置残差の分散は 0.0001、区間 [0.538, 2.509] は真値を含まない

成り立つ場合と成り立たない場合

仮定(残差を作るモデルが相手を見ていない) データに出るもの 今日の数字の読み方
成り立つ(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 つに絞りました。上から順にたどり、最初に右へ出たところが、いまやることです。

Fig 8: 判断フロー「DML を報告してよいか、上から 3 つ問う」(縦)。Q1 主要な交絡は X に入っているか → いいえなら DML では直せない(バックドア基準 Day 11 へ)。Q2 交差適合しているか → いいえなら残差が暗記で消える(5 分割などで推定し直す)。Q3 ニュイサンスの予測は十分か → 足りないなら 2 つの誤りの積が大きい(学習器や特徴を見直す)。全部通ったら、交差適合つきの点推定に 95%CI を添えて報告する

  • 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. おわりに

末尾の会話: 「交差適合つきの DML で 0.536、95%CI も真値を囲み、残差の分散も確かめました」と報告するさくらに、顧問が「ML には予測だけを任せて、効果は残差同士で読む」。さくらは「思いつく変数を全部 X に入れて、交絡探しも DML に任せます!」と張り切り、顧問は「DML は交絡を見つけてはくれない。何を入れるかは先に DAG で決めよう」

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 です。

Fig 0: 因果推論の地図。今回は「③ 推定する」の ML×因果「Double ML」

図は縦が分析の工程、横が流派です。この記事は「③ 推定する(数字を出す)」の、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(標本分割)が今日の交差適合と同じ精神であるところまで、手を動かして確かめます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?