Ridge回帰#

モデル#

リッジ回帰(ridge regression)は誤差関数に正則化項を追加した線形回帰モデルである。

モデル自体は線形回帰と同様で目的変数\(y\)をパラメータ\(\boldsymbol{\beta}=(\beta_1, \beta_2, ..., \beta_d)^\top\)と特徴量\(\boldsymbol{x}=(x_1, x_2, ..., x_d)^\top\)の線形関数と誤差\(\varepsilon\)で表現するものになる。

\[ y = \beta_0 + \beta_1 x_1 + \cdots + \beta_d x_d + \varepsilon \]

サンプルサイズが\(n\)のデータセット\(\{\boldsymbol{x}_i, y_i\}^n_{i=1}\)があるとして、目的変数を\(\boldsymbol{y} = (y_1, y_2, ..., y_n)^\top\)、特徴量を\(\boldsymbol{X}=(\boldsymbol{x}_1, \boldsymbol{x}_2, ..., \boldsymbol{x}_n)^\top\)とおくと

\[ \boldsymbol{y}=\boldsymbol{X} \boldsymbol{\beta}+\boldsymbol{\varepsilon} \]

と表記することもできる。

パラメータの推定#

制約付き最小化問題#

リッジ回帰が線形回帰と違う点は、パラメータの推定(誤差関数の最小化)に関して制約条件があること。

線形回帰は目的変数の実測値\(y_i\)と予測値\(\hat{y}_i=\sum^d_{j=1} x_{ij} \beta_j\)の誤差二乗和\(SSE=\sum^n_{i=1} (y_i - \hat{y}_i)^2\)を最小にするパラメータを求めるものであった。

\[ \newcommand{\argmin}{\mathop{\rm arg~min}\limits} \hat{\boldsymbol{\beta}}^{\text{LS}} = \argmin_{\boldsymbol{\beta}} \sum^n_{i=1} (y_i - \hat{y}_i)^2 \]

リッジ回帰はこれに「パラメータ\(\beta_j\)の二乗和がある値\(R\)以下である」という制約条件が付いた下でパラメータを推定する。

\[\begin{split} \newcommand{\argmin}{\mathop{\rm arg~min}\limits} \begin{align} \hat{\boldsymbol{\beta}}^{\text{Ridge}} = \text{ } & \argmin_{\boldsymbol{\beta}} \sum^n_{i=1} (y_i - \hat{y}_i)^2 \\ & \text{subject to } \sum^d_{i=1} \beta_j^2 \leq R \end{align} \end{split}\]

この問題を解くために、ラグランジュの未定乗数法を利用する。

Hide code cell source
# 二乗和が円になるイメージ
import numpy as np
import matplotlib.pyplot as plt
import itertools

R = 0.5
b1 = np.linspace(-1, 1, 100)
b2 = np.linspace(-1, 1, 100)
b = np.array(list(itertools.product(b1, b2)))
is_in_R = (b[:, 0]**2 + b[:, 1]**2) <= R

fig, ax = plt.subplots(figsize=[4, 4])
ax.scatter(b[~is_in_R, 0], b[~is_in_R, 1])
ax.scatter(b[is_in_R, 0], b[is_in_R, 1], color="orange")
Hide code cell output
<matplotlib.collections.PathCollection at 0x7f1d0ccda9b0>
../../../_images/7d0f21611fb31071eaed59654437c1743f4b6f43692fbe9373602a6b8ff54479.png

誤差関数の整理#

ラグランジュの未定乗数法を利用して、誤差関数を以下のように書くことができる。

\[ J({\boldsymbol{\beta}}) = \sum_{i=1}^n(y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^d \beta_j^2 \]

この右辺第二項は正則化項\(\lambda\)正則化パラメータと呼ばれる。\(\lambda=0\)のときは最小二乗法と同じ誤差関数になり、得られる推定量も最小二乗推定量と等しくなる。

一般的なラグランジュ双対問題とは異なり、リッジ回帰では最適な\(\lambda\)を推定することはせず、あらかじめ\(\lambda\)を指定して\(x\)を推定する。(誤差を最小にする\(\lambda\)はゼロであり、正則化の意味がなくなるためだと思われる。)

また、最初の制約問題で登場した\(R\)は誤差関数に含めない(おそらく誤差関数を\(\beta\)について微分したときに定数項の\(R\)は消えて特に影響をもたらさないため)

ちなみに行列表記するとこんな感じに表される。

\[\begin{split} \begin{align} J({\boldsymbol{\beta}}) &= \sum_{i=1}^n(y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^d \beta_j^2 \\ &= \| \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\|^2_2 + \lambda\| \boldsymbol{\beta}\|^2_2 \\ &= (\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})^\top (\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}) + \lambda \boldsymbol{\beta}^\top \boldsymbol{\beta} \end{align} \end{split}\]

リッジ回帰の推定量\(\hat{\boldsymbol{\beta}}^{\text{Ridge}}\)は解析的に解くことができ、

\[\begin{split} \begin{align} J(\boldsymbol{\beta}) &= (\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})^\top (\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}) + \lambda \boldsymbol{\beta}^\top \boldsymbol{\beta} \\ &= \boldsymbol{y}^\top \boldsymbol{y} - \boldsymbol{y}^\top \boldsymbol{X}\boldsymbol{\beta} - (\boldsymbol{X}\boldsymbol{\beta})^\top \boldsymbol{y} + (\boldsymbol{X}\boldsymbol{\beta})^\top (\boldsymbol{X}\boldsymbol{\beta}) + \lambda \boldsymbol{\beta}^\top \boldsymbol{\beta} \\ &= \boldsymbol{y}^\top \boldsymbol{y} - 2 \boldsymbol{\beta}^\top \boldsymbol{X}^\top \boldsymbol{y} + \boldsymbol{\beta}^\top \boldsymbol{X}^\top \boldsymbol{X} \boldsymbol{\beta} + \lambda \boldsymbol{\beta}^\top \boldsymbol{\beta} \end{align} \end{split}\]

なので、誤差関数の傾きがゼロ(誤差が最小値)の点を求めると

\[\begin{split} \frac{\partial J(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} = -2\boldsymbol{X}^\top\boldsymbol{y} + 2(\boldsymbol{X}^\top\boldsymbol{X})\boldsymbol{\beta} + 2\lambda\boldsymbol{\beta} =\boldsymbol{0} \\ \Longrightarrow (\boldsymbol{X}^\top\boldsymbol{X})\boldsymbol{\beta} + \lambda\boldsymbol{\beta} =\boldsymbol{X}^\top\boldsymbol{y} \\ \Longrightarrow (\boldsymbol{X}^\top\boldsymbol{X} + \lambda \boldsymbol{I})\boldsymbol{\beta} =\boldsymbol{X}^\top\boldsymbol{y} \end{split}\]

となり、

\[ \hat{\boldsymbol{\beta}}^{\text{Ridge}} = (\boldsymbol{X}^\top \boldsymbol{X} + \lambda \boldsymbol{I})^{-1} \boldsymbol{X}^\top \boldsymbol{y} \]

となる。

リッジ回帰の特徴#

リッジ回帰は制約をかけたことにより通常の線形回帰(最小二乗法)とは異なる特徴をもっている。

正則化#

線形回帰の最小二乗推定量\(\hat{\boldsymbol{\beta}}^{\text{LS}}\)は次のようなものだった。

\[ \hat{\boldsymbol{\beta}}^{\text{LS}} = (\boldsymbol{X}^\top \boldsymbol{X})^{-1} \boldsymbol{X}^\top \boldsymbol{y} \]

このとき、

  1. \(\boldsymbol{X}\)の列数が行数よりも多い(サンプルサイズより特徴量の次元数のほうが多い)

  2. 特徴量間の相関が非常に強い

といった状況においては、\(\boldsymbol{X}^\top \boldsymbol{X}\)が正則でなくなって逆行列が計算できなくなったり、あるいは推定が不安定になることがある。

そこでリッジ回帰の推定量\(\hat{\boldsymbol{\beta}}^{\text{Ridge}}\)では

\[ \hat{\boldsymbol{\beta}}^{\text{Ridge}} = (\boldsymbol{X}^\top \boldsymbol{X} + \lambda \boldsymbol{I})^{-1} \boldsymbol{X}^\top \boldsymbol{y} \]

と、\(\boldsymbol{X}^\top \boldsymbol{X}\)の対角成分に\(\lambda\)を足すことで尾根(ridge)を作り、正則にすることで逆行列が計算できるようにしている。

リッジ推定量が正則となる証明

\(X\)\(n\)次の実行列とする。実対称行列\(X^\top X\)は非負値定符号行列であるため、

\[ X^\top X = P \Gamma P^\top \]

と分解可能。ここで\(P\)は直交行列であり、\(\Gamma = \mathrm{diag}(\gamma_1, \cdots, \gamma_n)\)\(X^\top X\)の固有値(\(\gamma_1 \geq \cdots \geq \gamma_n \geq 0\))を対角成分にもつ対角行列。

もし\(\gamma_n = 0\)なら\(X^\top X\)の逆行列は存在せず、\(\gamma_n > 0\)なら逆行列は存在し、

\[\begin{split} \begin{aligned} (X^\top X)^{-1} &= (P \Gamma P^\top)^{-1}\\ &= P \Gamma^{-1} P^\top \quad (\because (ABC)^{-1} = (C^{-1} B^{-1} A^{-1}) であり、 Pは直交行列なのでP^\top = P^{-1})\\ &= P \operatorname{diag}(1 / \gamma_1, \ldots, 1 / \gamma_n) P^\top \end{aligned} \end{split}\]

となる。\(X^\top X\)の最小固有値が\(\gamma_n \to 0\)の場合、\(1/\gamma_n \to \infty\)になり逆行列が計算できない。

一方、リッジ推定量のように\(X^\top X + \lambda I\)とする(\(\lambda \in\mathbb{R}\))と、その逆行列は

\[\begin{split} \begin{aligned} (X^\top X + \lambda I)^{-1} &= (P \Gamma P^\top + \lambda I)^{-1}\\ &= \{ P (\Gamma + \lambda I) P^\top \}^{-1}\\ &= P (\Gamma + \lambda I)^{-1} P^\top\\ &= P \operatorname{diag}[1 / (\gamma_1 + \lambda I), \ldots, 1 / (\gamma_n + \lambda I)] P^\top \end{aligned} \end{split}\]

となる。こちらは\(\gamma_n \to 0\)の場合であっても\(1 / (\gamma_p + \lambda I)\)は無限大に発散することがないため、\(X^\top X + \lambda I\)は正則となる。

過学習の抑制#

リッジ回帰の誤差関数

\[ J(\beta)= \sum_{i=1}^n(y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^d \beta_j^2 \]

は、\(\lambda\)を大きくすると誤差に占める第二項の比重が大きくなり、パラメータ\(\beta_j\)の値をゼロに向けて縮小(shrink)させる。

パラメータが学習データに過学習して大きい値になっているような状況ではパラメータをうまく縮小させることによって過学習を抑制してモデルの汎化誤差を下げることができる。

推定量のバイアスとバリアンス#

正則化しない通常の最小二乗推定量はBLUE(最良線形不偏推定量:線形不偏推定量のなかでバリアンスが最小)だった。 リッジ回帰やlassoの推定量は不偏ではない(バイアスがある)推定量であるが、最小二乗推定量よりも小さなバリアンスとなる可能性がある。 そのため、最小二乗推定法を使用する線形回帰よりもリッジ回帰のほうが予測の2乗誤差を小さくする可能性がある。

\[\begin{split} \begin{aligned} \operatorname{Var}(\hat{\beta}^{\text{Ridge}}) &= \sigma^2 (X^\top X + \lambda I)^{-1} X^\top X(X^\top X + \lambda I)^{-1}\\ &\leq \sigma^2 (X^\top X)^{-1} = \operatorname{Var}(\hat{\beta}^{\text{LS}}) \end{aligned} \end{split}\]

Ridge Regression: Biased Estimation for Nonorthogonal Problems

https://hastie.su.domains/StatLearnSparsity_files/SLS.pdf

モンテカルロ・シミュレーション#

多項式をつかったデータに、多項式回帰をfittingしてみる

\[ y = \beta_0 + \beta_1 x + \beta_2 x^2 + u \]
import numpy as np
beta = np.array([3, 2, 1])

def gen_data(seed=0, n=500):
    np.random.seed(seed)
    x = np.random.uniform(-5, 3, size=n)
    X = np.array([np.ones(n), x, x**2]).T
    u = np.random.normal(scale=3, size=n)
    y = X @ beta + u
    return X, y

import matplotlib.pyplot as plt
X, y = gen_data(seed=0, n=30)
plt.scatter(X[:, 1], y)
<matplotlib.collections.PathCollection at 0x7f1d0cc38eb0>
../../../_images/59fb9c59e5811232f34ef4bcfb4d809055db9f387de3691992b683f31bb4ffdd.png
Hide code cell source
class OLS:
    def fit(self, X, y):
        self.beta_ = np.linalg.inv(X.T @ X) @ X.T @ y
        return self

    def predict(self, X):
        return X @ self.beta_


class Ridge:
    def __init__(self, lamb = 0.1):
        self.lambda_ = lamb

    def fit(self, X, y):
        d = X.shape[1]
        I = np.ones((d, d))
        self.beta_ = np.linalg.inv((X.T @ X) + self.lambda_ * I) @ X.T @ y
        return self

    def predict(self, X):
        return X @ self.beta_


from sklearn.metrics import mean_squared_error

results = []
for i in range(500):
    result = {}
    X_train, y_train = gen_data(seed=i, n=30)
    X_test, y_test = gen_data(seed=i+1, n=100)

    reg = OLS().fit(X_train, y_train)
    y_pred = reg.predict(X_test)
    result["ols_beta"] = reg.beta_[1]
    result["ols_error"] = mean_squared_error(y_test, y_pred)
    
    reg = Ridge(lamb=1).fit(X_train, y_train)
    y_pred = reg.predict(X_test)
    result["ridge_beta"] = reg.beta_[1]
    result["ridge_error"] = mean_squared_error(y_test, y_pred)

    results.append(result)

import pandas as pd
results = pd.DataFrame(results)
print(f"""
beta1

bias:
- ols: {beta[1] - results["ols_beta"].mean():.3f}
- ridge: {beta[1] - results["ridge_beta"].mean():.3f}

variance:
- ols: {results["ols_beta"].var():.3f}
- ridge: {results["ridge_beta"].var():.3f}
""")
beta1

bias:
- ols: -0.026
- ridge: 0.038

variance:
- ols: 0.115
- ridge: 0.110

ridgeのほうがvarianceが若干小さくbiasが大きくなっている

Hide code cell source
fig, ax = plt.subplots()
ax.hist(beta[1] - results["ols_beta"], label="OLS", alpha=0.5, bins=20)
ax.hist(beta[1] - results["ridge_beta"], label="Ridge", alpha=0.5, bins=20)
ax.axvline(beta[1] - results["ols_beta"].mean(), label="Bias(OLS)", color="steelblue")
ax.axvline(beta[1] - results["ridge_beta"].mean(), label="Bias(Ridge)", color="darkorange")
ax.legend()
ax.set(xlabel=r"$\beta_1 - \hat\beta_1$", ylabel="Frequency")
fig.show()
../../../_images/925448fe8cb48f25a71be7109b4657d7fff73f4cd87764162984061977d1823e.png
fig, ax = plt.subplots()
ax.hist(results["ols_error"], label="OLS", alpha=0.5, bins=20)
ax.hist(results["ridge_error"], label="Ridge", alpha=0.5, bins=20)
ax.axvline(results["ols_error"].mean(), label="Mean(OLS)", color="steelblue")
ax.axvline(results["ridge_error"].mean(), label="Mean(Ridge)", color="darkorange")
ax.legend()
ax.set(xlabel="Mean Squared Error", ylabel="Frequency")
fig.show()
../../../_images/578389b3890129e39754c612988e0e7aef33102f7d0749060558bbde9c95d754.png

参考文献#

リッジ回帰#

ラグランジュの未定乗数法#