はじめに
自分のやりたい事を整理していて、他の人と話す機会があったのですが、「それなら因果推論はやっておいた方がいいよね」、と言われまして、確かに勉強しておかないとまずいなと思い、記事を書いてみます。(いまさら感もありますが)
とりあえず因果推論とはどんなものかを、LLMを使って学習した内容で、初歩的な内容のアウトプットです。間違い等あれば指摘お願いいたします。
本格的に学習したい場合は、因果推論の勉強ロードマップや、【Juliaで因果推論】回帰分析 - OLS推定とその仮定などほかの記事を参考にして、学習するべきかと思います。
因果推論とは
因果推論は、単に「X と Y が一緒に動くか(相関)」を見るのではなく、**「X を介入(do)したら Y はどう変わるか」**を問う手法群です。
代表的な問いは例えば:
「広告を出したら売上はどれだけ増えるのか?」
この問いは単純に相関を調べるだけでは答えられません。相関は「一緒に動くか」を示すにすぎず、介入の効果(反実仮想)を推定するためには 仮定(因果構造) と 適切な調整 が必要です。
本記事では、まず相関解析から入り、次に因果を意識した解析(回帰での調整)を行い、さらに「モデル化を間違えるとどう壊れるか」をシミュレーションで示します。
シミュレーション
- 広告費に使ったお金に対して、インプレッションが発生し
- インプレッションの中でクリックされた人がある程度サイトに滞在し
- 滞在時間に応じて売り上げが上がる
といったシミュレーションを行いました。
このシミュレーションデータに対して、相関や因果推論の初歩的な理論を試していきます。
- データ生成コード
import numpy as np
import pandas as pd
import statsmodels.api as sm
np.random.seed(42)
n = 3000
# データ生成
ad_spend = np.random.gamma(shape=2, scale=50, size=n)
impression = 20 * ad_spend + np.random.normal(0, 200, n)
click = 0.05 * impression + np.random.normal(0, 20, n)
stay_time = 2.0 * click + np.random.normal(0, 10, n)
sales = 3.0 * stay_time + np.random.normal(0, 30, n)
df = pd.DataFrame({
"ad_spend": ad_spend,
"impression": impression,
"click": click,
"stay_time": stay_time,
"sales": sales
})
相関解析
単純ですが、計測された値の相関をとります。
相関係数の値が高いほど関係性が強いという意味です。
- 相関解析コード
corr = df.corr()
print("======correlation analysis======")
print(corr["sales"].sort_values(ascending=False))
- 結果
======correlation analysis======
sales 1.000000
stay_time 0.997655
click 0.995213
impression 0.957608
ad_spend 0.948205
Name: sales, dtype: float64
当たり前なのですがどれも値が高いですね。この解析から得るものはあまりありません。
因果推論
定数項を含めたOLSを行うことによって、因果推論を行います。
因果関係の大元との関係を調査します。
OLSを用いた時の、係数の値が元の特徴量が上がったら、どの程度出力が上がるのかを示します。
- コード
# 因果を意識したモデル
# ad_spend->impression->click->stay_time->sales
X_total = sm.add_constant(df["ad_spend"])
model_total = sm.OLS(df["sales"], X_total).fit()
print("======caused analysis1======")
print(model_total.params.drop("const"))
- 結果
======caused analysis1======
ad_spend 5.970593
dtype: float64
1単位当たりの出資で、約$5.97$の売り上げ効果があるようです。
因果推論が失敗する例
典型的な例を一つ
- コード
# 因果の設定を間違えたモデル
# ad_spend->impression->click->sales
# stay_time->sales
X_total = sm.add_constant(df[["ad_spend","stay_time"]])
model_total = sm.OLS(df["sales"], X_total).fit()
print("======caused analysis2======")
print(model_total.params.drop("const"))
- 結果
======caused analysis2======
ad_spend -0.001086
stay_time 2.998093
dtype: float64
因果の設定を間違えると広告費使っても効果がないという結論になってしまいます。
実務ではまず相関を見て、次に因果的妥当性(DAG)を考えるワークフローが有効のようです。
研究ではどうなっているか
因果推論研究は単純な OLS が破綻する現実を扱うために発展してきたようです。代表的な拡張・手法群(概要):
- IV(Instrumental Variables):観測できない交絡があっても、外生的な道具変数があれば識別可能。
- DiD(差分の差分) / 自然実験:ランダム化に近い状況を利用する。
- G-methods / Marginal Structural Models:時間的フィードバックがある場合の調整。
- CATE / Causal Forests / Double ML:個人差や高次元共変量の問題に対処する。
- 因果構造そのものを学習する 構造学習(causal discovery)。
参考文献やパイオニアとしては Judea Pearl の仕事などが基礎にあるようです。
まとめ
- 相関は「一緒に動く」ことを示すだけで、介入効果(因果)を保証しない。
- 因果的に正しい推定には仮定(因果構造)と適切な変数選択が必要。
- モデル化を間違えると解析は「成功」して見えるが、実際の介入効果は誤っている。
- 実務ではまず相関を見て、次に因果的妥当性(DAG)を考えるワークフローが有効。
さいごに
因果推論を勉強するきっかけとして、理論の基礎的な部分をLLMを使っておさらいしてみました。
因果関係をモデル化をちゃんとしないと解析できない上に、さらに数学的な素養も必要そうですね。
勉強が進んで報告するような内容があれば、報告したいと思います。
コードは GitHub に置いてあります:
続編は、こちら: