多くの人にとって馴染みがあるのは、時系列データ系の数理モデル(アルゴリズム)よりも、テーブルデータ系の数理モデル(アルゴリズム)の方です。
例えば、以下の数理モデル(アルゴリズム)はテーブルデータ系のものです。
- 線形回帰モデル(単回帰、重回帰、など)
- 正則化回帰モデル(Ridge回帰、Lasso回帰、など)
- 一般化線形モデル(GLMM)
- 一般化加法モデル(GAM)
- 階層線形モデル、マルチレベルモデル、一般化混合モデル
- 決定木(ディシジョンツリー)
- ランダムフォレスト
- ブースティングモデル(AdaBoost、XGBoost、LightGBMなど)
- ニューラルネットワークモデル
……などなど。
前回は、時系列特徴量付きデータセットを使い、正則化項付き線形回帰モデル(Ridge回帰、Lasso回帰、Elastic net回帰など)で時系列予測モデルを構築しました。
今回は、前回と同じ時系列特徴量付きデータセットを使い、ディシジョンツリー(決定木)で時系列予測モデルを構築します。
ディシジョンツリー(決定木)
ディシジョンツリーは、条件分岐によってデータをツリー状にどんどん分割し、いくつかのグループを作るモデルです。
条件分岐は、説明変数Xに対するIf-Thenルールで、説明変数x1が0であるかどうか(Yes or No)とか、説明変数x2が100未満であるかどうか(Yes or No)とか、そういったルールです。最もシンプルなディシジョンツリーは、Yes or Noで2分岐です。もちろん、多分岐のモデルも存在します。
説明変数Xに対する条件分岐によって、幾つかの分割されたグループができあがります。予測値は、各グループの目的変数yの代表値(例:平均値や最頻値など)とします。
各グループ内のデータの目的変数yの値が近い(もしくは同じ)ほど良いとされます。
グループ内のデータの目的変数yの値が近い(もしくは同じ)かどうかを、不純度という指標を使い評価します。不純度が小さいほど、グループ内のデータの目的変数yの値が近い(もしくは同じ)と解釈します。
不純度というワードで説明すると、ディシジョンツリーは、不純度がどんどん小さくなるように、ある条件分岐を設定しデータを分割し、いくつかのグループを作るモデルです。どのような条件分岐を設定すべきかを、学習データなどで求めます。
必要なライブラリーの読み込み
先ず、必要なライブラリーなどを読み込みます。
以下、コードです。
import numpy as np import pandas as pd import optuna from sklearn.tree import DecisionTreeRegressor from sklearn.inspection import PartialDependenceDisplay from sklearn.metrics import mean_absolute_error from sklearn.metrics import mean_squared_error from sklearn.metrics import mean_absolute_percentage_error import matplotlib.pyplot as plt plt.style.use('ggplot') #グラフのスタイル plt.rcParams['figure.figsize'] = [12, 9] # グラフサイズ設定
利用するデータ
今回利用するデータは、前回準備した時系列特徴量付きデータセットです。
以下からダウンロードできます。
dataset.csv
https://www.salesanalytics.co.jp/6ro8
このURLから直接データセットを読み込めます。
以下、コードです。
# データセットの読み込み url='dataset.csv' df=pd.read_csv(url, #読み込むデータのURL index_col='Month', #変数「Month」をインデックスに設定 parse_dates=True) #インデックスを日付型に設定 df.head() #確認
以下、実行結果です。
グラフ化し確認します。
以下、コードです。
# プロット df.plot() plt.title('Passengers') #グラフタイトル plt.ylabel('Monthly Number of Airline Passengers') #タテ軸のラベル plt.xlabel('Month') #ヨコ軸のラベル plt.show()
以下、実行結果です。
次に、読み込んだデータセットを、学習データとテストデータに分割します。
以下、コードです。
# 学習データ train = df.iloc[:-12] y_train = train['y'] #目的変数y X_train = train.drop('y', axis=1) #説明変数X # テストデータ test = df.iloc[-12:] #テストデータ y_test = test['y'] #目的変数y X_test = test.drop('y', axis=1) #説明変数X
グラフ化します。
以下、コードです。
# グラフ化 fig, ax = plt.subplots() ax.plot(y_train.index, y_train.values, label="actual(train dataset)") ax.plot(y_test.index, y_test.values, label="actual(test dataset)") plt.legend()
以下、実行結果です。
学習データでディシジョンツリー(決定木)モデルを構築し、構築したモデルをテストデータで精度検証します。
予測精度の評価指標
今回の予測精度の評価指標は、RMSE(二乗平均平方根誤差、Root Mean Squared Error)とMAE(平均絶対誤差、Mean Absolute Error)、MAPE(平均絶対パーセント誤差、Mean absolute percentage error)を使います。
以下の記号を使い精度指標の説明をします。
- y_i^{actual} ・・・i番目の実測値
- y_i^{pred} ・・・i番目の予測値
- n ・・・実測値・予測値の数
■ 二乗平均平方根誤差(RMSE、Root Mean Squared Error)
\sqrt{\frac{1}{n}\sum_{i=1}^n(y_i^{actual}-{y_i^{pred}})^2}■ 平均絶対誤差(MAE、Mean Absolute Error)
\frac{1}{n}\sum_{i=1}^n|y_i^{actual}-{y_i^{pred}}|■ 平均絶対パーセント誤差(MAPE、Mean absolute percentage error)
\frac{1}{n}\sum_{i=1}^n|\frac{y_i^{actual}-{y_i^{pred}}}{y_i^{actual}}|
ディシジョンツリー(決定木)
学習データを使って、ディシジョンツリー(決定木)を学習します。
以下、コードです。
regressor = DecisionTreeRegressor(max_depth=5, random_state=123) regressor.fit(X_train, y_train)
ディシジョンツリー(決定木)を図示化します。
以下、コードです。
# 決定木の図示化 from dtreeviz.trees import dtreeviz viz = dtreeviz(regressor, X_train, y_train, target_name='y', feature_names=X_train.columns ) viz
以下、実行結果です。
特徴量重要度(Feature Importances)を見てみます。
以下、コードです。
# 特徴量重要度(Feature Importances) df_importance = pd.DataFrame(zip(X_train.columns, regressor.feature_importances_), columns=["Features","Importance"]) df_importance = df_importance.sort_values("Importance", ascending=False) df_importance #確認
以下、実行結果です。
特徴量重要度をグラフ化します。
以下、コードです。
# グラフ化 df_importance.plot.bar(x='Features',y='Importance', rot=0)
以下、実行結果です。
部分従属プロット(Partial Dependence Plot)を見てみます。
以下、コードです。
# 部分従属プロット(Partial Dependence Plot) PartialDependenceDisplay.from_estimator(regressor, X_train, [0,1,2])
以下、実行結果です。
テストデータで精度検証します。
以下、コードです。
# 予測 train_pred = regressor.predict(X_train) test_pred = regressor.predict(X_test) # 精度指標(テストデータ) print('RMSE:') print(np.sqrt(mean_squared_error(y_test, test_pred))) print('MAE:') print(mean_absolute_error(y_test, test_pred)) print('MAPE:') print(mean_absolute_percentage_error(y_test, test_pred))
以下、実行結果です。
グラフ化します。
以下、コードです。
# グラフ化 fig, ax = plt.subplots() ax.plot(y_train.index, y_train.values, label="actual(train dataset)") ax.plot(y_test.index, y_test.values, label="actual(test dataset)") ax.plot(y_train.index, train_pred, linestyle="dotted", lw=2,color="m") ax.plot(y_test.index, test_pred, label="DT", linestyle="dotted", lw=2, color="m") plt.legend()
以下、実行結果です。
次回
今回は、前回と同じ時系列特徴量付きデータセットを使い、ディシジョンツリーモデル(決定木)で時系列予測モデルを構築しました。
次回は、今回と同じ時系列特徴量付きデータセットを使い、ランダムフォレストで時系列予測モデルを構築します。