線形回帰とRidge回帰の比較 過学習

以下の状態を過学習といいます。

  • トレーニングデータの評価値が良い
  • テストデータの評価値が悪い

このクエストでは、下記の手法に対して、これらの評価値がどうなるのかを確認します。

  • 線形回帰(LinearRegression
  • Ridge回帰(Ridge
  • サポートベクターマシン回帰(SVR
  • ランダムフォレスト回帰(RandomForestRegressor

まずは、線形回帰とRidge回帰を比較します。

%precision 3
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_squared_error
np.random.seed(23)
M, N = 80, 32
# ダミーデータ
X = np.random.randn(M, N)
y = X.sum(1) * 0.4 + np.random.randn(M)

ダミーデータ(X, y)を使います。
過学習を避ける上で、説明変数の選択は重要です。ダミーデータの全説明変数は、目的変数と弱い相関があるので、説明変数の選択は済んでいることにします。

# トレーニングデータとテストデータの平均二乗誤差を計算
def calc_score(model):
    lst1, lst2 = [], []
    for i in range(20):  # 20回の平均を取る
        X_train, X_test, y_train, y_test = (
            train_test_split(X, y, test_size=M//2, random_state=i))
        model.fit(X_train, y_train)
        lst1.append(mean_squared_error(y_train, model.predict(X_train)))
        lst2.append(mean_squared_error(y_test, model.predict(X_test)))
    score1 = np.mean(lst1)
    score2 = np.mean(lst2)
    return score1, score2

結果を入れるlst1, lst2を用意します
以下、20回繰り返します
トレーニングデータとテストデータを半々に分割します
modelを使って回帰します
lst1にトレーニングデータの平均二乗誤差を入れます。
lst2にテストデータの平均二乗誤差を入れます。
score1にlst1の平均を入れます。
score2にlst2の平均を入れます。

# 線形回帰のとき
model = LinearRegression()
score1, score2 = calc_score(model)
float(score1), float(score2)  # トレーニングデータとテストデータの平均二乗誤差
(0.165, 10.038)

線形回帰のときは、(0.165, 10.038)になり、テストデータの平均二乗誤差が大きいので、過学習しているといえます。

# Ridge回帰のとき
model = Ridge()
score3, score4 = calc_score(model)
float(score3), float(score4)  # トレーニングデータとテストデータの平均二乗誤差
(0.195, 3.906)

Ridge回帰のときは、(0.195, 3.906)になり、テストデータの平均二乗誤差が小さくなっており、正則化の効果で汎化性能が高くなっています

コメント

タイトルとURLをコピーしました