この演習ではscikt-learnを用いてRidge回帰を行う. 演習:多項式回帰および 演習:scikit-learnを用いた多項式回帰では, 9次多項式の回帰で過学習が起きていた.Ridge回帰を用いることで過学習が抑制されることを確認する.
下記のようにライブラリのインポートが必要
#%matplotlib inline # jupyter notebookでは必要.JupyterLabでは不要
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error, root_mean_squared_error
演習1:データの標準化
ここではデータの標準化のテストを行う.下記の行列(2次元配列)をnumpyなどを用いて 標準化せよ.平均ゼロ,分散1になっているか確認もすること.
x = np.array([[1, 4, 2], [3, 7, 2], [8, 5, 9]])
x # jupyterで表示用
z = ??? # xを標準化
scikit-learnにデータを標準化する機能があるのでそれを使って同じ結果になるか確認する.
sklearn.preprocessing.StandardScaler
ss = StandardScaler() # インスタンスの作成
z = ss.fit_transform(x) # fitしてtransform
z # jupyterで表示用
また,次の行列はどうなるか考えよ.
x = np.array([[1, 4, 2], [1, 7, 2], [1, 5, 9]])
x # jupyterで表示用
演習2:データの準備
演習:多項式回帰と同様にsin関数にガウスノイズを加えたデータを10点用意してプロットせよ. ただの復習.
xa = ???
yt = ???
x = ???
tt = ???
err = ???
t = tt + err
plt.plot(xa, yt)
plt.plot(x, t, 'o')
また,今回はテストデータとしてさらに4点同様に準備せよ.訓練データとともにグラフに表示する.
x_test = ??? # ランダムに4点
tt_test = ???
err_test = ???
t_test = tt_test + err_test
plt.plot(xa, yt)
plt.plot(x, t, 'o') # 訓練データ10点をプロット
plt.plot(x_test, t_test, 'v') # テストデータ4点をプロット
演習3:計画行列の標準化
作成した10点のデータに関して,多項式回帰を行うための計画行列を作成せよ. 多項式は9次のものを用いる.
def design_matrix(x, m):
???
???
return dmat
M = 9
phi = design_matrix(x, M) # 計画行列作成
phi
多項式回帰の場合,$x^0$の定数項が計画行列に入っていると標準化できないので, その列を外して,計画行列を修正せよ.
phi = ??? # 計画行列の修正
phi # jupyterで表示用
念の為,計画行列のshapeを確認する. 10行9列の行列になるはず.
phi.shape # 計画行列のshape確認
後の使用のために,テストデータの計画行列も作成せよ.4行9列になるはず.
M = 9
phi_test = ???
phi_test = ??? # 定数項を外す
phi_test.shape # テストデータの計画行列のshape確認 4点なら4行9列になるはず
計画行列を標準化せよ.
ss = ???
phi_std = ???
phi_std # jupyter表示用
同様にテストデータも標準化せよ.注意点としてはテストデータは訓練データと同じスケーリングパラメーターを使う必要があるのでfit
はせずに,transform
だけ行うこと.
phi_test_std = ???
phi_test_std # jupyter表示用
演習4:Ridge回帰
sklearn.linear_model.Ridge(alpha=1.0, *, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver='auto', random_state=None)
上で計算した標準化された計画行列を用いてRidge回帰を行い,予測モデルをプロットせよ.
ただし,ハイパーパラメータalpha
に関してはここでは0
と0.1
で固定して2通りの予測を行う.
計画行列から外した定数項の部分はfit_intercept=True
にしてここで考慮する.(デフォルトでTrue
なので省略可能)
使い方はLinearRegression
とほぼ同じ.
まずはalpha = 0.0
(つまり最小二乗法).ここではインスタンス化にridge0
という変数名を用いることにする.
ridge0 = Ridge(alpha=0.0, fit_intercept=True)
ridge0.???? # 訓練データをfit
フィッティングしたら係数と切片を確認.
ridge0.coef_ # 係数
ridge0.intercept_ # 切片
訓練データに対する決定係数も確認できる.
ridge0.score(phi_std, t) # 決定係数
訓練データに対する予測値も計算して変数に格納しておく(predict
を使う).
y0 = ridge0.predict(???) # 訓練データに対する予測値を求めておく
xa
に対する予測値を計算して,(連続的な)予測モデルをプロットする.
phi_xa = ??? # xaの計画行列
phi_xa = ??? # 計画行列から定数項を外す
phi_xa_std = ss.??? # 標準化.ただしfitはしない!同じスケーリングパラメーターを使ってtransformする
ya0 = ridge0.???? # xaに対する予測値
plt.plot(xa, yt) # 元になるsin関数をプロット
plt.plot(x, t, 'o') # データ10点をプロット
plt.plot(x_test, t_test, 'v') # テストのデータ4点をプロット
plt.plot(xa, ya0) # 連続的な予測モデルをプロット
plt.ylim(-1.5, 1.5)
結果は最小二乗法と同様に過学習しているはず.
事前に用意しておいたテストデータ4点に対する予測値も計算せよ.
y0_test = ridge0.predict(???) # テストデータに対する予測値(4つ)
訓練データおよびテストデータ両方に対して,横軸が真値,縦軸が予測値のグラフを作成する.
plt.plot(t, y0, 'o', label="training")
plt.plot(t_test, y0_test, 'v', label="test")
plt.plot([-1.5, 1.5], [-1.5, 1.5]) # y = xの基準線
plt.ylim(-1.5, 1.5)
plt.xlabel('True')
plt.ylabel('Predicted')
plt.legend()
plt.title('OLS')
次にalpha = 0.1
.インスタンス化にはridge1という変数名を用いることにする.
ridge1 = Ridge(alpha=0.1)
ridge1.??? # 訓練データのfit
y1 = ridge1.??? # 訓練データに対する予測値
ya1 = ridge1.??? # 連続的な予測モデル
plt.plot(xa, yt) # 元になるsin関数をプロット
plt.plot(x, t, 'o') # データ10点をプロット
plt.plot(x_test, t_test, 'v') # テストのデータ4点をプロット
plt.plot(xa, ya1) # 予測モデルをプロット
plt.ylim(-1.5, 1.5)
過学習が抑制されたことを確認する.同様に係数,決定係数を確認する.
ridge1.coef_ # 係数
ridge1.intercept_ # 切片
ridge1.score(phi_std, t) # 決定係数
決定係数は最小二乗法の時と比べて下がっている(過学習が抑制された)が汎化性能は上がっている.
事前に用意しておいたテストデータ4点に対する予測値も計算し,上記と同様に真値と予測値のグラフを表示せよ.
y1_test = ridge1.???
plt.plot(t, y1, 'o', label="training")
plt.plot(t_test, y1_test, 'v', label="test")
plt.plot([-1.5, 1.5], [-1.5, 1.5]) # y = xの基準線
plt.ylim(-1.5, 1.5)
plt.xlabel('True')
plt.ylabel('Predicted')
plt.legend()
plt.title('Ridge')
演習5:誤差の計算
決定係数でも予測がどれくらい合っているかを評価できるが,誤差がどれくらいあるかは分かりづらい.
平均二乗平方根誤差(root-mean-square error: RMSE)を用いてalpha = 0.0 と 0.1
で訓練データとテストデータの予測モデルとの誤差を計算せよ.
scikit-learnにはMSEやRMSEを計算できるmean_squared_error
やroot_mean_squared_error
が用意されている.
sklearn.metrics.mean_squared_error
sklearn.metrics.root_mean_squared_error
sklearn.metrics.mean_squared_error(y_true, y_pred, *, sample_weight=None, multioutput='uniform_average', squared=True)
alpha = 0
print('training: RMSE = ', mean_squared_error(???, ???))
print('test: RMSE = ', root_mean_squared_error(???, ???))
alpha = 0.1
print('training: RMSE = ', mean_squared_error(???, ???))
print('test: RMSE = ', root_mean_squared_error(???, ???))