- 追加された行はこの色です。
- 削除された行はこの色です。
- 第5回 は削除されています。
- 第5回 の差分を削除
#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}")
//```