はじめに #
リッジ回帰 (ridge regression) は回帰手法の1つで、\(L_2\)ノルムを用いて回帰係数の重みに制限を加えることで、予測性能を向上させることを目的としています。単純な線形回帰モデルは過学習しやすい傾向があります。そのため、対象とする問題によっては、リッジ回帰などによってモデルに制限を加えることで、予測性能を向上できます。
この記事ではPythonとScikit-learnによるサンプルコードも示します。実行環境は以下の通りです。
- Python: 3.9.7
- NumPy: 1.20.3
- sklearn: 0.24.2
重回帰モデル #
説明変数の数を\(N\)として、説明変数を\(x_1, x_2, ..., x_N\), 目的変数を\(y\)と置くと、重回帰モデルは次式で表されます。
$$ y = w_1 x_1 + w_2 x_2 + ... + w_N x_N + w_0 $$ここで、\(w_1, w_2, ..., w_N\)は重み、\(w_0\)は切片です。簡単のため、重みと係数をまとめて
$$ \boldsymbol{w}=[w_0, w_1, w_2, ..., w_N]^{\top} $$とベクトル化します。
単純な線形回帰では、学習データに対する予測値の平均二乗誤差 (mean square error, MSE) を最小化するように\(\boldsymbol{w}\)を決定していました。平均二乗誤差は\(\boldsymbol{w}\)によって決定されるため、\(\boldsymbol{w}\)の関数であるとみなすことができます。よって、平均二乗誤差を\(\mathrm{MSE}(\boldsymbol{w})\)とおくと、次式で定義されます。
$$ \mathrm{MSE}(\boldsymbol{w}) = \sum_{i=1}^{M} (\boldsymbol{w}^{\top} \boldsymbol{x}^{(i)} + w_0 - y^{(i)})^2 $$繰り返しになりますが、単純な線形回帰では\(\mathrm{MSE}(\boldsymbol{w})\)を最小化する\(\boldsymbol{w}\)を探索します。
リッジ回帰モデル #
一方、リッジ回帰では、最小化する関数として次式の\(J(\boldsymbol{w})\)を考えます。
$$ J(\boldsymbol{w}) = \mathrm{MSE}(\boldsymbol{w}) + \alpha \sum_{i=1}^{M} \boldsymbol{w}_i^2 $$\(\alpha \sum_{i=1}^{M} \boldsymbol{w}_i^2\)を正則化項 (regularization term) と呼びます。正則化 (regularization) とは、過学習を防ぐため、モデルに制約を追加することです。正則化項によって、重み係数はできるだけ小さな値をとるようになります。
\(\alpha\)は正則化の強さを表すパラメータで、0以上の値を取ります。\(\alpha=0\)のとき、単純な線形回帰と同じモデルになります。\(\alpha\)が大きくなるほど正則化が強くなり、非常に大きな値を取る場合、全ての重み係数が0に近づきます。
なお、ベクトル\(\boldsymbol{w}\)を用いると、正則化項は\(\alpha (||\boldsymbol{w}||_2)^2\)となります。\(||\boldsymbol{w}||_2\)は\(L_2\)ノルムです。
scikit-learnのリッジ回帰 #
Ridgeクラス #
scikit-learnではsklearn.linear_model.Ridge
というクラスにリッジ回帰が実装されています。
sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,
normalize='deprecated', copy_X=True, max_iter=None,
tol=0.001, solver='auto', positive=False, random_state=None)
主なパラメータの意味は以下の通りです。
alpha
(float
): 正則化のパラメータです。デフォルト値は1.0
.fit_intercept
(bool
):True
の場合、切片を計算します。予測モデルが原点を通ることが想定される場合はFalse
に設定します。solver
(str
): 学習に使用するソルバ(計算アルゴリズム)です。svd
(特異値分解)、cholesky
(コレスキー分解)、sag
(Stochastic Average Gradient) ,saga
(sagの改良手法)などから選択可能です。デフォルトはauto
(データによって最適なソルバを自動で選択)。random_state
(int
/None
):solver
がsag
またはsaga
の場合、学習時の乱数シード。常に同じ結果を得たい場合は適当な整数を指定する。None
の場合、結果は変わり得る(デフォルトはNone
)。
また、主なメソッドは以下の通りです。
fit(X, y)
: 特徴量X
, クラスy
を教師データとして学習する。predict(X)
: 特徴量X
に対する予測結果を返す。
使用例 #
Ridge
クラスの使用例を示します。X_train
は行がサンプル、列が特徴量の2次元配列です(PandasのDataFrameなどでも可)。y_train
は目的変数の1次元配列です。次に、Ridge
クラスのオブジェクトをreg
という名前で作成します(reg
はregressorから名付けています)。
import numpy as np
from sklearn.linear_model import Ridge
# 学習データ
X_train = np.array([[0, 1],
[3, 2],
[5, -2]])
y_train = np.array([3, 10, 23])
reg = Ridge(alpha=1.5)
fit
メソッドで学習し、predict
メソッドで予測します。予測結果は1次元配列となります。
# 学習
reg.fit(X_train, y_train)
X_test = np.array([[2, 1],
[8, 2]])
# 予測
y_pred = reg.predict(X_test)
print(y_pred)
実行結果:
[ 9.09456067 23.35230126]
係数を確認するにはreg.coef_
, 切片を確認するにはreg.intercept_
を表示します。
print(reg.coef_)
print(reg.intercept_)
実行結果:
[ 2.65941423 -1.69874477]
5.474476987447701