2
1

More than 3 years have passed since last update.

ProphetをOptunaでハイパラチューニングをしてみた

Posted at
  • 製造業出身のデータサイエンティストがお送りする記事
  • 今回は時系列解析手法の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()

スクリーンショット 2020-12-05 12.41.18.png

# データの可視化
fig, ax = plt.subplots()
a = sns.lineplot(x="Month", y="Passengers", data=df)
plt.show()

image.png

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)

image.png

fig, ax = plt.subplots()
df.y.plot(ax=ax, label='Original', linestyle="dashed")
forecast_test.yhat.plot(ax=ax, label='Predict')
ax.legend()

image.png

さいごに

最後まで読んで頂き、ありがとうございました。
今回は時系列解析手法のProphetをOptunaでハイパラチューニングをしてみました。

訂正要望がありましたら、ご連絡頂けますと幸いです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1