5.10 時系列交差検証

データセットを訓練データとテストデータに分割する方法をより洗練したのが、時系列交差検証です。 この手順では、それぞれ1つの観測値から成るテストセットが連なります。それぞれに対応する訓練セットはテストセットの観測値以前に生じた観測値だけから出来ています。こうすることで、将来の観測値が予測生成に使われないようにしています。訓練セットが小規模になると信頼できる予測が得られないので、標本期間の初期の観測値はテストセットにしません。

以下のダイアグラムは一連の訓練セットとテストセットを示しています。青色の観測値が訓練セットで、オレンジ色の観測値がテストセットです。

予測の正確性は、一連のテストセットでの結果を平均して計算します。この手順は「予測の起源をローリングすることによる評価 (evaluation on a rolling forecasting origin)」と呼ばれることもあります。予測が基づいている「起源」が時間方向に前へローリングされていくからです。

時系列予測では、1期先予測よりも、複数期先予測の方が重要な場合もあるでしょう。その場合、予測起源のローリングに基づく交差検証手順は、複数期先誤差が使えるように修正できます。ここで\(4\)期先予測を正確に予測するモデルに興味があるとします。すると、対応するダイアグラムは以下のようになります。

以下の例では、時系列交差検証からの正確性と訓練セットの残差からの正確性を比較します。まずstretch_tsibble()関数を使って、訓練セットを複数生成します。この例では、長さ.init=3の訓練セットから始めて、長さを.step=1ずつ増やしながら次々と訓練セットを作っています。

# 正確性を求める時系列交差検証のための訓練セット作成
google_2015_tr <- google_2015 %>%
  stretch_tsibble(.init = 3, .step = 1) %>%
  relocate(Date, Symbol, .id)
google_2015_tr
#> # A tsibble: 31,875 x 10 [1]
#> # Key:       Symbol, .id [250]
#>    Date       Symbol   .id  Open  High   Low Close Adj_Close  Volume   day
#>    <date>     <chr>  <int> <dbl> <dbl> <dbl> <dbl>     <dbl>   <dbl> <int>
#>  1 2015-01-02 GOOG       1  526.  528.  521.  522.      522. 1447600     1
#>  2 2015-01-05 GOOG       1  520.  521.  510.  511.      511. 2059800     2
#>  3 2015-01-06 GOOG       1  512.  513.  498.  499.      499. 2899900     3
#>  4 2015-01-02 GOOG       2  526.  528.  521.  522.      522. 1447600     1
#>  5 2015-01-05 GOOG       2  520.  521.  510.  511.      511. 2059800     2
#>  6 2015-01-06 GOOG       2  512.  513.  498.  499.      499. 2899900     3
#>  7 2015-01-07 GOOG       2  504.  504.  497.  498.      498. 2065100     4
#>  8 2015-01-02 GOOG       3  526.  528.  521.  522.      522. 1447600     1
#>  9 2015-01-05 GOOG       3  520.  521.  510.  511.      511. 2059800     2
#> 10 2015-01-06 GOOG       3  512.  513.  498.  499.      499. 2899900     3
#> # … with 31,865 more rows

.id列は、各訓練セットを指す新しいキー変数です。これを使うことで、accuracy()関数を使って、それら訓練セットをまとめて、予測の正確性を評価できるようになりました。

# 交差検証からの正確性
google_2015_tr %>%
  model(RW(Close ~ drift())) %>%
  forecast(h = 1) %>%
  accuracy(google_2015)
# 訓練セットからの正確性
google_2015 %>%
  model(RW(Close ~ drift())) %>%
  accuracy()
評価手法 RMSE MAE MAPE MASE
訓練セット 11.15 7.16 1.18 1.00
交差検証 11.27 7.26 1.19 1.02

やはり、訓練セットの残差からの正確性指標の方が小さくなりました。この「予測」はデータセット全体にモデルを当てはめており、真の意味で予測ではないからです。

最良の予測モデルを選択するには、時系列交差検証を使ってRMSEが最小となるモデルを見つけるのが良い方法です。

事例: 交差検証による予測期間ごとの正確性

5.9で示したgafa_stockデータの一部google_2015は、NASDAQでのGoogleの日次株価終値の2015年全営業日分データです。

以下のコードは、1から8期先のドリフト予測の予測性能を評価しています。プロットは、予測が先に延びるほど、予想通り予測誤差が大きくなることを示しています。

google_2015_tr <- google_2015 %>%
  stretch_tsibble(.init = 3, .step = 1)
fc <- google_2015_tr %>%
  model(RW(Close ~ drift())) %>%
  forecast(h = 8) %>%
  group_by(.id) %>%
  mutate(h = row_number()) %>%
  ungroup() %>%
  as_fable(response = "Close", distribution = Close)
fc %>%
  accuracy(google_2015, by = c("h", ".model")) %>%
  ggplot(aes(x = h, y = RMSE)) +
  geom_point()
Google株価終値にドリフト法を適用した場合の予測期間ごとのRMSE

図 5.24: Google株価終値にドリフト法を適用した場合の予測期間ごとのRMSE