- ホーム
- コラム
- YDC Labコラム
- データ解析ならPythonが最高!第8回

データ解析ならPythonが最高!第8回
Lab研究員 北山
重回帰分析(多重共線性、L1正則化)
多重共線性
実は、前回、検証に使ったデータを使って予測モデルを構築すると、偏回帰係数がおかしな値になります。
偏回帰係数を求めて予測モデルの構築します。
import numpy as np
# 白菜、大根、定数項
X2=np.array([
[ 6., 7., 1.],
[ 4., 4., 1.],
[ 2., 2., 1.],
])
# 総重量
y2=np.array([[28.], [13.], [11.]])
# 偏回帰係数を求める
w = np.linalg.inv(X2.T.dot(X2)).dot(X2.T).dot(y2)
print(u'偏回帰係数')
print(w)
(実行結果)
偏回帰係数
[[-12.]
[ 13.]
[ 9.]]
この予測モデルの重回帰式は、次のように推定されました。
白菜一個の重さが -12kg、大根一本の重さは 13kg、木箱の重さは 9kg、ということです。
白菜の個数が増えるほど総重量が軽くなる、ということですから白菜の重さがマイナスなんて明らかにおかしいです。
その原因は多重共線性にあります。
【多重共線性】
入力変数間に強い相関関係が存在する場合、誤差の拡大効果によって、偏回帰係数のバラツキが大きくなり,推定結果が信頼できなくなる。
入力変数間に強い相関とはどういうことでしょうか。
白菜の個数と大根の本数の関係を散布図で確認すると
確かに、白菜の個数と大根の本数に強い相関があります。
このように入力変数間に強い相関関係があると、偏回帰係数のバラツキが大きくなることがあります。理論的に相関関係がなくても、学習データに偶然、強い相関があれば多重共線性が問題となることがあるので注意が必要です。
偏差ベクトル a と b の成す角をθとすると、cosθ が相関係数でした。つまり、相関が強くなるほど偏差ベクトル a と b が平行に近づくということです。
このとき、ベクトル a と b の線形結合で偏差ベクトル c を表そうとすると・・・
a と b の僅かな差(ノイズ)が拡大され、偏回帰係数が大きくなります。
そこまで無理して合わせなくてもいいのに!
このように学習データに過剰に合わせ込んでしまうことを過学習といいます。過学習となる要因は多重共線性に限りません。過学習となったモデルは他のデータに適応しなくなり汎用性を失います。検証データよりも学習データの方がモデルの性能がはるかに良いときは過学習の兆候です。気を付けましょう。
L1正則化
多重共線性を避けるためには次の方法があります。
1.回帰係数が大きくなりすぎないように小さく抑える方法
・RR リッジ回帰(Ridge Regression) L2正則化最小二乗法(q=2)
2.次元を削減する方法
●変数を選択する
・LASSO L1正則化最小二乗法(q=1)
●特徴を抽出する
・PCR 主成分回帰(Principal Component Regression)
・PLS Partial Least Squares
ここでは変数を選択する方法 LASSO を簡単に紹介します。
変数を選択するということは、偏差ベクトル a と b が平行に近いなら、両方使わずに a か b のどちらか一方だけを使えばいいじゃないか、ということです。
重回帰は予測誤差を最小化するアプローチでした。
ここで、||...|| はノルムで予測誤差の大きさです。
重回帰分析は、学習データにおける予測誤差を最小化したため、結果として学習データに過剰適応した状態となり、偏回帰係数が大きくなりました。
そこで、LASSOは回帰係数が大きくなりすぎないように、懲罰項を付け足します。
α(アルファ) が十分に大きいとき、いくつかの回帰係数がゼロになります。
つまり変数を選択する、ということです。
α をゼロにすると重回帰と同じです。
次の図は、偏回帰係数 w1, w2 の値により予測誤差と懲罰項が変化する様子を図示したものです。重回帰分析では図のAの点で予測誤差が最小でした。LASSOでは、これに懲罰項が加算されるため点Aが最小にならずに赤丸の位置で最小になります。赤丸は w2=0 なので, w2 の変数は使われない、ということです。
原点Oから外れるほど懲罰項が拡大するため、偏回帰係数 w1, w2 が大きくなりすぎないように小さく抑えることができます。また、懲罰項の領域は角が軸上にあるように回転された正方形であるため、偏回帰係数のいくつかの成分がゼロになり、変数選択として機能します。
機械学習ライブラリscikit-learn を使用しLASSOを実行
import numpy as np
from sklearn import linear_model as lm
X = np.array( [
[3,5],
[1,1],
],dtype=np.float64)
y = np.array( [
[5],
[5],
],dtype=np.float64)
# LASSO
# fit_intercept : Y切片を計算するかどうか
clf = lm.Lasso(alpha=0.7, fit_intercept=False)
clf.fit(X, y)
print('LASSO')
print('w1 = %.1f' % clf.coef_[0])
print('w2 = %.1f' % clf.coef_[1])
(実行結果)
LASSO
w1 = 1.9
w2 = 0.0
偏回帰係数 w2 がゼロになりました。
重回帰分析はこれで終わりです。
次回は、
重回帰分析とRMSEの話を予定しています。