L1正則化とL2正則化

L1正則化とL2正則化とは?

L1正則化とL2正則化は、過学習を防ぎ、機械学習モデルの汎化性能を向上させるために使用されるテクニックです。これらは正則化(Regularization)の手法の一部で、モデルの複雑さにペナルティを課すことで訓練データに対するオーバーフィットを避けるのが目的です。

この記事では意図的にオーバーフィットしそうなデータを生成し、L1正則化とL2正則化を行なった結果を見てみたいと思います。

データの生成

from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split

X, y = make_regression(n_samples=50, n_features=100, n_informative=5, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

データの生成はscikit-learnのmake_regressionを利用しています。
データのサンプル数に比べて特徴量の数を増やし、オーバーフィットを引き起こしそうなデータを生成しています。

正則化無しの線形回帰

最も基本的な線形回帰を適用してみます。

from sklearn.linear_model import LinearRegression

linear_model = LinearRegression()
linear_model.fit(X_train, y_train)

print("Training score:", linear_model.score(X_train, y_train))
print("Testing score:", linear_model.score(X_test, y_test))

結果は下記の通りとなりました。
テストデータに対しては0.525とうまく一般化できていなさそうです。

Training score: 1.0
Testing score: 0.5252064060418984

それでは、L1正則化、L2正則化の効果を比較してみます。

L1正則化(Lasso正則化)

L1正則化は、モデルの重みパラメータの絶対値の和に対してペナルティを課します。

from sklearn.linear_model import Lasso

lasso_model = Lasso(alpha=0.1)
lasso_model.fit(X_train, y_train)

print("Training score:", lasso_model.score(X_train, y_train))
print("Testing score:", lasso_model.score(X_test, y_test))

LassoはL1正則化を適用した線形回帰モデルです。
結果は下記の通りとなりました。テストデータに対しても高いパフォーマンスが出ています。

Training score: 0.9999815964026731
Testing score: 0.9999607225292272

L2正則化(Ridge正則化)

L2正則化は、モデルの重みパラメータの二乗和に対してペナルティを課します。

from sklearn.linear_model import Ridge

ridge_model = Ridge(alpha=0.1)
ridge_model.fit(X_train, y_train)

print("Training score:", ridge_model.score(X_train, y_train))
print("Testing score:", ridge_model.score(X_test, y_test))

RidgeはL2正則化を適用した線形回帰モデルです。
それでは結果を見てみます。

Training score: 0.9999986621360992
Testing score: 0.5434980044389284

やや通常の線形回帰よりも良いスコアとなりました。alphaは正則化の強さを制御する重要なハイパーパラメータですが、この値を最適化することによって予測性能をより最大化出来るかもしれません。これについては次の機会に実践してみたいと思います。

それでは最後に各モデルの係数をプロットしてみます。

import numpy as np
import matplotlib.pyplot as plt

linear_coeffs = linear_model.coef_
lasso_coeffs = lasso_model.coef_
ridge_coeffs = ridge_model.coef_

plt.figure(figsize=(15, 5))
plt.plot(np.abs(linear_coeffs), label='Linear Regression', marker='o')
plt.plot(np.abs(lasso_coeffs), label='Lasso Regression', marker='^')
plt.plot(np.abs(ridge_coeffs), label='Ridge Regression', marker='x')
plt.xlabel('Coefficient Index')
plt.ylabel('Coefficient Magnitude')
plt.yscale('log')
plt.title('Comparison of Coefficient Magnitudes')
plt.legend()
plt.grid(True)
plt.show()

このグラフは、通常の線形回帰モデル、L1正則化(Lasso回帰)を適用したモデル、そしてL2正則化(Ridge回帰)を適用したモデルの係数の絶対値を比較しています。係数の大きさ(絶対値)は対数スケールで表示されています。

  • 線形回帰モデルでは、いくつかの係数が大きな値を持ち、他の係数も0ではない値を持っていることがわかります。

  • Lasso回帰モデルでは、多くの係数が実際に0になっていることがわかります。これはL1正則化が特徴選択のような役割を果たし、不要な特徴量をモデルから排除する効果があることを示しています。

  • Ridge回帰モデルでは、すべての係数が0にはならず、しかし係数の絶対値が全体的に小さく抑えられていることがわかります。これはL2正則化が係数の大きさを制限し、過学習を防ぐ効果があることを示しています。