重回帰分析と単回帰分析に及ぼす独立変数間の相関
シミュレーションによる検討
Spiegelhalter(2019)において、単回帰分析と重回帰分析の同じ独立変数の係数の値の違いが、独立変数間の相関によると説明されている。これを、Spiegelhalter(2019), p. xviに記載されているウェブサイトからダウンロードしたデータファイルを用いて分析を行い確認した。プログラムはリスト1に示すPythonスクリプトである。この独立変数間の相関係数が回帰係数に及ぼす影響を、相関係数が正の場合、相関係数が負の場合、相関係数が0の場合、相関係数が正の場合で真の回帰モデルでは回帰係数が0である独立変数の単回帰係数が0でない場合についてシミュレーションで調べる。いずれの場合も、重回帰分析を用いると、データ生成モデルと一致する結果が得られたが、単回帰分析の結果は独立変数間の相関の影響が認められた。最後に、単回帰モデルと重回帰モデルの関係を簡単なモデルで検討してみた。
なお、回帰係数の計算は以下の方法に依っている。
回帰モデルを次式
で表したときの誤差の2乗和
を最小にするものとして係数を求める。
いま、
とおけば、式(1)は
と書くことができる。このとき、誤差の平方和を最小にするパラメータ値は次式で与えられる(岡本、2009、p.26)。
ここで、はのムーア・ペンローズ逆行列である。
Spiegelhalter(2019)は、Galtonのデータに対して、息子の身長を従属変数、父親および母親の身長を独立変数としたときの分析例を説明している。
単回帰モデル:
重回帰モデル:
回帰分析を行うPythonスクリプトをリスト1のように用意した。入力データファイル05-1-galton-x.csvは、Spiegelhalter(2019), p. xviに記載されているウェブサイトからダウンロードしたものである。
リスト1のプログラムを実行すると、表1に示す結果を得る。
表1 Galtonのデータの分析 |
|||
|
y切片 |
父親の係数 |
母親の係数 |
単回帰モデル |
69.2 |
0.45 |
--- |
重回帰モデル |
69.2 |
0.41 |
0.33 |
y切片の値は、独立変数の値が平均値のときの従属変数の値として期待されるものである(Spiegelhalter, 2019)。これは、独立変数の値が平均値が0であるように中心化されていることによる。独立変数の単位はインチのままであるので、単回帰モデルの場合は、父親の身長の差が1インチであれば、息子の身長の差は0.45インチであることが期待される(Spiegelhalter, 2019)。これに対して重回帰モデルの場合は、父親の身長の差が1インチであれば、息子の身長の差は0.41インチであることが予想される。この単回帰分析との違いは、独立変数間に相関あるからであるとSpiegelhalter(2019)は説明している。以下において、シミュレーションにより独立変数間の相関の影響を、相関係数が正の場合、相関係数が負の場合、相関係数が0の場合、相関係数が正の場合で真の回帰モデルでは回帰係数が0である独立変数の単回帰係数が0でない場合について順に調べる。
"""
Spielgelhalter(2019)による分析例
"""
import pandas as pd
import numpy as np
# ダウンロードしたファイルの読み込み
d_csv =
pd.read_csv('05-1-galton-x.csv')
v_data = d_csv.values
son_data = v_data[v_data[:,3]=='M']
y = son_data[:,4] # 息子の身長
n = len(y)
#
# 家族単位に親のデータ1組を抜き出す
#
parents = []
idx = '?'
for v in son_data:
if v[0] != idx:
parents.append(v)
idx
= v[0]
parents = np.array(parents)
mean_father =
np.mean(parents[:,1])
# 父親の平均身長
mean_mother =
np.mean(parents[:,2])
# 母親の平均身長
father_data = son_data[:,1] -
mean_father # 中心化
#
# 単回帰分析
#
A1 = np.concatenate((np.ones((n,1)),
np.reshape(father_data, (n,1))), axis=1)
A1 = np.array(A1, dtype=float)
bc1 = np.linalg.pinv(A1) @
np.reshape(y, (n,1))
print('単回帰分析')
print('bc1 =\n', bc1)
f_m_data = son_data[:,1:3] - [mean_father,
mean_mother]
# 中心化
#
# 重回帰分析
#
A2 = np.concatenate((np.ones((n,1)),
f_m_data), axis=1)
A2 = np.array(A2, dtype=float)
bc2 = np.linalg.pinv(A2) @
np.reshape(y, (n,1))
print('重回帰分析')
print('bc2 =\n', bc2)
従属変数、および独立変数との間に次の関係を設定する。
データ生成モデル(2)に対して、リスト2に示すプログラムを用意した。従属変数と独立変数の組み合わせによる単回帰分析と、従属変数と独立変数およびの組み合わせによる重回帰分液を行うものである。実行すると表2に示す結果が得られた。
表2 式(2)の場合:相関係数>0 |
|||
|
y切片 |
の係数 |
の係数 |
単回帰モデル |
0.00 |
0.85 |
--- |
重回帰モデル |
0.00 |
0.50 |
0.50 |
独立変数の係数は、単回帰分析では0.85であるが、重回帰分析では0.50である。独立変数と正の相関がある独立変数を重回帰分析の独立変数として加えると、独立変数の係数が0.85から0.50へと低下している。この低下は、上のSpiegelhalter(2019)のGaltonのデータの分析結果と同様である。
"""
相関係数 > 0
y = 0.5*x0 + 0.5*x1
"""
import numpy as np
import scipy.stats as ss
n = 10000
x = ss.multivariate_normal.rvs(mean=[0,
0], cov=[[1, 0.7], [0.7, 1]], size=n)
y = x @ np.array([0.5, 0.5]).T # y = 0.5*x0 + 0.5*x1
#
#
単回帰分析
#
A1 = np.concatenate((np.ones((n,1)),
np.reshape(x[:,0], (n,1))), axis=1)
B1 = np.linalg.pinv(A1) @
np.reshape(y, (n,1))
print('単回帰分析')
print('B1 =\n', B1)
#
#
重回帰分析
#
A2 = np.concatenate((np.ones((n,1)),
x), axis=1)
B2 = np.linalg.pinv(A2) @
np.reshape(y, (n,1))
print('重回帰分析')
print('B2 =\n', B2)
従属変数、および独立変数との間に次の関係を設定する。
独立変数との間に負-0.7の相関係数が設定されたデータ生成モデル(3)に対して、リスト3に示すプログラムを用意した。従属変数と独立変数の組み合わせによる単回帰分析と、従属変数と独立変数およびの組み合わせによる重回帰分液を行うものである。実行すると表3に示す結果が得られた。
表3 式(3)の場合:相関係数<0 |
|||
|
y切片 |
の係数 |
の係数 |
単回帰モデル |
0.00 |
0.15 |
--- |
重回帰モデル |
0.00 |
0.50 |
0.50 |
独立変数の係数は、単回帰分析では0.15であるが、重回帰分析では0.50である。独立変数と負の相関がある独立変数を重回帰分析の独立変数として加えると、独立変数の係数が0.15から0.50へと高くなっている。この0.5は、データ生成モデル(3)におけるの係数の値である。
"""
相関係数 < 0
y = 0.5*x0 + 0.5*x1
"""
import numpy as np
import scipy.stats as ss
n = 10000
#
# 共分散 < 0
#
x = ss.multivariate_normal.rvs(mean=[0,
0], cov=[[1, -0.7], [-0.7, 1]], size=n)
y = x @ np.array([0.5, 0.5]).T
# y = 0.5*x0 +
0.5*x1
#
#
単回帰分析
#
A1 = np.concatenate((np.ones((n,1)),
np.reshape(x[:,0], (n,1))), axis=1)
B1 = np.linalg.pinv(A1) @
np.reshape(y, (n,1))
print('単回帰分析')
print('B1 =\n', B1)
#
#
重回帰分析
#
A2 = np.concatenate((np.ones((n,1)),
x), axis=1)
B2 = np.linalg.pinv(A2) @
np.reshape(y, (n,1))
print('重回帰分析')
print('B2 =\n', B2)
従属変数、および独立変数との間に次の関係を設定する。
データ生成モデル(4)では、独立変数間の相関係数は0である。式(4)に対して、リスト4に示すプログラムを用意した。従属変数と独立変数の組み合わせによる単回帰分析と、従属変数と独立変数およびの組み合わせによる重回帰分液を行うものである。実行すると表4に示す結果が得られた。
表4 式(4)の場合:相関係数=0 |
|||
|
y切片 |
の係数 |
の係数 |
単回帰モデル |
0.00 |
0.50 |
--- |
重回帰モデル |
0.00 |
0.50 |
0.50 |
独立変数の係数は、単回帰分析において0.50であり、重回帰分析においても0.50である。独立変数と相関のない独立変数を重回帰分析の独立変数として加えても、独立変数の係数は0.50で変わらない。この0.5は、データ生成モデル(4)におけるの係数の値である。
"""
相関係数 = 0
y = 0.5*x1 + 0.5*x2
"""
import numpy as np
import scipy.stats as ss
n = 10000
#
# 共分散 = 0
#
x = ss.multivariate_normal.rvs(mean=[0,
0], cov=[[1, 0], [0, 1]], size=n)
y = x @ np.array([0.5, 0.5]).T
# y = 0.5*x0 +
0.5*x1
#
#
単回帰分析
#
A1 = np.concatenate((np.ones((n,1)),
np.reshape(x[:,0], (n,1))), axis=1)
B1 = np.linalg.pinv(A1) @
np.reshape(y, (n,1))
print('単回帰分析')
print('B1 =\n', B1)
#
#
重回帰分析
#
A2 = np.concatenate((np.ones((n,1)),
x), axis=1)
B2 = np.linalg.pinv(A2) @
np.reshape(y, (n,1))
print('重回帰分析')
print('B2 =\n', B2)
相関係数が正の場合で真の回帰モデルでは回帰係数が0である独立変数の単回帰係数が0でない場合
従属変数、および独立変数との間に次の関係を設定する。
独立変数の係数は0である。独立変数間の相関係数は0.7であるので、独立変数と従属変数との関係は独立変数を介して間接的である。データ生成モデル(5)に対して、リスト5に示すプログラムを用意した。従属変数と独立変数の組み合わせによる単回帰分析と、従属変数と独立変数およびの組み合わせによる重回帰分液を行うものである。実行すると表5に示す結果が得られた。
表5 式(5)の場合:相関係数=0.7 |
|||
|
y切片 |
の係数 |
の係数 |
単回帰モデル |
0.00 |
0.34 |
--- |
重回帰モデル |
0.00 |
0.00 |
0.50 |
独立変数の係数は、データ生成モデル(5)において0であるが、単回帰分析の結果は0.34である。重回帰分析の結果は、独立変数の偏回帰係数は0.00であり、独立変数の偏回帰係数は0.50である。重回帰分析の結果は、データ生成モデル(5)と一致している。
リスト5 相関がある独立変数の1つがデータ生成モデルにおける係数が0の場合
"""
相関係数 > 0
y = 0.0*x0 + 0.5*x1
"""
import numpy as np
import scipy.stats as ss
n = 10000
x =
ss.multivariate_normal.rvs(mean=[0, 0], cov=[[1, 0.7], [0.7, 1]], size=n)
y = x @ np.array([0.0, 0.5]).T # y = 0.0*x0 + 0.5*x1
#
#
単回帰分析
#
A1 = np.concatenate((np.ones((n,1)),
np.reshape(x[:,0], (n,1))), axis=1)
B1 = np.linalg.pinv(A1) @
np.reshape(y, (n,1))
print('単回帰分析')
print('B1 =\n', B1)
#
#
重回帰分析
#
A2 = np.concatenate((np.ones((n,1)),
x), axis=1)
B2 = np.linalg.pinv(A2) @ np.reshape(y,
(n,1))
print('重回帰分析')
print('B2 =\n', B2)
従属変数が個の独立変数、、・・・、により式(M0)で表されているとする。
さらに、独立変数、・・・、は独立変数の単回帰モデルとして以下のように表されているとする。
・・・
式(M1)〜(Mp)を式(M0)に代入して次式を得る。
式(SR)で表される単回帰モデルにおける回帰係数は
である。
岡本安晴(2009) 統計学を学ぶための数学入門[下].培風館
岡本安晴(2019) いまさら聞けないPythonでデータ分析.丸善出版
Spiegelhalter, D. (2019). The art of statistics: Learning from data. Pelican