筑波大学の機械学習講座:課題のPythonスクリプト部分を作りながらsklearnを勉強する (1)
筑波大学の機械学習講座:課題のPythonスクリプト部分を作りながらsklearnを勉強する (2)
筑波大学の機械学習講座:課題のPythonスクリプト部分を作りながらsklearnを勉強する (3)
https://github.com/legacyworld/sklearn-basic
課題 3.4 多項式単回帰の正則化
さて、今回はリッジ回帰である。
Youtubeの解説はないようにみえるが、一部結果が第4回(1) 9分45秒あたりにある。
ソースコードとしては課題 3.2とほぼほぼ同じである。
今回の課題では次数は30に固定している。
その代わりに正則化パラメータを[1e-30,1e-20,1e-10,1e-5, 1e-3,1e-2,1e-1, 1,10,100]
で動かしていく。
ソースコード内では正則化パラメータはalpha
としている。Pythonのlambda
は予約されているので。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures as PF
from sklearn import linear_model
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import cross_val_score
DEGREE = 30
def true_f(x):
return np.cos(1.5 * x * np.pi)
np.random.seed(0)
n_samples = 30
# 描画用のx軸データ
x_plot = np.linspace(0,1,100)
# 訓練データ
x_tr = np.sort(np.random.rand(n_samples))
y_tr = true_f(x_tr) + np.random.randn(n_samples) * 0.1
# Matrixへ変換
X_tr = x_tr.reshape(-1,1)
X_plot = x_plot.reshape(-1,1)
degree = DEGREE
alpha_list = [1e-30,1e-20,1e-10,1e-5, 1e-3,1e-2,1e-1, 1,10,100]
for alpha in alpha_list:
plt.scatter(x_tr,y_tr,label="Training Samples")
plt.plot(x_plot,true_f(x_plot),label="True")
plt.xlim(0,1)
plt.ylim(-2,2)
filename = f"{alpha}.png"
pf = PF(degree=degree,include_bias=False)
linear_reg = linear_model.Ridge(alpha=alpha)
steps = [("Polynomial_Features",pf),("Linear_Regression",linear_reg)]
pipeline = Pipeline(steps=steps)
pipeline.fit(X_tr,y_tr)
plt.plot(x_plot,pipeline.predict(X_plot),label="Model")
y_predict = pipeline.predict(X_tr)
mse = mean_squared_error(y_tr,y_predict)
scores = cross_val_score(pipeline,X_tr,y_tr,scoring="neg_mean_squared_error",cv=10)
plt.title(f"Degree: {degree}, Lambda: {alpha}\nTrainErr: {mse:.2e} TestErr: {-scores.mean():.2e}(+/- {scores.std():.2e})")
plt.legend()
plt.savefig(filename)
plt.clf()
print(f"正則化パラメータ = {alpha}, 訓練誤差 = {mse}, テスト誤差 = {-scores.mean():.2e}")
変更しているのは
linear_reg = linear_model.Ridge(alpha=alpha)
だけである。
このプログラムを実行すると以下のようなWarningが出る。
/usr/local/lib64/python3.6/site-packages/sklearn/linear_model/_ridge.py:190: UserWarning: Singular matrix in solving dual problem. Using least-squares solution instead.
warnings.warn("Singular matrix in solving dual problem. Using "
これはコレスキー分解というところで出ているようなのだがよくわからなかった。
try:
# Note: we must use overwrite_a=False in order to be able to
# use the fall-back solution below in case a LinAlgError
# is raised
dual_coef = linalg.solve(K, y, sym_pos=True,overwrite_a=False)
except np.linalg.LinAlgError:
warnings.warn("Singular matrix in solving dual problem. Using "
"least-squares solution instead.")
dual_coef = linalg.lstsq(K, y)[0]
連立方程式が解けないから最小二乗法でやるよ、ということのようだが・・・
1e-30,1e-20
だけで出る理由は何なのかわからなかった。
実行結果
正則化パラメータ = 1e-30, 訓練誤差 = 0.002139325105436034, テスト誤差 = 5.11e+02
正則化パラメータ = 1e-20, 訓練誤差 = 0.004936191193133389, テスト誤差 = 5.11e+02
正則化パラメータ = 1e-10, 訓練誤差 = 0.009762751388489265, テスト誤差 = 1.44e+02
正則化パラメータ = 1e-05, 訓練誤差 = 0.01059565315043209, テスト誤差 = 2.79e-01
正則化パラメータ = 0.001, 訓練誤差 = 0.010856091742299396, テスト誤差 = 6.89e-02
正則化パラメータ = 0.01, 訓練誤差 = 0.012046102850453813, テスト誤差 = 7.79e-02
正則化パラメータ = 0.1, 訓練誤差 = 0.02351033489834412, テスト誤差 = 4.94e-02
正則化パラメータ = 1, 訓練誤差 = 0.11886509938269865, テスト誤差 = 2.26e-01
正則化パラメータ = 10, 訓練誤差 = 0.31077333649742883, テスト誤差 = 4.71e-01
正則化パラメータ = 100, 訓練誤差 = 0.41104732329314453, テスト誤差 = 5.20e-01
正則化が効きすぎると平均を取るだけになるし、効きが弱いと過学習になってしまう。
なのでリッジ回帰でも正則化パラメータのチューニングに交差検証は必要。