【R】modeltime

1. はじめに

tidymodelsパッケージを使えば、時系列データの予測も簡単にできます。modeltimeパッケージでは、古典的な時系列予測と機械学習を一度に扱えます。Getting Started with Modeltimeのページを参考に勉強してみます。

modeltimeのワークフローは次の通り。
*学習用/テスト用データの準備
*複数のモデルの生成とFit
*FitしたモデルをModelTableに追加
*モデルのキャリブレーション
*テストデータでの予測と精度評価
*Refitと予測

2. 使ってみる

2.1 準備

library(tidymodels)
library(modeltime)
library(tidyverse)
library(lubridate)
library(timetk)

interactive <- TRUE #インタラクティブプロット

2.2 データ

データは、4th M competitionのデータセットを使います。詳細はこちら。データは、id毎に分けられており、m1, m2 ,m750, m1000がありますが、m750を使います。なぜなら、予測に使いやすいデータなので(笑)。

使用するm4_monthlyというデータはこんな感じ。

# A tibble: 1,574 x 3
   id    date       value
   <fct> <date>     <dbl>
 1 M1    1976-06-01  8000
 2 M1    1976-07-01  8350
 3 M1    1976-08-01  8570
 4 M1    1976-09-01  7700
 5 M1    1976-10-01  7080
 6 M1    1976-11-01  6520
 7 M1    1976-12-01  6070
 8 M1    1977-01-01  6650
 9 M1    1977-02-01  6830
10 M1    1977-03-01  5710
# ... with 1,564 more rows

このうち、idがm750のデータのみを使います。

m750 <- m4_monthly %>% filter(id == "M750")

プロットして確認します。

m750 %>%
  plot_time_series(date, value, .interactive = interactive)

何となく、予測しやすそうなグラフ(笑)。

学習用とテスト用のデータに分けます。

splits <- initial_time_split(m750, prop = 0.9)

2.3 複数モデルの生成とFit

ここでは、モデルを6つ作ってみて、どれが良いかを比べてみます。modeltimeparsnipを使ってモデルを作ります。

2.3.1 モデル1 Auto ARIMA (modeltime)

model_fit_arima_no_boost <- arima_reg() %>%
    set_engine(engine = "auto_arima") %>%
    fit(value ~ date, data = training(splits))

2.3.2 モデル2 Boosted Auto ARIMA(modeltime)

model_fit_arima_boosted <- arima_boost(
    min_n = 2,
    learn_rate = 0.015
) %>%
    set_engine(engine = "auto_arima_xgboost") %>%
    fit(value ~ date + as.numeric(date) + factor(month(date, label = TRUE), ordered = F),
        data = training(splits))

2.3.3 モデル3 Exponential Smoothing (modeltime)

model_fit_ets <- exp_smoothing() %>%
    set_engine(engine = "ets") %>%
    fit(value ~ date, data = training(splits))

2.3.4 モデル4 prophet (modeltime)

model_fit_prophet <- prophet_reg() %>%
    set_engine(engine = "prophet") %>%
    fit(value ~ date, data = training(splits))

2.3.5 モデル5 Linear Regression(parsnip)

model_fit_lm <- linear_reg() %>%
    set_engine("lm") %>%
    fit(value ~ as.numeric(date) + factor(month(date, label = TRUE), ordered = FALSE),
        data = training(splits))

2.3.6 モデル6 Multivariate Adaptive Regression Spline(MARS)(workflow)

model_spec_mars <- mars(mode = "regression") %>%
    set_engine("earth")

recipe_spec <- recipe(value ~ date, data = training(splits)) %>%
    step_date(date, features = "month", ordinal = FALSE) %>%
    step_mutate(date_num = as.numeric(date)) %>%
    step_normalize(date_num) %>%
    step_rm(date)

wflw_fit_mars <- workflow() %>%
    add_recipe(recipe_spec) %>%
    add_model(model_spec_mars) %>%
    fit(training(splits))

2.4 ModelTableへの追加

上記、6つのモデルをモデルテーブルへ追加します。

models_tbl <- modeltime_table(
    model_fit_arima_no_boost,
    model_fit_arima_boosted,
    model_fit_ets,
    model_fit_prophet,
    model_fit_lm,
    wflw_fit_mars
)

models_tbl
> models_tbl
# Modeltime Table
# A tibble: 6 x 3
  .model_id .model     .model_desc                              
      <int> <list>     <chr>                                    
1         1 <fit[+]>   ARIMA(1,0,1)(0,1,1)[12]                  
2         2 <fit[+]>   ARIMA(1,0,1)(0,1,1)[12] W/ XGBOOST ERRORS
3         3 <fit[+]>   ETS(A,N,A)                               
4         4 <fit[+]>   PROPHET                                  
5         5 <fit[+]>   LM                                       
6         6 <workflow> EARTH 

2.5 モデルのキャリブレーション

calibration_tbl <- models_tbl %>%
    modeltime_calibrate(new_data = testing(splits))

calibration_tbl
> calibration_tbl
# Modeltime Table
# A tibble: 6 x 5
  .model_id .model     .model_desc                               .type .calibration_data
      <int> <list>     <chr>                                     <chr> <list>           
1         1 <fit[+]>   ARIMA(1,0,1)(0,1,1)[12]                   Test  <tibble [31 x 4]>
2         2 <fit[+]>   ARIMA(1,0,1)(0,1,1)[12] W/ XGBOOST ERRORS Test  <tibble [31 x 4]>
3         3 <fit[+]>   ETS(A,N,A)                                Test  <tibble [31 x 4]>
4         4 <fit[+]>   PROPHET                                   Test  <tibble [31 x 4]>
5         5 <fit[+]>   LM                                        Test  <tibble [31 x 4]>
6         6 <workflow> EARTH                                     Test  <tibble [31 x 4]>

2.6 予測と精度評価

まずは、プロットして予測の精度を可視化してみます。

calibration_tbl %>%
    modeltime_forecast(
        new_data    = testing(splits),
        actual_data = m750
    ) %>%
    plot_modeltime_forecast(
      .legend_max_width = 25, 
      .interactive      = interactive
    )

モデル3が最もよく、モデル1、2、4が同程度に良いです。モデル6はオーバーフィッティングです。数値でちゃんと確認してみます。

calibration_tbl %>%
    modeltime_accuracy() %>%
    table_modeltime_accuracy(resizable = TRUE, bordered = TRUE)

yardstickパッケージの評価結果を表示しています。
MAE-Mean Absolute Error,
MAPE-Mean Absolute Percentage Error,
MASE – Mean Absolute Square Error,
SMAPE – Symmetric Mean Absolute Percentage Error,
RMSE – Root Mean Squared Error,
RSQ – R – Squared

この結果からもモデル3が最も良いことが分かります。

2.7 Refitと将来予測

Refitをして、5年分の将来予測をしてみます。

refit_tbl <- calibration_tbl %>%
    modeltime_refit(data = m750)

refit_tbl %>%
    modeltime_forecast(h = "5 years", actual_data = m750) %>%
    plot_modeltime_forecast(
      .legend_max_width = 25, 
      .interactive      = interactive
    )

3. さいごに

色々なモデルを比較でき、最も良いモデルを探すことができました。これぐらい将来予測できると十分です。実際のビジネスでも使えるようになりたいですね。

Add a Comment

メールアドレスが公開されることはありません。