- 製造業出身のデータサイエンティストがお送りする記事
- 今回は時系列解析手法のProphetをOptunaでハイパラチューニングをしてみました
##はじめに
過去に時系列解析に関しては何個か整理しておりますので、興味ある方は参照して頂けますと幸いです。
##Prophetとは
Prophet は Facebook が公開しているオープンソースの時系列解析ライブラリです。
Prophetのメリットは大きく下記があります。
1.モデル式設計の柔軟性が高い
2.サンプル間隔の柔軟性が高い
3.高速に計算可能
4.パラメータが理解しやすい
詳細はProphetの公式ドキュメントを参照してください。
##Prophet実装
今回も使用したデータは、月ごとの飛行機の乗客数データです。
# ライブラリーのインポート
import pandas as pd
import numpy as np
import seaborn as sns
import optuna
from matplotlib import pylab as plt
%matplotlib inline
from fbprophet import Prophet
from fbprophet.plot import add_changepoints_to_plot
import warnings
warnings.filterwarnings("ignore")
# https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/AirPassengers.html
df = pd.read_csv('../data/AirPassengers.csv')
# float型に変換
df['#Passengers'] = df['#Passengers'].astype('float64')
df = df.rename(columns={'#Passengers': 'Passengers'})
# datetime型に変換にする
df.Month = pd.to_datetime(df.Month)
# データの中身を確認
df.head()
# データの可視化
fig, ax = plt.subplots()
a = sns.lineplot(x="Month", y="Passengers", data=df)
plt.show()
Prophetでモデルを構築します。
def objective_variable(train, valid):
def objective(trial):
params = {
'changepoint_range' : trial.suggest_discrete_uniform('changepoint_range', 0.8, 0.95, 0.001),
'n_changepoints' : trial.suggest_int('n_changepoints', 20, 35),
'changepoint_prior_scale' : trial.suggest_discrete_uniform('changepoint_prior_scale',0.001, 0.5, 0.001),
'seasonality_prior_scale' : trial.suggest_discrete_uniform('seasonality_prior_scale',1, 25, 0.1),
}
# fit_model
model = Prophet(
changepoint_range = params['changepoint_prior_scale'],
n_changepoints=params['n_changepoints'],
changepoint_prior_scale=params['changepoint_prior_scale'],
seasonality_prior_scale = params['seasonality_prior_scale'],
)
model.fit(train)
future = model.make_future_dataframe(periods=len(valid))
forecast = model.predict(future)
valid_forecast = forecast.tail(len(valid))
val_mape = np.mean(np.abs((valid_forecast.yhat-valid.y)/valid.y))*100
return val_mape
return objective
def optuna_parameter(train, valid):
study = optuna.create_study(sampler=optuna.samplers.RandomSampler(seed=10))
study.optimize(objective_variable(train, valid), timeout=500)
optuna_best_params = study.best_params
return study
df = df.rename(columns={'Month':'ds','Passengers':'y'})
df = df[['ds','y']]
df_train = df[df['ds'] < '1956-04-01']
df_valid = df[(df['ds'] >= '1956-04-01')&(df['ds'] < '1957-04-01')]
df_test = df[df['ds'] >= '1957-04-01']
study = optuna_parameter(df_train, df_valid)
あとは、チューニング結果のハイパーパラメータを使ってモデルの学習と予測を行います。
# fit_model
best_model = Prophet(
changepoint_range = study.best_params['changepoint_prior_scale'],
n_changepoints=study.best_params['n_changepoints'],
seasonality_prior_scale = study.best_params['seasonality_prior_scale'],
changepoint_prior_scale=study.best_params['changepoint_prior_scale'],
)
best_model.fit(df_train)
feature_test = best_model.make_future_dataframe(periods=len(df_valid)+len(df_test), freq='M')
forecast_test = best_model.predict(feature_test)
forecast_test_plot = best_model.plot(forecast_test)
fig, ax = plt.subplots()
df.y.plot(ax=ax, label='Original', linestyle="dashed")
forecast_test.yhat.plot(ax=ax, label='Predict')
ax.legend()
##さいごに
最後まで読んで頂き、ありがとうございました。
今回は時系列解析手法のProphetをOptunaでハイパラチューニングをしてみました。
訂正要望がありましたら、ご連絡頂けますと幸いです。