5.2 いくつかの単純な予測手法

とても単純で、かつ、驚くほど効果的な予測手法がいくつかあります。本書を通じて、4つの単純な予測手法をベンチマークとして使用します。例示のため、オーストラリアの1970年から2004年までの粘土れんがの四半期生産量を使いましょう。

bricks <- aus_production %>%
  filter_index("1970 Q1" ~ "2004 Q4")

filter_index()関数は、時系列データの一部を切り出すのに便利です。

平均法

この手法では、全ての将来値の予測を、過去のデータの平均値と等しくします。過去のデータを\(y_{1},\dots,y_{T}\)で表すと、予測は以下のように書けます。 \[ \hat{y}_{T+h|T} = \bar{y} = (y_{1}+\dots+y_{T})/T \] \(\hat{y}_{T+h|T}\)という表記は、\(y_1,\dots,y_T\)のデータに基づいた\(y_{T+h}\)の推計値を表す略記です。

bricks %>% model(MEAN(Bricks))
オーストラリアの粘土れんが生産量に適用した平均予測

図 5.3: オーストラリアの粘土れんが生産量に適用した平均予測

ナイーブ法

ナイーブ予測では、最後の観測値を全ての予測にするだけです。つまり、以下の通りです。 \[ \hat{y}_{T+h|T} = y_{T} \] この手法は、多くの経済・金融時系列でとても上手く機能します。

bricks %>% model(NAIVE(Bricks))
オーストラリアの粘土れんが生産量に適用したナイーブ予測

図 5.4: オーストラリアの粘土れんが生産量に適用したナイーブ予測

データがランダムウォーク(9.1節を参照)に従う場合、ナイーブ予測が最適になるので、ランダムウォーク予測とも呼ばれ、NAIVE関数の替わりにRW()関数を使うことができます。

季節ナイーブ法

季節性の強いデータには、似た手法が役に立ちます。この場合、季節ごとの予測を同じ季節の最後の観測値(例えば、前年同月値)と等しくします。式としては、\(T+h\)時点の予測は、以下のように書けます。 \[ \hat{y}_{T+h|T} = y_{T+h-m(k+1)} \] ただし、\(m\)は季節周期、\(k\)\((h-1)/m\)の整数部分(つまり、\(T+h\)時点以前の予測期間に含まれる完全な年の数)です。この式は複雑そうに見えますが、実際はもっと簡単です。例えば、月次データの場合、2月の将来全ての予測値は最後に観測された2月値と等しくします。四半期データの場合、Q2の将来全ての予測は最後に観測されたQ2値と等しくします(Q2は第2四半期を指します)。他の月や四半期、あるいは、それ以外の季節周期についても、同じルールが適用されます。

bricks %>% model(SNAIVE(Bricks ~ lag("year")))

この例では、lag()関数を指定することはオプションで、しなくて構いません。bricksは四半期データなので、季節ナイーブ法が必要とするラグは1年に決まっているからです。しかし、季節周期が複数ある時系列もあり、その場合はラグを指定しなければなりません。

オーストラリアの粘土れんが生産量に適用した季節ナイーブ予測

図 5.5: オーストラリアの粘土れんが生産量に適用した季節ナイーブ予測

ドリフト法

この手法はナイーブ法の変形で、予測値が時とともに増加もしくは減少できるようにして、その経時変化量(ドリフトと呼びます)を過去のデータでの平均的変化量と等しくします。すると、\(T+h\)時点の予測は以下のようになります。 \[ \hat{y}_{T+h|T} = y_{T} + \frac{h}{T-1}\sum_{t=2}^T (y_{t}-y_{t-1}) = y_{T} + h \left( \frac{y_{T} -y_{1}}{T-1}\right) \] 最初と最後の観測値を直線で結び、将来に向けて外挿することと同じです。

bricks %>% model(RW(Bricks ~ drift()))
オーストラリアの粘土れんが生産量に適用したドリフト予測

図 5.6: オーストラリアの粘土れんが生産量に適用したドリフト予測

事例: オーストラリアの四半期ビール生産量

5.7は、1992年から2006年までのオーストラリア四半期ビール生産量に、これまで述べた予測手法の3つを適用して、3.5年先までの予測と実績を比較したものです。

# 1992年から2006年までを訓練データにセット
train <- aus_production %>%
  filter_index("1992 Q1" ~ "2006 Q4")
# モデルを当てはめる
beer_fit <- train %>%
  model(
    "平均" = MEAN(Beer),
    "ナイーブ" = NAIVE(Beer),
    "季節ナイーブ" = SNAIVE(Beer)
  )
# その先14四半期の予測を生成
beer_fc <- beer_fit %>% forecast(h = 14)
# 予測と実績をプロット
beer_fc %>%
  autoplot(train, level = NULL) +
  autolayer(
    filter_index(aus_production, "2007 Q1" ~ .),
    colour = "black"
  ) +
  labs(
    y = "メガリットル",
    title = "四半期ビール生産量の予測"
  ) +
  guides(colour = guide_legend(title = "予測手法"))
オーストラリア四半期ビール生産量の予測

図 5.7: オーストラリア四半期ビール生産量の予測

このケースでは、季節ナイーブ予測だけが2007年以降の観測値と近い値になっています。

事例: Googleの日次株価終値

5.8では、2015年のGoogleの日次株価終値に非季節性データ向けの手法を適用し、1カ月先の予測をしています。株価は毎日観測されるわけではないので、まず暦日ではなく営業日に基づく新しい時間インデックスを作ります。

# 営業日に基づいて再インデックス
google_stock <- gafa_stock %>%
  filter(Symbol == "GOOG", year(Date) >= 2015) %>%
  mutate(day = row_number()) %>%
  update_tsibble(index = day, regular = TRUE)
# 興味のある年を抽出
google_2015 <- google_stock %>% filter(year(Date) == 2015)
# モデルを当てはめる
google_fit <- google_2015 %>%
  model(
    "平均" = MEAN(Close),
    "ナイーブ" = NAIVE(Close),
    "ドリフト" = NAIVE(Close ~ drift())
  )
# 2016年1月営業日の予測を生成
google_jan_2016 <- google_stock %>%
  filter(yearmonth(Date) == yearmonth("2016 Jan"))
google_fc <- google_fit %>%
  forecast(new_data = google_jan_2016)
# 予測をプロット
google_fc %>%
  autoplot(google_2015, level = NULL) +
  autolayer(google_jan_2016, Close, colour = "black") +
  labs(y = "米ドル",
       title = "Googleの日次株価終値",
       subtitle = "(2015年1月 - 2016年1月)") +
  guides(colour = guide_legend(title = "予測手法"))
Googleの日次株価終値の予測

図 5.8: Googleの日次株価終値の予測

これらの単純な手法の一つが、利用可能な予測手法の中で最良であることがまれにあります。しかし、多くのケースでは、これらは選択すべき手法ではなく、予測評価のベンチマークとして使われる手法です。つまり、開発する予測手法をこれらの単純な手法と比較し、新しい手法の方が優れていることを確認するために利用します。開発した新手法に基づく予測が優れていない場合、新しい手法は考慮に値しない、ということになります。