欠落変数バイアス#

結果変数Y、処置変数Dと、Y,Dに影響を与える共変量(交絡因子)Xがあるとし、各変数の間には線形の関係があるとする。

処置の効果を正しく推定するためには共変量をモデルに含める必要があるため、正しいモデルは次の式の形になる(「長いモデル」ということでLとつけている)。

Y=αL+βLD+γLX+εL

ここでXを説明変数に入れない「短いモデル」

Y=αS+βSD+εS

を構築した場合、処置効果βSはどう推定されるのだろうか。

XをDに回帰する(Xの変動をDで説明する)モデルを立ててみる。

X=α+βD+ε

これを「長いモデル」に代入して整理すると、「短いモデル」との対応が見えてくる

Y=αL+βLD+γL(α+βD+ε)+εL=αL+γLα+(βL+γLβ)D+γLε+εL=αL+γLααS+(βL+γLβ)βSD+γLε+εLεS

「短いモデル」のβS

βS=βL+γLβ

であるため、正しいモデルの推定量βLからγLβの分だけズレることがわかる。

生成データで実験#

実際に回帰分析を行ってみる。乱数で生成する。

Hide code cell source
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
import statsmodels.formula.api as smf


# generate data
np.random.seed(0)

n = 100
X = np.random.uniform(low=0, high=1, size=n)

# XがDと独立していれば共変量でないので欠落変数バイアスは生まれない
# D = np.random.binomial(n=1, p=0.7, size=n)

# XはDとYに影響を与える共変量であるため、xと処置確率が相関するとする
D = np.array([np.random.binomial(n=1, p=x * 0.8) for x in X])

epsilon_L = np.random.normal(size=n)
alpha_L = 3
beta_L = 5
gamma_L = 7

print(f"真の係数:α_L={alpha_L}, β_L={beta_L}, γ_L={gamma_L}")
Y = alpha_L + beta_L * D + gamma_L * X + epsilon_L

# data
df = pd.DataFrame(dict(Y=Y, D=D, X=X))
display(df.head())


# plot
fig, ax = plt.subplots(dpi=70)
for d in np.unique(D):
    ax.scatter(X[D == d], Y[D == d], label=f"D == {d}")
ax.legend()
ax.set(xlabel="X", ylabel="Y")
fig.show()
真の係数:α_L=3, β_L=5, γ_L=7
Y D X
0 12.968330 1 0.548814
1 11.926394 1 0.715189
2 11.071875 1 0.602763
3 11.376362 1 0.544883
4 5.467551 0 0.423655
../../_images/4eacff3bb9373da7ce91c973a17b0fbc579958b1727662352bbe084639b883a3.png

このデータからそれぞれのモデルを推定すると次のようになる。

# long model
results = smf.ols('Y ~ D + X', data=df).fit()
alpha_L_, beta_L_, gamma_L_ = results.params
print(f"「長いモデル」の推定値:α_L={alpha_L_:.2f}, β_L={beta_L_:.2f}, γ_L={gamma_L_:.2f}")

# short model
results = smf.ols('Y ~ D', data=df).fit()
alpha_S_, beta_S_ = results.params
print(f"「短いモデル」の推定値:α_S={alpha_S_:.2f}, β_S={beta_S_:.2f}")

# X ~ D
results = smf.ols('X ~ D', data=df).fit()
alpha_, beta_ = results.params
print(f"XをDに回帰したモデルの推定値:α={alpha_:.2f}, β={beta_:.3f}")
「長いモデル」の推定値:α_L=3.16, β_L=5.04, γ_L=6.43
「短いモデル」の推定値:α_S=5.32, β_S=7.14
XをDに回帰したモデルの推定値:α=0.34, β=0.327

3つのモデルの関係性は

Y=αL+γLααS+(βL+γLβ)βSD+γLε+εLεS

だったので、推定値で同様に計算すると

estimated_alpha_S = (alpha_L_ + gamma_L_ * alpha_)
estimated_beta_S = (beta_L_ + gamma_L_ * beta_)
bias_beta_S = gamma_L_ * beta_

print(f"""
α_Sの推定値 = {estimated_alpha_S:.2f}
β_Sの推定値 = {estimated_beta_S:.2f}
β_Lとの差(欠落変数バイアス) = {bias_beta_S:.2f}
""")
α_Sの推定値 = 5.32
β_Sの推定値 = 7.14
β_Lとの差(欠落変数バイアス) = 2.10

となり、「短いモデル」の推定値と同じものが得られた。また、「長いモデル」と比べたときの差(バイアス)も得られた

誤差項との関係#

εS=γLε+εL

「短いモデル」の誤差項は説明変数と相関がある

residuals_L = Y - smf.ols('Y ~ D + X', data=df).fit().predict(df)

fig, ax = plt.subplots(figsize=[8, 3], ncols=2, dpi=72)
ax[0].scatter(X, residuals_L)
ax[0].set(xlabel="X", ylabel="residual")

ax[1].scatter(D, residuals_L, alpha=.5)
ax[1].set(xlabel="D", ylabel="residual")

fig.suptitle("Residuals of the long model")
fig.show()
../../_images/1a26975d4047bfc590dedcf10d601618a8c20806e30b81a63dba555831a4cc3a.png
residuals_S = Y - smf.ols('Y ~ D', data=df).fit().predict(df)

fig, ax = plt.subplots(figsize=[8, 3], ncols=2, dpi=72)
ax[0].scatter(X, residuals_S)
ax[0].set(xlabel="X", ylabel="residual")

ax[1].scatter(D, residuals_S, alpha=.5)
ax[1].set(xlabel="D", ylabel="residual")

fig.suptitle("Residuals of the short model")
fig.show()
../../_images/1ec49d805839c75b0190186ee9dbf204af220f0079dc57f7e710ec5145308cf5.png

外生性#

このことについては外生性・内生性といった言い方もされる。

次の単回帰モデルを考える。

Yi=α+βXi+εi,i=1,2,,n

説明変数Xiと誤差項εiが相関しないとき、説明変数Xi外生性(exogeneity)をもつと言われる。またこのような変数は外生変数(exogenous variable)と呼ばれる。

そうでないとき、説明変数Xi内生性(endogeneity)をもつという。

モデルの式の両辺の期待値をとってαについて解くとα=E[Yi]βE[Xi]であり、これを代入すると

YiE[Yi]=β(XiE[Xi])+εi

と書き換えることができる。両辺にXを乗じて期待値をとると

E[Xi(YiE[Yi])]=E[XiYi]E[Xi]E[Yi]=Cov(Xi,Yi)=βE[Xi(XiE[Xi])]=E[Xi2]E[Xi]2=Var(Xi)+E[Xiεi]=Cov(Xi,εi)=0

移項するとOLS推定量が得られる

β=Cov(Xi,Yi)Var(Xi)

もしE[Xiεi]=Cov(Xi,εi)0であれば、

Cov(Xi,Yi)Var(Xi)=β+Cov(Xi,εi)Var(Xi)

となり、Cov(Xi,εi) / Var(Xi)の分だけバイアスのある推定量になる

参考文献#

関連論文(積読リスト)#