【Scikit-learn】ボストン住宅価格で標準化と正規化の効果を検討(Lasso、ElasticNet)[Python]

  • URLをコピーしました!
目次

機械学習ライブラリScikit-learn

前回、機械学習ライブラリScikit-learnのボストンの住宅価格を予想するのにデータを標準化、正規化をした後、LinearRegressionモデルで機械学習をしてみました。

今回は同じようにして標準化、正規化したデータを使って、Lassoモデル、ElasticNetモデルで機械学習を行ってみます。

まずはいつも通りデータの読み込みから。

<セル1>

from sklearn.datasets import load_boston
import pandas as pd

boston = load_boston()

df = pd.DataFrame(boston.data, columns=boston.feature_names)

df["MEDV"] = boston.target

df

実行結果

そしてデータを標準化と正規化をしていきます。

<セル2>

from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler

x = df.loc[:, ["CRIM", "RM", "LSTAT"]]
y = df.loc[:, "MEDV"]

std_model = StandardScaler()
x_std = std_model.fit_transform(x)

norm_model = MinMaxScaler()
x_norm = norm_model.fit_transform(x)

実行結果

これで準備は完了です。

前回のプログラムを分かりやすく書き換える

前回、LinearRegressionモデルで標準化、正規化の効果を試したプログラムにLassoモデル、ElasticNetモデルを組み込んでいこうと思います。

<セル2>

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
import numpy as np

trial = 100

pred_lr_score = []; pred_std_lr_score =[]; pred_norm_lr_score = []
for i in range(trial):
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, train_size=0.8)
    x_std_train, x_std_test, y_std_train, y_std_test = train_test_split(x_std, y, test_size=0.2, train_size=0.8)
    x_norm_train, x_norm_test, y_norm_train, y_norm_test = train_test_split(x_norm, y, test_size=0.2, train_size=0.8)
    
    model_lr = LinearRegression()
    model_std_lr = LinearRegression()
    model_norm_lr = LinearRegression()

    model_lr.fit(x_train, y_train)
    model_std_lr.fit(x_std_train, y_std_train)
    model_norm_lr.fit(x_norm_train, y_norm_train)

    pred_lr = model_lr.predict(x_test)
    pred_std_lr = model_std_lr.predict(x_std_test)
    pred_norm_lr = model_norm_lr.predict(x_norm_test)
    
    pred_lr_score.append(r2_score(y_test, pred_lr))
    pred_std_lr_score.append(r2_score(y_std_test, pred_std_lr))
    pred_norm_lr_score.append(r2_score(y_norm_test, pred_norm_lr))

pred_lr_ave = np.average(np.array(pred_lr_score))
pred_std_lr_ave = np.average(np.array(pred_std_lr_score))
pred_norm_lr_ave = np.average(np.array(pred_norm_lr_score))

print(pred_lr_ave, pred_std_lr_ave, pred_norm_lr_ave)

実行結果
0.6251955895149124 0.6285481272482702 0.6384084236567933

ただ次々とモデルを組み込んでいくと、どこがどのモデルのプログラムか分からなくなるので、機械学習の部分を書き換えます。

どう書き換えるかというと、処理ごとで分割していたところを、モデルごとに分割するという感じで書き換えます。

ということでこの部分を、

model_lr = LinearRegression()
model_std_lr = LinearRegression()
model_norm_lr = LinearRegression()

model_lr.fit(x_train, y_train)
model_std_lr.fit(x_std_train, y_std_train)
model_norm_lr.fit(x_norm_train, y_norm_train)

pred_lr = model_lr.predict(x_test)
pred_std_lr = model_std_lr.predict(x_std_test)
pred_norm_lr = model_norm_lr.predict(x_norm_test)
    
pred_lr_score.append(r2_score(y_test, pred_lr))
pred_std_lr_score.append(r2_score(y_std_test, pred_std_lr))
pred_norm_lr_score.append(r2_score(y_norm_test, pred_norm_lr))

こう書き換えます。

model_lr = LinearRegression()
model_lr.fit(x_train, y_train)
pred_lr = model_lr.predict(x_test)
pred_lr_score.append(r2_score(y_test, pred_lr))
    
model_std_lr = LinearRegression()
model_std_lr.fit(x_std_train, y_std_train)
pred_std_lr = model_std_lr.predict(x_std_test)
pred_std_lr_score.append(r2_score(y_std_test, pred_std_lr))
    
model_norm_lr = LinearRegression()
model_norm_lr.fit(x_norm_train, y_norm_train)
pred_norm_lr = model_norm_lr.predict(x_norm_test)
pred_norm_lr_score.append(r2_score(y_norm_test, pred_norm_lr))

これにより一つの段落が一つのモデルの処理になり、後で分かりやすくなります。

Lassoモデル、ElasticNetモデルを組み込む

ではLassoモデル、ElasticNetモデルを組み込んでいきましょう。

追加するライブラリはモデルの2つ。

from sklearn.linear_model import Lasso
from sklearn.linear_model import ElasticNet

そして後はLassoモデルの処理とElasticNetモデルの処理を追加していきます。

まずはLassoモデルの処理から。

model_lasso = Lasso()
model_lasso.fit(x_train, y_train)
pred_lasso = model_lasso.predict(x_test)
pred_lasso_score.append(r2_score(y_test, pred_lasso))
    
model_std_lasso = Lasso()
model_std_lasso.fit(x_std_train, y_std_train)
pred_std_lasso = model_std_lasso.predict(x_std_test)
pred_std_lasso_score.append(r2_score(y_std_test, pred_std_lasso))
    
model_norm_lasso = Lasso()
model_norm_lasso.fit(x_norm_train, y_norm_train)
pred_norm_lasso = model_norm_lasso.predict(x_norm_test)
pred_norm_lasso_score.append(r2_score(y_norm_test, pred_norm_lasso))

次にElasticNetモデルの処理。

model_en = ElasticNet()
model_en.fit(x_train, y_train)
pred_en = model_en.predict(x_test)
pred_en_score.append(r2_score(y_test, pred_en))
    
model_std_en = ElasticNet()
model_std_en.fit(x_std_train, y_std_train)
pred_std_en = model_std_en.predict(x_std_test)
pred_std_en_score.append(r2_score(y_std_test, pred_std_en))
    
model_norm_en = ElasticNet()
model_norm_en.fit(x_norm_train, y_norm_train)
pred_norm_en = model_norm_en.predict(x_norm_test)
pred_norm_en_score.append(r2_score(y_norm_test, pred_norm_en))

どちらも最初の段落が何もしていないデータ、2段目が標準化したデータ、3段目が正規化したデータでの処理です。

後は平均値の計算、表示を加えるとこんな感じになります。

<セル3>

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import Lasso
from sklearn.linear_model import ElasticNet
from sklearn.metrics import r2_score
import numpy as np

trial = 100

pred_lr_score = []; pred_std_lr_score =[]; pred_norm_lr_score = []
pred_lasso_score = []; pred_std_lasso_score = []; pred_norm_lasso_score = []
pred_en_score = []; pred_std_en_score = []; pred_norm_en_score = []

for i in range(trial):
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, train_size=0.8)
    x_std_train, x_std_test, y_std_train, y_std_test = train_test_split(x_std, y, test_size=0.2, train_size=0.8)
    x_norm_train, x_norm_test, y_norm_train, y_norm_test = train_test_split(x_norm, y, test_size=0.2, train_size=0.8)
    
    model_lr = LinearRegression()
    model_lr.fit(x_train, y_train)
    pred_lr = model_lr.predict(x_test)
    pred_lr_score.append(r2_score(y_test, pred_lr))
    
    model_std_lr = LinearRegression()
    model_std_lr.fit(x_std_train, y_std_train)
    pred_std_lr = model_std_lr.predict(x_std_test)
    pred_std_lr_score.append(r2_score(y_std_test, pred_std_lr))
    
    model_norm_lr = LinearRegression()
    model_norm_lr.fit(x_norm_train, y_norm_train)
    pred_norm_lr = model_norm_lr.predict(x_norm_test)
    pred_norm_lr_score.append(r2_score(y_norm_test, pred_norm_lr))
    
    model_lasso = Lasso()
    model_lasso.fit(x_train, y_train)
    pred_lasso = model_lasso.predict(x_test)
    pred_lasso_score.append(r2_score(y_test, pred_lasso))
    
    model_std_lasso = Lasso()
    model_std_lasso.fit(x_std_train, y_std_train)
    pred_std_lasso = model_std_lasso.predict(x_std_test)
    pred_std_lasso_score.append(r2_score(y_std_test, pred_std_lasso))
    
    model_norm_lasso = Lasso()
    model_norm_lasso.fit(x_norm_train, y_norm_train)
    pred_norm_lasso = model_norm_lasso.predict(x_norm_test)
    pred_norm_lasso_score.append(r2_score(y_norm_test, pred_norm_lasso))
    
    model_en = ElasticNet()
    model_en.fit(x_train, y_train)
    pred_en = model_en.predict(x_test)
    pred_en_score.append(r2_score(y_test, pred_en))
    
    model_std_en = ElasticNet()
    model_std_en.fit(x_std_train, y_std_train)
    pred_std_en = model_std_en.predict(x_std_test)
    pred_std_en_score.append(r2_score(y_std_test, pred_std_en))
    
    model_norm_en = ElasticNet()
    model_norm_en.fit(x_norm_train, y_norm_train)
    pred_norm_en = model_norm_en.predict(x_norm_test)
    pred_norm_en_score.append(r2_score(y_norm_test, pred_norm_en))

pred_lr_ave = np.average(np.array(pred_lr_score))
pred_std_lr_ave = np.average(np.array(pred_std_lr_score))
pred_norm_lr_ave = np.average(np.array(pred_norm_lr_score))
pred_lasso_ave = np.average(np.array(pred_lasso_score))
pred_std_lasso_ave = np.average(np.array(pred_std_lasso_score))
pred_norm_lasso_ave = np.average(np.array(pred_norm_lasso_score))
pred_en_ave = np.average(np.array(pred_en_score))
pred_std_en_ave = np.average(np.array(pred_std_en_score))
pred_norm_en_ave = np.average(np.array(pred_norm_en_score))

print(pred_lr_ave, pred_std_lr_ave, pred_norm_lr_ave, pred_lasso_ave, pred_std_lasso_ave, pred_norm_lasso_ave, pred_en_ave, pred_std_en_ave, pred_norm_en_ave)

実行結果
0.6271352730578258 0.6273988042003288 0.6430302631752858 0.5924658782746538 0.6107730695970007 0.23101389811233983 0.5773827966016526 0.5853423422079327 0.04969310466296231

なかなか膨大なプログラムになってきましたが、とりあえず今回はこのままいきましょう。

Lassoモデル、ElasticNetモデルに対する標準化、正規化の効果を見てみる

それではプログラムも完成したということで、Lassoモデル、ElasticNetモデルに対する標準化、正規化の効果を検討してみましょう。

いつも通りプログラムで100回試行して平均値を出し、それを5回試してみます。

モデル標準化 or 正規化1回目2回目3回目4回目5回目
LinearRegressionなし0.627140.638410.635940.630240.61714
LinearRegression標準化0.627400.631550.627620.640760.63498
LinearRegression正規化0.643030.631570.633210.633130.62717
Lassoなし0.592470.596870.600090.603840.58902
Lasso標準化0.610770.614120.609350.620000.61583
Lasso正規化0.231010.225440.228420.229910.23005
ElasticNetなし0.577380.582060.585180.589320.57585
ElasticNet標準化0.585340.586970.583700.594130.58964
ElasticNet正規化0.049690.049090.048600.046420.04938

さぁわかりにくいですね。

表をそれぞれのモデルに分割して、さらにそれぞれの回で良くなったものを青色で、悪くなったものを赤色にしてみましょう。

まずはLinearRegressionから。

モデル標準化 or 正規化1回目2回目3回目4回目5回目
LinearRegressionなし0.627140.638410.635940.630240.61714
LinearRegression標準化0.627400.631550.627620.640760.63498
LinearRegression正規化0.643030.631570.633210.633130.62717

何もしない vs 標準化 では2:3でわずかに標準化した方がいい。

何もしない vs 正規化 ではこちらも2:3でわずかに正規化した方がいい。

といっても本当にわずかな差なので、前回の結論通りほぼ結果は変わっていないと言っていいでしょう。

次にLassoモデル。

モデル標準化 or 正規化1回目2回目3回目4回目5回目
Lassoなし0.592470.596870.600090.603840.58902
Lasso標準化0.610770.614120.609350.620000.61583
Lasso正規化0.231010.225440.228420.229910.23005

何もしない vs 標準化 では0:5で標準化した方がいい。

何もしない vs 正規化 では5:0で何もしない方がいい。

標準化に関しては、ここまで差が出てくれるなら間違いなく良くなっていると感じられます。

ただ正規化に関しては、どこかでプログラムを間違えたんじゃないかというくらい結果が悪くなっています。

Lassoモデルと正規化は相性が悪いのでしょうか?

ちゃんとした知識がないと答えるのが難しいところだと思いますので、とりあえず放置ということで。

次にElasticNetモデル。

モデル標準化 or 正規化1回目2回目3回目4回目5回目
ElasticNetなし0.577380.582060.585180.589320.57585
ElasticNet標準化0.585340.586970.583700.594130.58964
ElasticNet正規化0.049690.049090.048600.046420.04938

何もしない vs 標準化 では 1:4で標準化した方がいい。

何もしない vs 正規化 では 5:0で何もしない方がいい。

ということでElasticNetモデルでは、標準化するとわずかによい感じがしますが、正規化すると全くダメになってしまいました。

こちらも原因を究明するには、ちゃんとした知識がないと難しいのではないかと感じます。

現段階では漠然とした知識で進めているのですが、こういうものなんだという感覚を養った後に知識をインプットしたときに入りやすいので、とりあえずこのまま進めていきます。

ということで今回の結果としては、

  • Lassoモデルで標準化すると精度は良くなる。
  • LassoモデルでもElasticNetモデルでも正規化は全く予想がうまくいかなくなった。

ということでした。

次回はさらにRidgeRegression、SVRで同じように標準化、正規化を試していきましょう。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次