Elastic Net・LASSO・Ridge回帰モデルの作成|正則化手法を導入したPython機械学習モデルの構築

当ページには広告が含まれています。

こんにちは、DXCEL WAVEの運営者(@dxcelwave)です!

こんな方におすすめ!
  • 機械学習の回帰モデルに対する正則化手法の導入方法が知りたい
  • LASSO・Ridge回帰・Elastic Net法の概要およびPythonでのモデル作成方法が知りたい
目次

正則化とは?

正則化とは、過学習対策の手法であり、学習データへの過剰フィッティングに伴うモデル複雑化を抑制しながら、より単純な(低い次元の)モデルとして学習データを表現できることを目指した手法です。

正則化の仕組みは、モデルの学習指標である予測性能誤差(上図は誤差平方和SSEを例に記載)に対して、パラメータ(重み)にペナルティを科すための追加情報(バイアス)を導入することで、モデルの複雑性と学習データへの当てはまりの良さをバランスさせるのが特徴です。

正則化の具体的な内容についてはこちらの記事でまとめています。合わせてご覧下さい。

本記事では回帰モデルに正則化手法を取り入れるアプローチについて詳しく解説します。

回帰モデルに正則化手法を取り入れた代表的なアプローチ

機械学習の回帰問題に正則化を適用する場合、L1正則化とL2正則化が一般的に用いられます。

正則化を適用したアプローチには、LASSO回帰、Ridge回帰、Elastic Net法の3つが代表的です。

LASSOL1正則化
RidgeL2正則化
Elastic NetL1+L2正則化の混合

後述では上記アプローチに基づく回帰モデルの作成手順を「モデル学習」「評価」という観点別に解説します。

LASSO回帰(Least Absolute Shrinkage and Selection Operator regression)

LASSO回帰とは、L1ペナルティ付きの回帰モデルです。

上図にLASSOの予測性能誤差算出式を示します。モデル学習時は、正則化パラメータλの値によって、正則化の強さを調節します。(λが大きいほど、大きな重み係数wiは受けるペナルティが増加する)

LASSOの特徴として、正則化の強さによっては特定の重み係数wiが0になることがあります。このため、LASSOは教師ありの特徴選択手法としても用いることができます。

加えて、LASSOには制約があることも留意しましょう。データサンプル数(D)よりも特徴量の方が多い場合、モデル学習に用いる説明変数(I)の数は(0 < I <= D)とする必要があります。

Ridge回帰(Ridge regression)

リッジ回帰はL2ペナルティ付きの回帰モデルです。

LASSOとの違いは、ペナルティ項R(w)に重みの平方和の合計を用いる点です。

Elastic Net

Elastic NetはL1ペナルティとL2ペナルティ両方を使用したモデル作成アプローチであり、LASSOとRidge両方の側面を有します。

【事前準備】回帰モデル作成に必要なデータ

実際にPythonのScikit-learnライブラリを用いて正則化した回帰モデルを構築していきましょう!下記の手順でプログラムを構築していきます。

  • データセットの説明
  • データの準備
  • 回帰モデル学習
  • モデル性能評価

今回は機械学習モデル過程で必須となるデータクレンジングやグラフ可視化等の前処理プロセスは割愛しています。その代わり、モデル作成と評価方法を詳しく解説しております。

データセットの説明

データセットには、Boston Housingというデータセットを活用します。

1970年代後半におけるボストンの住宅情報とその地域における環境をまとめたデータセットであり、住宅価格の予測を目的とした回帰モデル作成のチュートリアルによく利用されます。

Boston Housingデータセットの説明変数および目的変数の概要はそれぞれ以下になります。

説明変数一覧

特徴量名概要
CRIM(地域人工毎の)犯罪発生率
ZN25,000平方フィート以上の住宅区画の割合
INDUS(地域人工毎の)非小売業の土地面積の割合
CHASチャールズ川沿いに立地しているかどうか(該当の場合は1、そうでない場合は0)
NOX窒素酸化物の濃度(単位:pphm)
RM平均部屋数/一戸
AGE1940年よりも古い家の割合
DIS5つのボストン雇用センターまでの重み付き距離
RAD主要な高速道路へのアクセス指数
TAX10,000ドルあたりの所得税率
PTRATIO(地域人工毎の)学校教師1人あたりの生徒数
B(地域人工毎の)アフリカ系アメリカ人居住者の割合
LSTAT低所得者の割合

目的変数一覧

特徴量名概要
MEDV住宅価格の中央値(単位 $1,000)

データの準備

前述したBoston Housingのデータセットを準備するために以下のコードを実行しましょう。

# データ前処理
import numpy as np
import pandas as pd

# データ可視化
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use("ggplot")
# %matplotlib inline

# グラフの日本語表記対応
from matplotlib import rcParams
rcParams["font.family"]     = "sans-serif"
rcParams["font.sans-serif"] = "Hiragino Maru Gothic Pro"

# データセット読込
from sklearn.datasets import load_boston
boston = load_boston()

# DataFrame作成
df = pd.DataFrame(boston.data)
df.columns = boston.feature_names
df["MEDV"] = boston.target

【実践】Lasso回帰モデルの作成・評価

下記に示す説明変数・目的変数をもとにLASSO回帰モデル用いてを作成・評価します。

説明変数目的変数以外の変数全て
目的変数MEDV

LASSO回帰モデルの学習

LASSO回帰モデルを作成するためのコードを下記に示します。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import Lasso

# 変数定義
X = df.iloc[:, :-1].values # 説明変数(目的変数以外)
y = df['MEDV'].values      # 目的変数(住宅価格の中央値)

# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

# LASSO回帰
lasso = Lasso(alpha=0.1)

# モデル学習
lasso.fit(X_train, y_train)

Lasso回帰モデルの概要

scikit-learnのLasso()メソッドを用いて回帰モデルを作成しています。

このメソッドで利用する引数には次のようなものがあります。引数で留意すべきはalphaであり、これが上述した正則化パラメータλに該当します。

Lasso(alpha=1.0,
      fit_intercept=True, 
      normalize='deprecated', 
      precompute=False, 
      copy_X=True, 
      max_iter=1000, 
      tol=0.0001, 
      warm_start=False, 
      positive=False, 
      random_state=None, 
      selection='cyclic'
     )
スクロールできます
引数名概要デフォルト
alpha正則化パラメータ(正則化の強さを指定)1.0
fit_interceptモデルの切片の計算要否(Falseの場合、切片=0のモデルになる)True
normalizeモデル学習前に説明変数を正規化するかどうか‘deprecated’
precompute計算を高速化するために事前計算されたグラム行列を使用するかどうかFalse
copy_XTrueの場合、メモリ内でデータを複製して実行。True
max_iter最大イテレーション数1000
tol多重共線性の許容値。許容値の値が小さいほど、多重共線性のレベルが高くなる。0.0001
warm_startTrueの場合、モデル学習の初期化に前の呼出情報を利用False
positiveTrueの場合、偏回帰係数は正の値を示す。False
random_state乱数シードNone
selection偏回帰係数の更新方法cyclic

【評価】RMSEおよび決定係数R2を用いた性能評価

RMSE(平均平方二乗誤差)と決定係数R2を用いて回帰モデルの性能を評価します。

from sklearn.metrics import r2_score            # 決定係数
from sklearn.metrics import mean_squared_error  # RMSE

# 予測値(Train)
y_train_pred = lasso.predict(X_train)

# 予測値(Test)
y_test_pred = lasso.predict(X_test)

# 平均平方二乗誤差(RMSE)
print('RMSE 学習: %.2f, テスト: %.2f' % (
        mean_squared_error(y_train, y_train_pred, squared=False), # 学習
        mean_squared_error(y_test, y_test_pred, squared=False)    # テスト
      ))

# 決定係数(R^2)
print('R^2 学習: %.2f, テスト: %.2f' % (
        r2_score(y_train, y_train_pred), # 学習
        r2_score(y_test, y_test_pred)    # テスト
      ))

# 出力結果
# RMSE 学習: 4.57, テスト: 5.37
# R^2 学習: 0.75, テスト: 0.65

上記決定係数R2に着目すると、学習データを使ったR2は0.75、テストデータを使ったR2は0.65であり、性能としてはまずまずの値となりました。

ここで回帰モデルの評価指標について詳しく知りたい方はこちらの記事をご覧下さい。

【評価】残差プロットによる可視化

LASSO回帰モデルの予測結果を残差プロットとして表現します。

# 予測値と残差をプロット(学習データ)
plt.scatter(y_train_pred,             # グラフのx値(予測値)  
            y_train_pred - y_train,   # グラフのy値(予測値と学習値の差)
            c='blue',                 # プロットの色
            marker='o',               # マーカーの種類
            s=40,                     # マーカーサイズ
            alpha=0.7,                # 透明度
            label='学習データ')         # ラベルの文字


# 予測値と残差をプロット(テストデータ)
plt.scatter(y_test_pred,            
            y_test_pred - y_test, 
            c='red',
            marker='o', 
            s=40,
            alpha=0.7,
            label='テストデータ')

# グラフの書式設定
plt.xlabel('予測値')
plt.ylabel('残差')
plt.legend(loc='upper left')
plt.hlines(y=0, xmin=-20, xmax=60, lw=2, color='black')
plt.xlim([-20, 60])
plt.ylim([-50, 40])
plt.tight_layout()

plt.show()

【実践】Ridge回帰(リッジ回帰)モデルの作成・評価

下記に示す説明変数・目的変数をもとにRidge回帰モデル用いてを作成・評価します。

説明変数目的変数以外の変数全て
目的変数MEDV

Ridge回帰モデルの学習

Ridge回帰モデルを作成するためのコードを下記に示します。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge


# 変数定義
X = df.iloc[:, :-1].values # 説明変数(目的変数以外)
y = df['MEDV'].values      # 目的変数(住宅価格の中央値)

# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

# Ridge回帰
ridge = Ridge(alpha=1.0)
# 学習
ridge.fit(X_train, y_train)

Ridge回帰モデルの概要

scikit-learnのRidge()メソッドを用いて回帰モデルを作成しています。

このメソッドで利用する引数には次のようなものがあります。

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正則化パラメータλに該当(正則化の強さを指定)1.0
fit_interceptモデルの切片の計算要否(Falseの場合、切片=0のモデルになる)True
normalizeモデル学習前に説明変数を正規化するかどうか‘deprecated’
copy_XTrueの場合、メモリ内でデータを複製して実行。True
max_iter最大イテレーション数None
tol多重共線性の許容値。許容値の値が小さいほど、多重共線性のレベルが高くなる。0.001
solverモデル学習時の計算ルーティン‘auto’
positiveTrueの場合、偏回帰係数は正の値を示す。False
random_state乱数シードNone

【評価】RMSEおよび決定係数R2を用いた性能評価

RMSE(平均平方二乗誤差)と決定係数R2を用いて回帰モデルの性能を評価します。

from sklearn.metrics import r2_score            # 決定係数
from sklearn.metrics import mean_squared_error  # RMSE

# 予測値(Train)
y_train_pred = ridge.predict(X_train)

# 予測値(Test)
y_test_pred = ridge.predict(X_test)

# 平均平方二乗誤差(RMSE)
print('RMSE 学習: %.2f, テスト: %.2f' % (
        mean_squared_error(y_train, y_train_pred, squared=False), # 学習
        mean_squared_error(y_test, y_test_pred, squared=False)    # テスト
      ))

# 決定係数(R^2)
print('R^2 学習: %.2f, テスト: %.2f' % (
        r2_score(y_train, y_train_pred), # 学習
        r2_score(y_test, y_test_pred)    # テスト
      ))

# 出力結果
# RMSE 学習: 4.49, テスト: 5.27
# R^2 学習: 0.76, テスト: 0.67

上記決定係数R2に着目すると、学習データを使ったR2は0.76、テストデータを使ったR2は0.67であり、LASSOより若干性能が改善されていることがわかります。

【評価】残差プロットによる可視化

Ridge回帰モデルの予測結果を残差プロットとして表現します。

# 予測値と残差をプロット(学習データ)
plt.scatter(y_train_pred,             # グラフのx値(予測値)  
            y_train_pred - y_train,   # グラフのy値(予測値と学習値の差)
            c='blue',                 # プロットの色
            marker='o',               # マーカーの種類
            s=40,                     # マーカーサイズ
            alpha=0.7,                # 透明度
            label='学習データ')         # ラベルの文字


# 予測値と残差をプロット(テストデータ)
plt.scatter(y_test_pred,            
            y_test_pred - y_test, 
            c='red',
            marker='o', 
            s=40,
            alpha=0.7,
            label='テストデータ')

# グラフの書式設定
plt.xlabel('予測値')
plt.ylabel('残差')
plt.legend(loc='upper left')
plt.hlines(y=0, xmin=-20, xmax=60, lw=2, color='black')
plt.xlim([-20, 60])
plt.ylim([-50, 40])
plt.tight_layout()

plt.show()

【実践】Elastic Netモデルの作成・評価

下記に示す説明変数・目的変数をもとにElastic Netの回帰モデル用いてを作成・評価します。

説明変数目的変数以外の変数全て
目的変数MEDV

回帰モデルの学習

Elastic Netモデルを作成するためのコードを下記に示します。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import ElasticNet

# 変数定義
X = df.iloc[:, :-1].values # 説明変数(目的変数以外)
y = df['MEDV'].values      # 目的変数(住宅価格の中央値)

# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

# Elastic Net
elasticnet = ElasticNet(alpha=1.0, l1_ratio=0.5)

# モデル学習
elasticnet.fit(X_train, y_train)

グラフで示すような正常値(青プロット)を学習させ、回帰モデルを作成しました。

Elastic Net法を用いた回帰モデルの概要

正則化の強さ(alpha)に加え、L1・L2ペナルティの比率を示すl1_ratioの設定が重要です。

例えばl1_ratio=0として設定すると、L2のペナルティは0になるため、LASSO回帰モデルと等しくなります。反対に、l1_ratio=1とした場合、L1ペナルティが0となるため、Ridge回帰と等しくなります。

ElasticNet(alpha=1.0,
           l1_ratio=0.5,
           fit_intercept=True, 
           normalize='deprecated', 
           precompute=False, 
           max_iter=1000, 
           copy_X=True, 
           tol=0.0001, 
           warm_start=False, 
           positive=False, 
           random_state=None, 
           selection='cyclic'
          )
引数名概要デフォルト
alpha正則化パラメータλに該当(正則化の強さを指定)1.0
l1_ratioL1ペナルティとL2ペナルティの比率0.5
fit_interceptモデルの切片の計算要否(Falseの場合、切片=0のモデルになる)True
normalizeモデル学習前に説明変数を正規化するかどうか‘deprecated’
precompute計算を高速化するために事前計算されたグラム行列を使用するかどうかFalse
copy_XTrueの場合、メモリ内でデータを複製して実行。True
max_iter最大イテレーション数1000
tol多重共線性の許容値。許容値の値が小さいほど、多重共線性のレベルが高くなる。0.0001
warm_startTrueの場合、モデル学習の初期化に前の呼出情報を利用False
positiveTrueの場合、偏回帰係数は正の値を示す。False
random_state乱数シードNone
selection偏回帰係数の更新方法cyclic

【評価】RMSEおよび決定係数R2を用いた性能評価

RMSE(平均平方二乗誤差)と決定係数R2を用いて回帰モデルの性能を評価します。

from sklearn.metrics import r2_score            # 決定係数
from sklearn.metrics import mean_squared_error  # RMSE

# 予測値(Train)
y_train_pred = elasticnet.predict(X_train)

# 予測値(Test)
y_test_pred = elasticnet.predict(X_test)

# 平均平方二乗誤差(RMSE)
print('RMSE 学習: %.2f, テスト: %.2f' % (
        mean_squared_error(y_train, y_train_pred, squared=False), # 学習
        mean_squared_error(y_test, y_test_pred, squared=False)    # テスト
      ))

# 決定係数(R^2)
print('R^2 学習: %.2f, テスト: %.2f' % (
        r2_score(y_train, y_train_pred), # 学習
        r2_score(y_test, y_test_pred)    # テスト
      ))

# 出力結果
# RMSE 学習: 4.94, テスト: 5.65
# R^2 学習: 0.71, テスト: 0.62

上記決定係数R2に着目すると、学習データを使ったR2は0.71、テストデータを使ったR2は0.62でした。

【評価】残差プロットによる可視化

回帰モデルの予測結果を残差プロットとして表現します。

# 予測値と残差をプロット(学習データ)
plt.scatter(y_train_pred,             # グラフのx値(予測値)  
            y_train_pred - y_train,   # グラフのy値(予測値と学習値の差)
            c='blue',                 # プロットの色
            marker='o',               # マーカーの種類
            s=40,                     # マーカーサイズ
            alpha=0.7,                # 透明度
            label='学習データ')         # ラベルの文字


# 予測値と残差をプロット(テストデータ)
plt.scatter(y_test_pred,            
            y_test_pred - y_test, 
            c='red',
            marker='o', 
            s=40,
            alpha=0.7,
            label='テストデータ')

# グラフの書式設定
plt.xlabel('予測値')
plt.ylabel('残差')
plt.legend(loc='upper left')
plt.hlines(y=0, xmin=-20, xmax=60, lw=2, color='black')
plt.xlim([-20, 60])
plt.ylim([-50, 40])
plt.tight_layout()

plt.show()

【参考】AI・機械学習における配信情報まとめ

当サイトではAI・機械学習における「基礎」から「最新のプログラミング手法」に至るまで幅広く解説しております。また「おすすめの勉強方法」をはじめ、副業・転職・フリーランスとして始める「AI・機械学習案件の探し方」についても詳しく言及しています。

【仕事探し】副業・転職・フリーランス

【教育】おすすめ勉強法

【参考】記事一覧

最後に

この記事が気に入ったら
フォローしてね!

目次