#author("2023-10-25T11:31:12+09:00","default:cmdsadmin","cmdsadmin")
* 第5回:教師あり学習:回帰 [#s98df3b7]
#author("2024-05-07T10:37:55+09:00","default:cmdsadmin","cmdsadmin")

#contents

* 5.1 おさらい [#h65f6abc]

** 教師あり学習 (supervised learning) [#we2c1085]

データにおける''入力X(特徴量)''と''出力y(正解データ)''の''関係f (y=f(X))''を学習する。機械学習の最も代表的なアプローチ。''回帰''と''分類''の2タイプに大別される。

- 回帰 (regression)
-- yを数値(連続値)として,Xから予測するモデルを構築する
-- 応用例:売上予測,需要予測,リードタイム予測,収穫量予測
-- モデル:線形回帰,リッジ回帰,ラッソ回帰,回帰木

- 分類 (classification)
-- yをカテゴリ(離散値)として,予測する問題
-- 応用例:故障予測,文字認識,感情認識,スパム判定
-- モデル:決定木,ロジスティック回帰,k近傍法,サポートベクタマシン(SVM)


//* 5.2 教師あり学習の概要 [#cfc94c6d]

** 教師あり学習の目標 [#zc1b2140]

N個のデータとラベル (x, y) = { (x_1, y_1), (x_2, y_2), ..., (x_N, y_N) }  = { (x_n, y_n) }_{n=1}^N とする。このとき、y_n = f(x_n ,w) + ε(ノイズ) として、N個のデータに対して、二乗誤差が最小となるf(x,w)とw*を求めたい(最小二乗法)。

CENTER:&attachref(./5_eq_param.png,70%);

但し、

CENTER:&attachref(./5_eq_error.png,70%);

ここで、f(x,w):モデル、w:パラメータ、f(x_n,w):モデル出力、y_n:目標値、正解データ

** 教師あり学習の実行手順 [#n8730f65]

+ ''学習データ''(x, y) = { (x_n, y_n) }_{n=1}^Nを準備する。(前処理やアノテーションはやっておく)
+ モデルf(x,w)を選ぶ。(AI専門家は,優れたAIモデルを考案し,その学習アルゴリズムを導出する)
+ 入力x_nをモデルに与えて出力hat{y}_n = f (x_n , w)を計算し,二乗誤差. E(w)を計算する。(最小二乗法の場合)
+ ''学習アルゴリズム''に従って、パラメータwを更新する。(通常、何回も繰り返しが必要)
+ ''テストデータ''を使って、更新されたモデルの''予測精度(誤差)''を評価する.

** 学習誤差とテスト誤差 [#maacaf08]

- 学習誤差

学習データセットX = { (x_n, y_n) }_{n=1}^Nに対し、以下の平均二乗誤差 (Mean Square Error, MSE)を最小化してモデルパラメータwを最適化

CENTER:&attachref(./5_eq_error.png,70%);

これはパラメータwの関数

- テスト誤差

テストデータセット tilde{X} = { (tilde{x}_n, tilde{y}_n) }_{n=1}^{tilde{N}}に対し、パラメータwを固定してモデルを評価

CENTER:&attachref(./5_eq_error_test.png,70%);

これはテストデータセットtilde{X}の関数
モデルの評価は、学習途中でも行うし、学習終了後にも行う

//** モデル [#aa463422]

//*** 線形回帰モデル [#hd192490]

//CENTER:&attachref(./5_eq_model_lr.png,70%);

//- 平均二乗誤差

//CENTER:&attachref(./5_eq_error_lr.png,70%);

//を最小化する{ w_0, w_1, w_2, ..., w_D }を求める。

//- データxが1変数の場合は単回帰、2変数以上の場合は重回帰と言う

//*** 決定木(回帰木)モデル [#vbe60bdf]
//- 〇〇〇〇

//- 〇〇〇〇

//*** モデル選択の基準 [#k434e85b]
//- 〇〇〇〇

//- 〇〇〇〇

//** 過学習 [#f413665c]

//*** 概念 [#g1dd7162]
//- 〇〇〇〇

//- 〇〇〇〇

//*** 対処法 [#faf6f0ed]

//- ハイパーパラメータチューニング

//- 特徴量選択

//- 正則化


* 5.2 例題:不動産価格の予測問題 [#nbfad5dc]

** 準備 [#bc8ded7b]

+ Google Colabを開き,新規ノートブックを作成
+ ノートブックの名前 Untitled.ipynb を realestate.ipynb に変更する

*** ライブラリのインポート [#w53e3938]
//```
 # PandasとNumPyをインポート
 import pandas as pd
 import numpy as np
 
 # 日本語化MatplotLib
 import matplotlib.pyplot as plt
 !pip install japanize-matplotlib
 import japanize_matplotlib
 
 # Seabornをインポート
 import seaborn as sns
 
 # Pickleをインポート
 import pickle
//```

*** データの取得 [#o9013e2f]

CENTER:&attachref(./5_newtaipei.png,80%);~
CENTER:図1: 新北市(Wikipediaより)

//```
 # 不動産データの取得
 data = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/realestate-sample.csv")
//```

** データの理解・可視化 [#oa7a41ee]

*** データの確認と整形 [#s576a49f]

- データ項目の確認

//```
 data
//```

- 表データの確認

//```
 # 表の形を表示する
 data.shape
//```

//```
 # 各列の型を確認する
 data.dtypes
//```

//```
 data.info()
//```

- 表データの整形

//```
 # 生データをコピーしておく(いつでもやり直せるように)
 df = data.copy()
//```

*** データを眺める [#kd0928bc]

- 1変数を眺める

//```
 # 箱ひげ図
 sns.boxplot(df[["坪単価"]])
//```
CENTER:&attachref(./5_boxplot.png,70%);~
CENTER:図2: 箱ひげ図

//```
 # ヒストグラム
 sns.histplot(df["坪単価"])
//```
CENTER:&attachref(./5_histplot.png,70%);~
CENTER:図3: ヒストグラム

- 2変数間の関係を眺める

//```
 # 相関行列
 sns.heatmap(df.corr(), annot=True)
//```
CENTER:&attachref(./5_corr.png,70%);~
CENTER:図4: 相関行列

//```
 # 散布図
 sns.scatterplot(df, x="駅距離", y="坪単価", hue="コンビニ数")
//```
CENTER:&attachref(./5_scatterplot.png,70%);~
CENTER:図5: 散布図

** 前処理 [#m140283e]

*** データを修正する [#w9ad6041]

- 欠損値の処理

//```
 # 欠損値の確認
 df.isnull().sum()
//```

- 外れ値の処理

//```
 # 外れ値を見つける:各変数の要約統計量
 df.describe()
//```

//```
 # 外れ値を見つける:各変数の箱ひげ図
 fig, axes= plt.subplots(nrows=2, ncols=4, tight_layout=True, squeeze=False)
 for i, col in  enumerate(["取引日",  "築年数",  "駅距離",  "コンビニ数",  "緯度",  "経度",  "坪単価"]):
 sns.boxplot(df[[col]], ax=axes[i//4, i%4])
//```
CENTER:&attachref(./5_boxplots.png,70%);~
CENTER:図6: 各変数の箱ひげ図

> 外れ値に対する処理は省略

- 重複行の処理

//```
 # 重複行を見つける
 df[df.duplicated(keep=False)]
//```

*** データを変換する [#zb57f0f6]

//```
 # 特徴量に指定する列名リスト
 features = df.columns[0:6]
 
 # 正解データに指定する列名
 target = df.columns[6:7]
 
 # 特徴量
 X = df[features]
 
 # 正解データ
 y = df[target]
 
 # X, yのそれぞれを訓練データとテストデータに分ける (訓練:テスト=8:2)
 from sklearn.model_selection import train_test_split
 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1234)
//```

- 数値データのスケーリング(標準化)

//```
 from sklearn.preprocessing import StandardScaler
 # 標準化のためのスケーラー
 sc = StandardScaler()
 
 # 訓練データにフィットさせる
 sc.fit(X_train)
 
 # 訓練データをスケール変換して、データフレームに入れなおす
 X_train_sc = pd.DataFrame(sc.transform(X_train), index=X_train.index,columns=X_train.columns)
 
 # テストデータもスケール変換する
 X_test_sc = pd.DataFrame(sc.transform(X_test), index=X_test.index,columns=X_test.columns)
//```

> 教師あり学習の場合は、''訓練データとテストデータを分割した後''にスケーリングを行う
> - データ分割前にスケーラーをfitさせてはならない(訓練データがテストデータに依存してしまう)
> - 訓練データにスケーラーをfit、transformさせ、''同じスケーラーでテストデータをtransformさせる''こと
> - 訓練データとテストデータで別々のスケーラを使ってはいけない

** 線形回帰モデルによる学習・評価 [#d298a4f2]

*** モデルの選択と学習 [#w76a1d1e]

//```
 # 線形回帰モデルの選択
 from sklearn import linear_model
 model_lr = linear_model.LinearRegression()
 
 # 線形回帰モデルの学習(標準化した訓練データを使う)
 model_lr.fit(X_train_sc, y_train)
//```

*** モデルの評価 [#af62f711]

//```
 # 線形回帰モデルのパラメータ
 m_exp = pd.DataFrame()
 m_exp.index = ["切片"] + model_lr.feature_names_in_.tolist()
 m_exp["重み"] = [model_lr.intercept_[0]] + model_lr.coef_[0].tolist()
 m_exp
//```

//```
 # 実際にあっているかどうかを確認してみる
 y_eval = pd.DataFrame()
 y_eval["正解"] = y_test[target]
 y_eval["予測"] = model_lr.predict(X_test_sc)
 y_eval["誤差"] = (y_eval["正解"] - y_eval["予測"])
 
 from sklearn.metrics import PredictionErrorDisplay, r2_score, mean_absolute_error, mean_squared_error
 disp = PredictionErrorDisplay(y_true = y_eval["正解"], y_pred= y_eval["予測"])
//```

//```
 # 正解値と予測値を散布図にプロット
 disp.plot(kind="actual_vs_predicted")
//```
CENTER:&attachref(./5_actual_vs_predicted_lr.png,70%);~
CENTER:図7: 正解値と予測値を散布図にプロット(線形回帰モデル)

//```
 # 残差と予測値を散布図にプロット
 disp.plot()
//```
CENTER:&attachref(./5_residuals_lr.png,70%);~
CENTER:図8: 残差と予測値を散布図にプロット(線形回帰モデル)

- 決定係数
CENTER:&attachref(./5_eq_r2.png,70%);~
ここで、y:実際の値、\hat{y}:予測値、\bar{y}:実際の値の平均値、n:データ数
-- このモデルにおける特徴量Xがどの程度yを説明できているかを表す指標
-- 0~1の値を取る.0.7以上なら良い精度とされる
-- R2 = 1 - (予測残差平方和) / (平均残差平方和)

- MAE(平均絶対誤差)
CENTER:&attachref(./5_eq_mae.png,70%);
-- 解釈しやすい

- MSE(平均二乗誤差)
CENTER:&attachref(./5_eq_mse.png,70%);

- RMSE(二乗平均平方根誤差)
CENTER:&attachref(./5_eq_rmse.png,70%);
-- 外れ値の影響を受けやすい。MAEの方が平均的に誤差を評価

//```
 # 決定係数
 r2 = r2_score(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"決定係数:{r2}")
 
 # MAE(平均絶対誤差)
 mae = mean_absolute_error(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"MAE(平均絶対誤差):{mae}")
 
 # MSE(平均二乗誤差)
 mse = mean_squared_error(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"MSE(平均二乗誤差):{mse}")
 
 # RMSE(二乗平均平方根誤差)
 rmse = np.sqrt(mse)
 print(f"RMSE(二乗平均平方根誤差):{rmse}")
//```

*** 汎化性能の確認 [#x078a969]

- 学習誤差とテスト誤差

//```
 # 訓練データに対しても評価してみる
 y_eval_train = pd.DataFrame()
 y_eval_train["正解"] = y_train[target]
 y_eval_train["予測"] = model_lr.predict(X_train_sc)
 y_eval_train["誤差"] = (y_eval_train["正解"] - y_eval_train["予測"])
//```

//```
 # 正解値と予測値を散布図にプロット(訓練データ、テストデータ両方とも)
 plt.xlabel("Predicted values")
 plt.ylabel("Actual values")
 plt.xlim(0.0, 120.0)
 plt.ylim(0.0, 120.0)
 plt.grid(True)
 plt.gca().set_aspect('equal', adjustable='box')
 plt.scatter(y_eval["予測"], y_eval["正解"], label="test", s=10, alpha=0.5, linewidths=1)
 plt.scatter(y_eval_train["予測"], y_eval_train["正解"], label="train", s=10, alpha=0.5, linewidths=1)
 plt.plot([0, y_test.max()], [0, y_test.max()], 'k--', lw=1)  # y=x
 plt.legend()
 plt.show()
//```
CENTER:&attachref(./5_actual_vs_predicted_lr2.png,70%);~
CENTER:図9: 正解値と予測値を散布図にプロット(訓練、テスト両方)(線形回帰モデル)

//```
 # 残差と予測値を散布図にプロット(訓練データ、テストデータ両方とも)
 plt.xlabel("Predicted values")
 plt.ylabel("Residuals (Actual - Predicted)")
 plt.xlim(0.0, 100.0)
 plt.ylim(-100.0, 100.0)
 plt.grid(True)
 plt.scatter(y_eval["予測"], y_eval["誤差"], label="test", s=10, alpha=0.5, linewidths=1)
 plt.scatter(y_eval_train["予測"], y_eval_train["誤差"], label="train", s=10, alpha=0.5, linewidths=1)
 plt.legend()
 plt.show()
//```
CENTER:&attachref(./5_residuals_lr2.png,70%);~
CENTER:図10: 残差と予測値を散布図にプロット(訓練、テスト両方)(線形回帰モデル)

//```
 # 学習誤差とテスト誤差の比較
 # 決定係数(テストデータ)
 r2 = r2_score(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"決定係数(テストデータ):{r2}")
 
 # 決定係数(訓練データ)
 r2_train = r2_score(y_true = y_eval_train['正解'], y_pred = y_eval_train['予測'])
 print(f"決定係数(訓練データ) :{r2_train}")
 
 # MAE(テストデータ)
 mae = mean_absolute_error(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"MAE(テストデータ):{mae}")
 
 # MAE(訓練データ)
 mae_train = mean_absolute_error(y_true = y_eval_train['正解'], y_pred = y_eval_train['予測'])
 print(f"MAE(訓練データ) :{mae_train}")
//```

- 学習曲線

//```
 # 学習曲線を作成する
 from sklearn.model_selection import learning_curve
 
 train_sizes, train_scores, test_scores = learning_curve(
     estimator=model_lr, X=X_train_sc, y=y_train, cv=10, scoring='r2',
     train_sizes=np.linspace(0.1, 1.0, 10), random_state=1234)
 
 train_scores_mean = np.mean(train_scores, axis=1)
 train_scores_std = np.std(train_scores, axis=1)
 test_scores_mean = np.mean(test_scores, axis=1)
 test_scores_std = np.std(test_scores, axis=1)
 
 plt.plot(train_sizes, train_scores_mean, 'o-', color='r', label='Training score')
 plt.plot(train_sizes, test_scores_mean, 'o-', color='g', label='Validation score')
 plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                  train_scores_mean + train_scores_std, alpha=0.1, color='r')
 plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                  test_scores_mean + test_scores_std, alpha=0.1, color='g')
 plt.grid()
 plt.title('Learning curve')
 plt.xlabel('Number of training examples')
 plt.ylabel('R2')
 plt.ylim(0.0, 1.0)
 plt.legend(loc='best')
 plt.show()
//```
CENTER:&attachref(./5_learningcurve_lr.png,70%);~
CENTER:図11: 学習曲線(線形回帰モデル)

*** 過学習をしている場合の対処法1:正則化 [#j3d77546]

CENTER:&attachref(./5_overfit.png,70%);~
CENTER:図12: オーバーフィッティング(Wikipediaより)

//```
 # ラッソ回帰モデル
 # モデルの選択
 model_lasso = linear_model.Lasso(alpha=0.1)
 
 # モデルの学習(標準化した訓練データを使う)
 model_lasso.fit(X_train_sc, y_train)
 
 # 決定係数
 # テストデータ
 r2_lasso = model_lasso.score(X_test_sc, y_test)
 print(f"決定係数(テストデータ)(ラッソ回帰):{r2_lasso}")
 # 訓練データ
 r2_train_lasso = model_lasso.score(X_train_sc, y_train)
 print(f"決定係数(訓練データ)(ラッソ回帰) :{r2_train_lasso}")
//```

//```
 # リッジ回帰モデル
 # モデルの選択
 model_ridge = linear_model.Ridge(alpha=0.1)
 
 # モデルの学習(標準化した訓練データを使う)
 model_ridge.fit(X_train_sc, y_train)
 
 # 決定係数
 # テストデータ
 r2_ridge = model_ridge.score(X_test_sc, y_test)
 print(f"決定係数(テストデータ)(リッジ回帰):{r2_ridge}")
 # 訓練データ
 r2_train_ridge = model_ridge.score(X_train_sc, y_train)
 print(f"決定係数(訓練データ)(リッジ回帰) :{r2_train_ridge}")
//```

//```
 # ElasticNetモデル
 # モデルの選択
 model_elastic = linear_model.ElasticNet(alpha=0.1, l1_ratio=0.5)
 
 # モデルの学習(標準化した訓練データを使う)
 model_elastic.fit(X_train_sc, y_train)
 
 # 決定係数
 # テストデータ
 r2_elastic = model_elastic.score(X_test_sc, y_test)
 print(f"決定係数(テストデータ)(ElasticNet):{r2_elastic}")
 # 訓練データ
 r2_train_elastic = model_elastic.score(X_train_sc, y_train)
 print(f"決定係数(訓練データ)(ElasticNet) :{r2_train_elastic}")
//```

** 回帰木モデルによる学習・評価 [#v49d1ba0]

*** モデルの選択と学習 [#tac01883]

//```
 # 回帰木モデルの選択
 from sklearn import tree
 model_dt = tree.DecisionTreeRegressor(max_depth=10, random_state=1234) #max_depthは木の深さの最大値
 
 # 回帰木モデルの学習
 model_dt.fit(X_train, y_train)
//```

*** モデルの評価 [#e562059d]

//```
 # 得られた木を可視化する(木が深いと描画に時間がかかる)
 plt.figure(figsize=(40, 20))
 _ = tree.plot_tree(model_dt, fontsize=10, feature_names=X.columns)
//```
CENTER:&attachref(./5_tree.png,20%);~
CENTER:図11: 得られた木を可視化

//```
 # 誤差を確認する
 y_eval = pd.DataFrame()
 y_eval["正解"] = y_test[target]
 y_eval["予測"] = model_dt.predict(X_test)
 y_eval["誤差"] = (y_eval["正解"] - y_eval["予測"])
 
 from sklearn.metrics import PredictionErrorDisplay, r2_score, mean_absolute_error, mean_squared_error
 disp = PredictionErrorDisplay(y_true = y_eval["正解"], y_pred= y_eval["予測"])
//```

//```
 # 正解値と予測値を散布図にプロット
 disp.plot(kind="actual_vs_predicted")
//```
CENTER:&attachref(./5_actual_vs_predicted_dt.png,70%);~
CENTER:図12: 正解値と予測値を散布図にプロット(回帰木モデル)

//```
 # 残差と予測値を散布図にプロット
 disp.plot()
//```
CENTER:&attachref(./5_residuals_dt.png,70%);~
CENTER:図12: 残差と予測値を散布図にプロット(回帰木モデル)

//```
 # 決定係数
 r2 = r2_score(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"決定係数:{r2}")
 
 # MAE(平均絶対誤差)
 mae = mean_absolute_error(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"MAE(平均絶対誤差):{mae}")
 
 # MSE(平均二乗誤差)
 mse = mean_squared_error(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"MSE(平均二乗誤差):{mse}")
 
 # RMSE(二乗平均平方根誤差)
 rmse = np.sqrt(mse)
 print(f"RMSE(二乗平均平方根誤差):{rmse}")
//```

*** 汎化性能の確認 [#m44d029e]

- 学習誤差とテスト誤差

//```
 # 訓練データに対しても評価してみる
 y_eval_train = pd.DataFrame()
 y_eval_train["正解"] = y_train[target]
 y_eval_train["予測"] = model_dt.predict(X_train)
 y_eval_train["誤差"] = (y_eval_train["正解"] - y_eval_train["予測"])
//```

//```
 # 正解値と予測値を散布図にプロット(訓練データ、テストデータ両方とも)
 plt.xlabel("Predicted values")
 plt.ylabel("Actual values")
 plt.xlim(0.0, 120.0)
 plt.ylim(0.0, 120.0)
 plt.grid(True)
 plt.gca().set_aspect('equal', adjustable='box')
 plt.scatter(y_eval["予測"], y_eval["正解"], label="test", s=10, alpha=0.5, linewidths=1)
 plt.scatter(y_eval_train["予測"], y_eval_train["正解"], label="train", s=10, alpha=0.5, linewidths=1)
 plt.plot([0, y_test.max()], [0, y_test.max()], 'k--', lw=1)  # y=x
 plt.legend()
 plt.show()
//```
CENTER:&attachref(./5_actual_vs_predicted_dt2.png,70%);~
CENTER:図13: 正解値と予測値を散布図にプロット(訓練、テスト両方)(回帰木モデル)

//```
 # 残差と予測値を散布図にプロット(訓練データ、テストデータ両方とも)
 plt.xlabel("Predicted values")
 plt.ylabel("Residuals (Actual - Predicted)")
 plt.xlim(0.0, 100.0)
 plt.ylim(-100.0, 100.0)
 plt.grid(True)
 plt.scatter(y_eval["予測"], y_eval["誤差"], label="test", s=10, alpha=0.5, linewidths=1)
 plt.scatter(y_eval_train["予測"], y_eval_train["誤差"], label="train", s=10, alpha=0.5, linewidths=1)
 plt.legend()
 plt.show()
//```
CENTER:&attachref(./5_residuals_dt2.png,70%);~
CENTER:図14: 残差と予測値を散布図にプロット(訓練、テスト両方)(回帰木モデル)

//```
 # 学習誤差とテスト誤差の比較
 # 決定係数(テストデータ)
 r2 = r2_score(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"決定係数(テストデータ):{r2}")
 
 # 決定係数(訓練データ)
 r2_train = r2_score(y_true = y_eval_train['正解'], y_pred = y_eval_train['予測'])
 print(f"決定係数(訓練データ) :{r2_train}")
 
 # MAE(テストデータ)
 mae = mean_absolute_error(y_true = y_eval['正解'], y_pred= y_eval['予測'])
 print(f"MAE(テストデータ):{mae}")
 
 # MAE(訓練データ)
 mae_train = mean_absolute_error(y_true = y_eval_train['正解'], y_pred = y_eval_train['予測'])
 print(f"MAE(訓練データ) :{mae_train}")
//```

- 学習曲線

//```
 # 学習曲線を作成する
 from sklearn.model_selection import learning_curve
 
 train_sizes, train_scores, test_scores = learning_curve(
   estimator=model_dt, X=X_train, y=y_train, cv=10, scoring='r2',
   train_sizes=np.linspace(0.1, 1.0, 10), random_state=1234)
 
 train_scores_mean = np.mean(train_scores, axis=1)
 train_scores_std = np.std(train_scores, axis=1)
 test_scores_mean = np.mean(test_scores, axis=1)
 test_scores_std = np.std(test_scores, axis=1)
 
 plt.plot(train_sizes, train_scores_mean, 'o-', color='r', label='Training score')
 plt.plot(train_sizes, test_scores_mean, 'o-', color='g', label='Validation score')
 plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                   train_scores_mean + train_scores_std, alpha=0.1, color='r')
 plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                   test_scores_mean + test_scores_std, alpha=0.1, color='g')
 plt.grid()
 plt.title('Learning curve')
 plt.xlabel('Number of training examples')
 plt.ylabel('R2')
 plt.ylim(0.0, 1.0)
 plt.legend(loc='best')
 plt.show()
//```
CENTER:&attachref(./5_learningcurve_dt.png,70%);~
CENTER:図15: 学習曲線(回帰木モデル)

*** 過学習をしている場合の対処法2:ハイパーパラメータチューニング [#lb5345cc]

- 検証曲線

//```
 # 検証曲線を作成する(横軸はmax_depth)
 from sklearn.model_selection import validation_curve
 
 param_range = np.arange(1, 16)
 train_scores, test_scores = validation_curve(
     estimator=model_dt, X=X_train, y=y_train, cv=10, scoring='r2',
     param_name='max_depth', param_range=param_range)
 
 train_scores_mean = np.mean(train_scores, axis=1)
 train_scores_std = np.std(train_scores, axis=1)
 test_scores_mean = np.mean(test_scores, axis=1)
 test_scores_std = np.std(test_scores, axis=1)
 
 plt.plot(param_range, train_scores_mean, 'o-', color='r', label='Training score')
 plt.plot(param_range, test_scores_mean, 'o-', color='g', label='Validation score')
 plt.fill_between(param_range, train_scores_mean - train_scores_std,
                  train_scores_mean + train_scores_std, alpha=0.1, color='r')
 plt.fill_between(param_range, test_scores_mean - test_scores_std,
                  test_scores_mean + test_scores_std, alpha=0.1, color='g')
 plt.grid()
 plt.title('Validation curve')
 plt.xlabel('Parameter max_depth')
 plt.ylabel('R2')
 plt.ylim(0.0, 1.0)
 plt.legend(loc='best')
 plt.show()
//```
CENTER:&attachref(./5_validationcurve_dt.png,70%);~
CENTER:図16: 検証曲線(回帰木モデル)

*** 過学習をしている場合の対処法3:特徴量選択 [#c7e01d2f]

- 特徴量の重要度

//```
 # 特徴量重要度の確認
 imp_value = pd.DataFrame({'feature':features, 'importance':model_dt.feature_importances_})
 print(imp_value)
//```

//```
 # 特徴量重要度のグラフ化
 imp = model_dt.feature_importances_
 label = X.columns
 indices = np.argsort(imp)
 
 fig=plt.figure(figsize=(4,4))
 plt.barh(range(len(imp)), imp[indices])
 plt.yticks(range(len(imp)), label[indices], fontsize=10)
 plt.xticks(fontsize=10)
 plt.ylabel("Feature", fontsize=12)
 plt.xlabel("Feature importance", fontsize=12)
//```
CENTER:&attachref(./5_featureimportances.png,70%);~
CENTER:図17: 特徴量重要度

//```
 # 上位2つの特徴量以外を削除
 X_train_dropped = X_train.drop(columns=["コンビニ数", "取引日", "緯度", "築年数"])
 X_test_dropped = X_test.drop(columns=["コンビニ数", "取引日", "緯度", "築年数"])
 # 確認
 X_train_dropped.info()
 X_test_dropped.info()
//```

//```
 # 再評価
 # モデルの学習(特徴量を選別した訓練データを使う)
 model_dt.fit(X_train_dropped, y_train)
 
 # 決定係数
 # テストデータ
 r2 = model_dt.score(X_test_dropped, y_test)
 print(f"決定係数(テストデータ)(回帰木):{r2}")
 # 訓練データ
 r2_train = model_dt.score(X_train_dropped, y_train)
 print(f"決定係数(訓練データ)(回帰木) :{r2_train}")
//```


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS