こんにちは、DXCEL WAVEの運営者(@dxcelwave)です!
- 機械学習の回帰モデルに対する正則化手法の導入方法が知りたい
- LASSO・Ridge回帰・Elastic Net法の概要およびPythonでのモデル作成方法が知りたい
正則化とは?
正則化とは、過学習対策の手法であり、学習データへの過剰フィッティングに伴うモデル複雑化を抑制しながら、より単純な(低い次元の)モデルとして学習データを表現できることを目指した手法です。
正則化の仕組みは、モデルの学習指標である予測性能誤差(上図は誤差平方和SSEを例に記載)に対して、パラメータ(重み)にペナルティを科すための追加情報(バイアス)を導入することで、モデルの複雑性と学習データへの当てはまりの良さをバランスさせるのが特徴です。
正則化の具体的な内容についてはこちらの記事でまとめています。合わせてご覧下さい。
【AI・機械学習】正則化とは|L1・L2正則化の概要解説
機械学習モデル開発において、過学習対策として取り扱われる「正則化」について詳しく解説します。「正則化とは?」「L1・L2正則化って何?」という疑問にお応えします。
本記事では回帰モデルに正則化手法を取り入れるアプローチについて詳しく解説します。
回帰モデルに正則化手法を取り入れた代表的なアプローチ
機械学習の回帰問題に正則化を適用する場合、L1正則化とL2正則化が一般的に用いられます。
正則化を適用したアプローチには、LASSO回帰、Ridge回帰、Elastic Net法の3つが代表的です。
LASSO | L1正則化 |
Ridge | L2正則化 |
Elastic Net | L1+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 | (地域人工毎の)犯罪発生率 |
ZN | 25,000平方フィート以上の住宅区画の割合 |
INDUS | (地域人工毎の)非小売業の土地面積の割合 |
CHAS | チャールズ川沿いに立地しているかどうか(該当の場合は1、そうでない場合は0) |
NOX | 窒素酸化物の濃度(単位:pphm) |
RM | 平均部屋数/一戸 |
AGE | 1940年よりも古い家の割合 |
DIS | 5つのボストン雇用センターまでの重み付き距離 |
RAD | 主要な高速道路へのアクセス指数 |
TAX | 10,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_X | Trueの場合、メモリ内でデータを複製して実行。 | True |
max_iter | 最大イテレーション数 | 1000 |
tol | 多重共線性の許容値。許容値の値が小さいほど、多重共線性のレベルが高くなる。 | 0.0001 |
warm_start | Trueの場合、モデル学習の初期化に前の呼出情報を利用 | False |
positive | Trueの場合、偏回帰係数は正の値を示す。 | 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であり、性能としてはまずまずの値となりました。
ここで回帰モデルの評価指標について詳しく知りたい方はこちらの記事をご覧下さい。
【AI・機械学習】回帰モデルの性能評価および評価指標の解説|決定係数・RMSE・MAE・残差プロット
機械学習の性能評価方法の中で「回帰モデルはどうやって評価するの?」本記事ではその疑問に回答します。具体的に、決定係数、RMSE、MAE等の評価指標があり、それら特徴・利用シーンを1つずつ詳しく解説します。
【評価】残差プロットによる可視化
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_X | Trueの場合、メモリ内でデータを複製して実行。 | True |
max_iter | 最大イテレーション数 | None |
tol | 多重共線性の許容値。許容値の値が小さいほど、多重共線性のレベルが高くなる。 | 0.001 |
solver | モデル学習時の計算ルーティン | ‘auto’ |
positive | Trueの場合、偏回帰係数は正の値を示す。 | 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_ratio | L1ペナルティとL2ペナルティの比率 | 0.5 |
fit_intercept | モデルの切片の計算要否(Falseの場合、切片=0のモデルになる) | True |
normalize | モデル学習前に説明変数を正規化するかどうか | ‘deprecated’ |
precompute | 計算を高速化するために事前計算されたグラム行列を使用するかどうか | False |
copy_X | Trueの場合、メモリ内でデータを複製して実行。 | True |
max_iter | 最大イテレーション数 | 1000 |
tol | 多重共線性の許容値。許容値の値が小さいほど、多重共線性のレベルが高くなる。 | 0.0001 |
warm_start | Trueの場合、モデル学習の初期化に前の呼出情報を利用 | False |
positive | Trueの場合、偏回帰係数は正の値を示す。 | 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・機械学習案件の探し方」についても詳しく言及しています。
【仕事探し】副業・転職・フリーランス
【教育】おすすめ勉強法
【参考】記事一覧
最後に
お問い合わせフォーム
上記課題に向けてご気軽にご相談下さい。
お問い合わせはこちら