学習コースLearn
因果推論
相関を超えて「原因と結果」を見極めるための考え方と手法を、概要から理論、そして実際に動かせるコードまで、順を追って学ぶモジュールです。各ステップは「概要 → 仕組み(座学)→ コードで動かす」の3層で進みます。ページ内には手を動かせるデモを3つ用意しました。
この教材は日本語のみで提供していますThis learning material is available in Japanese only.
はじめにIntroduction
このモジュールの全体像
因果推論(causal inference)とは、「Xを変えたら、本当にYは変わるのか」という原因と結果の関係をデータから見極めるための考え方と手法の総称です。ある教材で成績が上がったのか、ある薬で症状が改善したのか、ある施策で売上が伸びたのか。こうした問いに答えるには、単にXとYが一緒に動くこと(相関)を確かめるだけでは足りません。
データ分析でくり返し戒められる言葉に「相関は因果ではない」があります。二つの量が連動していても、片方がもう片方を引き起こしているとは限らないからです。因果推論は、この落とし穴を避け、正しく効果を測るための道具立てを与えてくれます。多くの手法に共通するのが、次のような考えの流れです。
因果推論の考え方の流れ
このモジュールは、上の流れを左から順にたどります。各ステップは次の3層で構成します。
- 概要:その考え方や手法が何のためにあるのか、あらましをつかむ。
- 仕組み(座学):背後にある定義・仮定・式を、ていねいに理解する。
- コードで動かす:Python の定番ライブラリや、ページ内デモで実際に確かめる。
手を動かす題材には、ページ内の小さなサンプルや、乱数で作ったシミュレーションデータを使います。因果効果の「正解」があらかじめ分かっているシミュレーションは、各手法が本当に正しい値を取り戻せるかを確かめるのに向いています。特別な環境がなくても、読みながら試せる構成です。
因果推論とは
What is causal inference概要Overview
私たちが本当に知りたいのは、多くの場合「もし介入したら結果はどう変わるか」です。ある施策を打つべきか、ある治療を選ぶべきか。こうした意思決定は、単なる予測ではなく因果の問いです。ところが観察されたデータには、しばしば見かけの関係が紛れ込みます。
- 相関:二つの量が一緒に動く、という観測上のパターン。
- 因果:一方を変えれば他方が変わる、という介入に対する応答。
よく知られた例に「アイスクリームの売上が増えると水難事故も増える」があります。両者は強く相関しますが、アイスが事故を起こすわけではありません。背後には気温という共通の原因があり、暑い日にはアイスも売れ、泳ぐ人も増えるだけです。相関を因果と取り違えないために、私たちは考えの枠組みを必要とします。
仕組みHow it works
潜在結果(potential outcomes)
因果を厳密に考えるための土台が潜在結果(potential outcomes)の枠組みです(Rubin の因果モデルとも呼ばれます)。ある個体 i について、処置(介入)を受けたかどうかを表す二値 T を考え、次の二つの結果を想定します。
- Yi(1):もし処置を受けたら得られる結果。
- Yi(0):もし処置を受けなかったら得られる結果。
この個体にとっての処置効果は、両者の差 Yi(1) - Yi(0) です。ところが現実には、同じ個体について「受けた場合」と「受けなかった場合」を同時に観測できません。処置を受けた人からは Y(1) しか、受けなかった人からは Y(0) しか手に入らないのです。もう一方はけっして観測できない反実仮想であり、これを因果推論の根本問題と呼びます。
平均処置効果(ATE)
個体ごとの効果は取り出せませんが、集団全体で平均を取れば推定できる見込みがあります。これが平均処置効果(ATE: Average Treatment Effect)です。
単純な「処置群の平均 − 対照群の平均」がこれと一致するのは、両群が処置以外の点でそろっているときに限られます。
ここが因果推論の核心です。観察データでは、処置を受けた人と受けなかった人がもともと違う集団であることが多く、両者を素朴に比べても ATE にはなりません。Step 2 以降では、この「もともとの違い」=交絡をどう扱うかを、順に見ていきます。
この Step のまとめ
因果推論が問うのは「介入したら結果はどう変わるか」。各個体には受けた場合 Y(1) と受けなかった場合 Y(0) があり、片方しか観測できません(根本問題)。その差の平均が平均処置効果(ATE)で、これを正しく推定するのがこのモジュールの目標です。
交絡とバイアス
Confounding & bias概要Overview
観察データで因果を測るときに、最大の敵となるのが交絡(confounding)です。処置の有無と結果の両方に影響する第三の要因があると、処置と結果の見かけの関係がゆがみます。この Step では、交絡とそこから生じるバイアスの正体を、具体例とともに押さえます。
仕組みHow it works
交絡変数(confounder)
交絡変数とは、処置 T と結果 Y の両方に影響する変数のことです。先ほどの例では、気温がアイスの売上(T)と水難事故(Y)の共通原因でした。交絡があると、T と Y の相関には「T が Y を引き起こす効果」と「共通原因を通じた見かけの効果」が混ざり込み、素朴な比較は偏り(バイアス)を持ちます。
選択バイアス(selection bias)
誰がデータに含まれるか、誰が処置を受けるかが結果と関係していると、選択バイアスが生じます。たとえば「やる気のある人ほど講座を受講する」なら、受講者の成績が良くても、それが講座の効果なのか、もともとのやる気の差なのか区別できません。処置群と対照群が処置以外の点で異なるとき、比較は公平になりません。
シンプソンのパラドックス
交絡の効果が劇的に現れるのがシンプソンのパラドックスです。全体で見るとある傾向があるのに、集団を適切なグループに層別すると、すべての層で逆の傾向になる、という現象です。下のデモで実際に体験できますが、たとえば「治療法Aは全体では回復率が低く見えるのに、軽症でも重症でも、層別すればAのほうがBより回復率が高い」といったことが起こります。原因は、Aが重症者に多く使われている(=重症度が交絡している)ことです。どちらの数字を見るべきかは、背後の因果構造によって決まります。
因果ダイアグラム(DAG)とバックドア基準
どの変数を調整すべきかを見きわめる道具が因果ダイアグラム(DAG: 有向非巡回グラフ)です。変数を点、因果の向きを矢印で描きます。処置から結果への「まっすぐな道」以外に、交絡変数を経由して裏から回り込む経路(バックドア経路)があると、見かけの相関が生まれます。この裏道を、交絡変数で条件づけてふさぐのがバックドア基準の考え方です。必要な交絡変数をすべて調整できれば、観察データからでも因果効果を識別できます。逆に、調整すべきでない変数(結果の後に来る変数など)まで触ると、かえって新たなバイアスを生む点にも注意します。
シンプソンのパラドックス
全体で見たときと、グループごとに層別したときで、結論が逆転する数値例です。データを選び、「全体で見る」「層別で見る」を切り替えて、棒グラフと表がどう変わるかを確かめてください。全体では負けている側が、じつはどの層でも勝っている、という逆転が起こります。
この Step のまとめ
交絡変数は処置と結果の両方に影響し、素朴な比較にバイアスを生みます。シンプソンのパラドックスは、その極端な現れ方です。DAG とバックドア基準は「どの変数を調整すべきか」を教えてくれます。次の Step では、交絡そのものを断ち切る最強の方法=ランダム化を見ます。
ランダム化比較試験(RCT)
Randomized controlled trials概要Overview
交絡を根本から断ち切る、もっとも確実な方法がランダム化比較試験(RCT)です。誰が処置を受けるかをくじ引き(無作為割り付け)で決めることで、処置群と対照群を「処置以外はそっくりな二つの集団」に仕立てます。新薬の治験や、施策の効果検証(A/Bテスト)の基礎にある考え方です。
仕組みHow it works
なぜランダム化で交絡が消えるのか
処置を受けるかどうかをコイン投げで決めると、割り付けはあらゆる背景要因と統計的に独立になります。年齢も、重症度も、やる気も、まだ測っていない未知の要因さえも、処置群と対照群にほぼ同じ割合で散らばります。つまり、既知の交絡だけでなく未観測の交絡までまとめてバランスさせられるのが、ランダム化の決定的な強みです。両群がそろっている以上、処置後に生じた結果の差は、処置そのものの効果と見なせます。
処置群・対照群と ATE の推定
ランダム化のもとでは、処置群の結果の平均が E[Y(1)] の、対照群の結果の平均が E[Y(0)] の、それぞれ偏りのない推定になります。したがって単純な差
観察データでは、この等式は交絡のぶんだけ成り立ちません。
下のデモは、この違いを目で見て確かめるものです。同じ母集団に対し、重症者ほど処置を受けやすい観察データと、コイン投げで割り付けたランダム化を並べ、それぞれの単純比較が「本当の効果」からどれだけずれるかを見ます。
ランダム化の効果
重症度が交絡している母集団を作り、二通りの割り付けを比べます。観察データ(重症ほど処置を受けやすい)と、ランダム化(コイン投げ)です。真の平均処置効果はどちらでも同じですが、単純比較の値は大きく変わります。スライダで交絡の強さを変え、再サンプリングで別の乱数も試せます。
コードで動かすRun the code
NumPy で同じ状況をシミュレーションできます。潜在結果 Y(0)・Y(1) を先に作っておけば、割り付けを変えるだけで観察データとランダム化を比べられます。真の ATE は 10 に設定しています。
import numpy as np
rng = np.random.default_rng(42)
N = 2000
# 交絡変数 U: 重症度(1=重症, 0=軽症)
U = rng.integers(0, 2, size=N)
# 潜在結果(健康スコア, 高いほど良い)。真の処置効果 tau = 10
tau = 10.0
base = np.where(U == 1, 40.0, 65.0) # 重症は低い
Y0 = base + rng.normal(0, 5, size=N) # 処置を受けない場合の結果
Y1 = Y0 + tau # 処置を受ける場合の結果
# 観察データ: 重症ほど処置を受けやすい(交絡)
p = np.where(U == 1, 0.8, 0.2)
T = rng.binomial(1, p)
Y = np.where(T == 1, Y1, Y0)
naive = Y[T == 1].mean() - Y[T == 0].mean()
# ランダム化: コイン投げで割り付け(U と独立)
Tr = rng.binomial(1, 0.5, size=N)
Yr = np.where(Tr == 1, Y1, Y0)
rct = Yr[Tr == 1].mean() - Yr[Tr == 0].mean()
print(f"真の ATE : {(Y1 - Y0).mean():.2f}")
print(f"観察データ 単純比較 : {naive:.2f}")
print(f"ランダム化 単純比較 : {rct:.2f}")
真の ATE : 10.00
観察データ 単純比較 : -5.12
ランダム化 単純比較 : 9.11観察データの単純比較は -5.12、つまり「処置は結果を下げる」と符号すら逆に出てしまいました。重症者ほど処置を受けているため、処置群の結果が低く引きずられたのです。いっぽうランダム化では 9.11 と、真の値 10 のごく近くに収まりました(残りのずれは有限標本の偶然によるもので、N を増やすと縮みます)。
この Step のまとめ
ランダム化は、既知・未知を問わずあらゆる交絡をバランスさせ、単純な群間差をそのまま ATE の推定にします。これが因果推論の理想形です。とはいえ、倫理やコストの制約でランダム化できない場面も多い。次の Step からは、すでにある観察データから因果を取り出す方法を学びます。
観察データでの因果推定 ①
Adjusting observational data概要Overview
ランダム化ができないとき、私たちは手持ちの観察データから因果効果を取り出そうとします。鍵は、Step 2 で見た交絡変数を測って調整することです。ここでは、層別・回帰による調整と、傾向スコアという強力な考え方を扱います。
仕組みHow it works
層別と回帰による調整
もっとも素直なのは、交絡変数の値ごとに層別して、層のなかで処置群と対照群を比べる方法です。シンプソンのパラドックスの例で「軽症・重症に分けて比べる」のが、まさにこれでした。各層での効果を、層の大きさで重み付けして平均すれば、全体の効果になります。交絡変数が多いと層が細かくなりすぎるため、実務では回帰で調整することも多い。結果 Y を、処置 T と交絡変数 X の両方で説明する回帰式を立て、X をそろえたうえでの T の係数を効果と見なします。
傾向スコア(propensity score)
交絡変数が多いと、層別も回帰も扱いづらくなります。そこで登場するのが傾向スコアです。傾向スコアとは、共変量 X が与えられたときにその個体が処置を受ける確率
傾向スコアが同じ個体どうしは、共変量の分布がそろう(バランスする)という性質があります。
多次元の X を、この1つの確率に要約できるのが利点です。同じ傾向スコアを持つ処置群と対照群は、共変量の分布がそろうため、擬似的にランダム化に近い比較ができます。使い方は主に二つです。
- マッチング:傾向スコアが近い処置群と対照群をペアにして比べる。
- 逆確率重み付け(IPW: Inverse Probability Weighting):処置を受けにくかった人が受けた場合など、めずらしい組み合わせを重く数えて、集団全体を作り直す。
IPW による ATE の推定量は次の形です。処置群は 1/e(X) で、対照群は 1/(1−e(X)) で重み付けします。
この推定が正しいのは、必要な交絡変数がすべて X に含まれている(未観測交絡がない)という仮定のもとです。
コードで動かすRun the code
scikit-learn のロジスティック回帰で傾向スコアを推定し、IPW で ATE を求めてみます。交絡があるため単純比較は上振れしますが、IPW は真の効果に近づきます。真の効果は 5 に設定しています。
import numpy as np
from sklearn.linear_model import LogisticRegression
rng = np.random.default_rng(0)
N = 2000
X = rng.normal(0, 1, size=(N, 1)) # 共変量(交絡変数)
# 交絡: X が大きいほど処置を受けやすく、結果も高くなる
p = 1 / (1 + np.exp(-(-0.2 + 1.3 * X[:, 0])))
T = rng.binomial(1, p)
tau = 5.0 # 真の処置効果
Y = 2.0 * X[:, 0] + tau * T + rng.normal(0, 1, size=N)
naive = Y[T == 1].mean() - Y[T == 0].mean()
# 傾向スコア e(X)=P(T=1|X) をロジスティック回帰で推定
ps = LogisticRegression().fit(X, T)
e = ps.predict_proba(X)[:, 1]
# 逆確率重み付け(IPW)による ATE の推定
ate = np.mean(T * Y / e - (1 - T) * Y / (1 - e))
print(f"単純比較(交絡あり): {naive:.2f}")
print(f"IPW による ATE 推定 : {ate:.2f}")
print(f"真の処置効果 : {tau:.2f}")
単純比較(交絡あり): 7.06
IPW による ATE 推定 : 4.88
真の処置効果 : 5.00単純比較は 7.06 と、真の効果 5 を大きく上回りました。もともと結果が高くなりやすい人ほど処置を受けているためです。傾向スコアで重み付けし直した IPW は 4.88 と、真の値に近づきました。ただしこれは、交絡変数 X をすべて観測できているという前提のうえに成り立つ点を忘れてはいけません。
この Step のまとめ
観察データでは、交絡変数を測って調整するのが基本です。層別・回帰に加え、多次元の共変量を1つの確率にまとめる傾向スコア(マッチング・IPW)が強力です。ただしどの方法も「必要な交絡をすべて観測できている」という仮定に依存します。
観察データでの因果推定 ②
DID, IV, and RDD概要Overview
交絡変数をすべて測るのは、現実には難しいことがあります。そこで、データの構造や自然に起きた変化を賢く利用して因果を取り出す手法群が発達しました。代表的な三つ、差分の差分法(DID)・操作変数法(IV)・回帰不連続デザイン(RDD)を概観します。
仕組みHow it works
差分の差分法(DID: Difference-in-Differences)
ある施策が一部の集団(処置群)だけに導入され、別の集団(対照群)には導入されなかったとします。両群の処置前後の変化の差を取ることで、施策の効果を推定するのが DID です。定義は次のとおりです。
両群に共通する時間変化(トレンド)を、対照群の変化として差し引くのが要点です。
DID が効果を正しく捉えるための鍵が平行トレンドの仮定です。「もし施策がなかったら、処置群も対照群と同じだけ変化していたはずだ」という仮定です。これが成り立つなら、対照群の変化ぶんを「処置群にとっての反実仮想の変化」と見なせます。処置群の実際の変化と、この反実仮想の変化との差が、施策の効果です。下のデモで、この関係を図で確かめられます。
操作変数法(IV: Instrumental Variables)
未観測の交絡があっても使えることがあるのが IV です。操作変数とは、(1) 処置には影響するが、(2) 結果には処置を通じてしか影響せず、(3) 交絡変数とは無関係、という三条件を満たす変数です。この「処置をゆさぶるが結果には直接効かない」外生的な変動だけを取り出して、効果を推定します。たとえば、くじで決まる何かや、制度上の割り当てなどが操作変数の候補になります。適切な操作変数を見つけるのが最大の難所です。
回帰不連続デザイン(RDD: Regression Discontinuity Design)
ある連続量のしきい値で処置の有無がぱっと切り替わる状況を使うのが RDD です。たとえば「点数が基準点以上なら奨学金を受給」なら、基準点のすぐ上とすぐ下の人は、点数以外はほとんど同じはずです。境界のすぐ両側を比べれば、その場所での効果を、あたかも局所的なランダム化のように推定できます。境界近傍という限られた範囲での効果である点に注意します。
差分の差分法(DID)
処置群と対照群について、処置前・処置後の平均アウトカムを入力すると、DID 推定量を計算し図にします。破線は「もし処置がなければ処置群はこう動いたはず」という平行トレンドの仮定にもとづく反実仮想です。実際の処置後の値と破線との差が、推定された効果(DID)です。
コードで動かすRun the code
DID は、交互作用項つきの回帰としてすっきり書けます。処置群ダミー treat と処置後ダミー post を用意し、その積 treat:post の係数が DID 推定量になります。statsmodels で確かめましょう。
import pandas as pd
import statsmodels.formula.api as smf
# 処置群・対照群 × 処置前後 のデータ(各セルの平均アウトカム)
df = pd.DataFrame({
"treat": [1, 1, 0, 0], # 1=処置群, 0=対照群
"post": [0, 1, 0, 1], # 0=処置前, 1=処置後
"Y": [20.0, 35.0, 25.0, 32.0],
})
# Y = b0 + b1*treat + b2*post + b3*(treat*post) を最小二乗推定
model = smf.ols("Y ~ treat * post", data=df).fit()
print(model.params.round(1))
print()
print(f"DID 推定量(交互作用項)= {model.params['treat:post']:.1f}")
Intercept 25.0
treat -5.0
post 7.0
treat:post 8.0
dtype: float64
DID 推定量(交互作用項)= 8.0係数を読み解くと、Intercept=25 は対照群の処置前、post=7 は対照群に共通する時間変化、treat=−5 は両群のもともとの差、そして treat:post=8 が、時間変化を差し引いてなお残る処置群だけの上乗せ=DID 推定量です。デモの「効果あり(+8)」と同じ値になっているのが分かります。
この Step のまとめ
DID・IV・RDD は、交絡をすべて測れなくても、データの構造や自然な変化を利用して因果を取り出す準実験的な手法です。いずれも「平行トレンド」「操作変数の三条件」「境界での連続性」といった識別のための仮定に支えられており、その仮定が妥当かどうかが結果の信頼性を決めます。
落とし穴とこれから
Pitfalls and what comes next概要Overview
ここまで見てきた手法は強力ですが、どれも仮定のうえに立っています。因果推論を実務で使うときに気をつけたい落とし穴を整理し、機械学習との接点にも触れて、このモジュールを締めくくります。
仕組みHow it works
識別仮定の重要性
因果効果を観察データから取り出せるかどうかは、識別仮定にかかっています。傾向スコアや回帰調整は「必要な交絡をすべて観測できている」、DID は「平行トレンド」、IV は「操作変数の三条件」、RDD は「境界での連続性」を前提にしていました。手法の計算が正しく回ることと、仮定が現実に成り立つことは別の話です。どんなに洗練された推定でも、仮定が崩れていれば結論は信用できません。
未観測交絡
観察データでの最大の脅威が未観測交絡です。測れていない、あるいは存在に気づいていない交絡変数があると、調整のしようがありません。ランダム化がこれほど尊ばれるのは、まさに未観測交絡までバランスさせられるからです。観察研究では、結論がどれだけ未観測交絡に対して頑健かを調べる感度分析が役立ちます。
外的妥当性
ある集団・ある状況で得られた効果が、別の集団や状況でも同じとは限りません。これを外的妥当性の問題と呼びます。特定の地域や時期の実験結果を、そのまま一般化してよいかは慎重に考える必要があります。効果が誰にとっても一定とは限らず、人によって異なる(異質な処置効果)ことも多いのです。
因果推論と機械学習の接点
近年は、機械学習と因果推論が急速に融合しています。多数の共変量から傾向スコアや結果を柔軟に予測させつつ、因果効果の推定には偏りが乗らないように工夫する二重機械学習(Double ML)や、人によって異なる効果(異質処置効果)を推定する手法が発展しています。予測を得意とする機械学習と、介入の効果を問う因果推論は、目的が違うからこそ補い合う関係にあります。
この Step のまとめ
因果推論の結論は、識別仮定の妥当性しだいです。未観測交絡・外的妥当性・効果の異質性に注意し、感度分析で頑健さを確かめましょう。機械学習との融合は、この分野のもっとも活発なフロンティアの一つです。
まとめWrap-up
学びの振り返りと、さらに学ぶために
このモジュールでは、相関を超えて因果に迫るための道具を、考えの流れに沿って手に入れました。
- 反実仮想と ATE:受けた場合 Y(1) と受けなかった場合 Y(0) の差の平均が、測りたい効果。
- 交絡とバイアス:処置と結果の共通原因が、素朴な比較をゆがめる。シンプソンのパラドックスはその極端な例。
- ランダム化(RCT):くじ引きで交絡を断ち切り、群間差をそのまま効果にできる理想形。
- 観察データの調整:層別・回帰・傾向スコア(マッチング・IPW)で交絡を調整する。
- 準実験的手法:DID・IV・RDD は、データの構造や自然な変化を利用する。仮定が命。
次に進むなら、下の道具と資料が役に立ちます。
公開データセット
- LaLonde(NSW 職業訓練データ):職業訓練の効果検証に使われる古典的な公開データ。因果推論の教材で広く用いられる。
- シミュレーション生成データ:効果の「正解」を自分で決められるため、手法の検証に最適。本ページの例もこの方式。
ライブラリ
- statsmodels:回帰・DID など計量経済の定番。
- scikit-learn:傾向スコア(ロジスティック回帰)など。
- DoWhy:因果グラフにもとづく効果推定の枠組み。
- EconML:機械学習と組み合わせた効果推定。
参考書
- Judea Pearl ほか『入門 統計的因果推論』
- 宮川雅巳『統計的因果推論』
- 安井翔太『効果検証入門』
おつかれさまでした
ここで学んだ「相関を疑い、交絡を洗い出し、仮定を明示して効果を推定する」という姿勢は、データから意思決定へつなぐあらゆる場面で共通します。3つのデモの数値を書き換えて、推定値がどう動くかを何度も確かめてみてください。手を動かすほど、仮定の大切さが実感できます。
発展トピックBeyond this module
このコースでは扱わない、関係する発展トピック
このモジュールでは、反実仮想から出発して交絡を調整し、効果を推定する「基礎の流れ」を扱いました。いっぽうで現代の因果推論は、グラフ理論や機械学習と結びつきながら急速に広がっています。ここでは、このコースでは踏み込まないものの、知っておくと視野が広がる発展的なトピックを、特に近年の主流を中心に紹介します。深掘りは各自の興味に合わせてどうぞ。
構造的因果モデルと do 演算
- 構造的因果モデル(SCM):変数間の因果関係を方程式とグラフで表す枠組み(Pearl)。
- do 演算子:観測ではなく「介入した世界」を数式で表す記法。バックドア基準やフロントドア基準は、この上で導かれる。
機械学習との融合
- 二重機械学習(Double ML):柔軟な機械学習で共変量を捌きつつ、効果推定の偏りを抑える。
- 異質処置効果:人によって異なる効果(CATE)を推定する(Causal Forest など)。
- DoWhy・EconML:これらを実装したライブラリ群。
因果探索と媒介分析
- 因果探索(causal discovery):データから因果グラフの構造そのものを推定する試み。
- 媒介分析:効果を「直接効果」と「媒介変数を経由する間接効果」に分解する。
頑健性の評価
- 感度分析:未観測交絡がどれほどあれば結論が覆るかを調べ、推定の頑健さを測る。
- 反証テスト:効果が出るはずのない場所(プラセボ)で本当に効果ゼロか確かめる健全性チェック。