"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

3次式で生成したデータの線形回帰と罰則付き回帰(Ridge回帰・Lasso回帰)のサンプル/Python+scikit-learn

f:id:arakan_no_boku:20190707151819j:plain 

目次

3次式でデータを作成

今回は3次式の線形回帰問題をPythonでやってみます。

今回は以下のような一つの変数が式に複数回でてくる3次式をやってみます。

$$3x^3-2x+3$$

変数Xを-2から2の範囲の乱数で発生させて、上記式で計算した結果に-20から20の範囲で発生させた乱数をノイズとして加えたものを学習データとします。

学習データのグラフは例えば、こんな感じになります。

f:id:arakan_no_boku:20190712150659p:plain

今回は、このデータに対して、LinearRegression(線形回帰)・罰則付き回帰のRidge回帰とLasso回帰・ElasticNetをためします。

といっても。

今回は「それぞれのやり方をざっくり理解する」のが目的なので、ほんの上っ面だけしかやりませんが。

sklearnのLinearRegression(線形回帰)

最初にソースです。

sk_linear_sample04.py

import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
from sklearn.metrics import r2_score

# 変数2つを、-2から2の範囲の乱数で初期化
x = np.random.rand(300, 1) * 4 - 2
# ノイズはー5から5の範囲の乱数で生成する
noise = np.random.rand(300, 1) * 40 - 20
# 正解をもとめる y=3x - 2z -3
true_y = 3 * x ** 3 - 2 * x + 3
# ノイズを加える
y = true_y + noise
# 学習用
_x_train = x[:200]
y_train = y[:200]
# 予測用
_x_test = x[200:]
true_y_test = true_y[200:]
# 引数に使うため、2変数をまとめる
x_train = np.c_[_x_train**3, _x_train]
x_test = np.c_[_x_test**3, _x_test]
# クラスオブジェクトを生成
model = linear_model.LinearRegression()
# 学習する
model.fit(x_train, y_train)
# 予測する
predict_y = model.predict(x_test)
# グラフに書くための設定
plt.scatter(_x_train, y_train, marker="+", color="b")
plt.scatter(_x_test, predict_y, color="r")

# 決定係数を求める
r2_score = r2_score(true_y_test, predict_y)
print(r2_score)
# グラフを描画する
plt.show()

補足します。

学習のにはノイズありの_y、正解データはノイズなしの_true_yを使います。

そのため、以下のようにして学習用と予測用に元データを分けています。

#学習用
_x_train = x[:200]
y_train = y[:200]
#予測用
_x_test = x[200:]
true_y_test = true_y[200:]

さて。

実行した結果はこんな感じでした。

f:id:arakan_no_boku:20190712161225p:plain

やり方の確認なので、まあ、こんなものでしょう。

 

罰則付き回帰

今度は罰則付き回帰であるRidge回帰とLasso回帰・ElasticNetを試します。

罰則付き回帰について、ちょっとだけ補足です。

上記で使ったLinearRegression(線形回帰)は学習時に正解の値と予測値の差のみに着目して、それを最小にしていく考え方の「最小二乗法」を使っています。

mathtrain.jp

それに対して、数値の誤差に加えて、モデルの複雑度を加味するようにしたのが、罰則付き回帰です。

考え方としては同じですが、モデルの複雑度を反映させる方法の違いで「Ridge回帰」・「Lasso回帰」・「ElasticNet」などの種類があります。

jojoshin.hatenablog.com

 

これらは、scikit-learnを使うなら、簡単に試せます。

ソースとしては、上記のLinearRegressionのものとほぼ同じです。

書き換えるのはクラスオブジェクトを生成する一か所だけです。

LinearRegressionの場合はこうです。

model = linear_model.LinearRegression()

それを。

Redge回帰にするとき。

model = linear_model.Ridge()

Lasso回帰にするとき。

 model = linear_model.Lasso()

ElasticNetのときはこう

model = linear_model.ElasticNet()

書き換えるだけで試せます。

なので、個別のソースは掲載していません。

実行結果のグラフだけをのせておきます。

Ridge回帰の結果グラフ

sk_ridge_sample04.py

f:id:arakan_no_boku:20190712171509p:plain

Lasso回帰の結果グラフ

sk_lasso_sample04.py

f:id:arakan_no_boku:20190712171741p:plain

ElasticNetの結果グラフ

sk_elastic_sample04.py

f:id:arakan_no_boku:20190712172026p:plain

今回はこんなところで。

ではでは。