BigQuery MLの時系列予測でFORECAST_LIMIT_LOWER_BOUNDを使った制限オプションと、休日オプションとの組み合わせを確認する

BQMLの時系列予測の結果について、上限・下限を仮定した結果を出力できるようにするオプションが一般提供開始されたので、下限の方を試してみました。
2023.12.10

データアナリティクス事業本部 機械学習チームの鈴木です。

この記事はBigQuery Advent Calendar 2023の10日目の記事になります。

先月BigQuery MLの時系列予測で、FORECAST_LIMIT_LOWER_BOUNDFORECAST_LIMIT_UPPER_BOUNDオプションにより、推定結果の下限および上限を仮定できる機能が一般提供開始になりました。

この機能について公式のチュートリアルについて、休日の効果も考慮した例を実行してみたのでご紹介します。また、休日に関する組み込み関数も使ったことがなかったのでこれを機に試してみました。

この記事について

FORECAST_LIMIT_LOWER_BOUNDを使った以下の時系列予測のチュートリアルを元に、一般提供開始となった時系列モデルの予測値を制限する機能を確認しつつ、BigQuery MLのholiday_regionオプションも試してみたレポートになります。

チュートリアル自体が非常に分かりやすく、FORECAST_LIMIT_LOWER_BOUNDを使うとどのように推定結果が変化するかすぐに理解できます。

この記事の内容としてはチュートリアルに沿って操作を見つつ、チュートリアル中ではされていなかった休日オプションの有効化と、せっかくなので前から気になっていたML.HOLIDAY_INFO関数など休日に関する関数も確認してみました。

実際に試してみると、休日の影響を評価するML.EXPLAIN_FORECAST関数とは、この機能は一緒に使えないような事象も分かりましたので触れておきます。

オプションによる推定結果の変化を確認する

早速、チュートリアルにしたがって、FORECAST_LIMIT_LOWER_BOUNDオプションの有無でどのように結果が変わるか確認します。休日のオプションも有効にするため、チュートリアルとの結果の違いが気になる方はその観点でもご確認下さい。

FORECAST_LIMIT_LOWER_BOUNDを指定しないとき

まずは以下のようにARIMA_PLUSを使い、nyc_citibike_arima_modelモデルを作成しました。bqml_tutorialデータセットはあらかじめUSマルチリージョンに作成しておきました。

-- https://cloud.google.com/bigquery/docs/time-series-forecasting-holidays-tutorial?hl=jaより2023/12/9に引用した。
-- holiday_regionの指定を追加した。

#standardSQL
CREATE OR REPLACE MODEL bqml_tutorial.nyc_citibike_arima_model
OPTIONS
  (model_type = 'ARIMA_PLUS',
   holiday_region = 'US',
   time_series_timestamp_col = 'date',
   time_series_data_col = 'num_trips'
  ) AS
SELECT
   EXTRACT(DATE from starttime) AS date,
   COUNT(*) AS num_trips
FROM
  `bigquery-public-data`.new_york.citibike_trips
WHERE starttime > '2014-07-11' AND starttime < '2015-02-11'
GROUP BY date

モデルが作成できたら、以下のように推論を行いました。

-- https://cloud.google.com/bigquery/docs/time-series-forecasting-holidays-tutorial?hl=jaより2023/12/9に引用した。

#standardSQL
  SELECT
  forecast_timestamp AS forecast_timestamp,
  history_value AS history_value,
  forecast_value AS forecast_value
  FROM ( (
     SELECT
        DATE(forecast_timestamp) AS forecast_timestamp,
        NULL AS history_value,
        forecast_value AS forecast_value
     FROM
        ML.FORECAST(MODEL bqml_tutorial.`nyc_citibike_arima_model`,
        STRUCT(365 AS horizon,
           0.9 AS confidence_level)) )
  UNION ALL (
     SELECT
        DATE(date_name) AS forecast_timestamp,
        num_trips AS history_value,
        NULL AS forecast_value
     FROM (
        SELECT
        EXTRACT(DATE
        FROM
           starttime) AS date_name,
        COUNT(*) AS num_trips
        FROM
        `bigquery-public-data`.new_york.citibike_trips
        WHERE
        starttime > '2014-07-11'
        AND starttime < '2015-02-11'
        GROUP BY
        date_name ) ))
  ORDER BY
  forecast_timestamp

クエリの結果でグラフタブを開くと、以下のようにnum_tripsの推定値が0を通り越して負の値になりました。これでも推定の最初の方の日付範囲はいいかもしれませんが、しばらく先に0に向かっていくだろうという仮説を立てた上での推定結果としては改善の余地がありそうです。

制限なしの推定結果

FORECAST_LIMIT_LOWER_BOUNDを指定したとき

ではFORECAST_LIMIT_LOWER_BOUNDを指定したいと思います。チュートリアルでは、カウント負の値にならないことは明らかなので、forecast_limit_lower_bound = 0という指定をしています。

以下を実行してモデルを作成しました。

-- https://cloud.google.com/bigquery/docs/time-series-forecasting-holidays-tutorial?hl=jaより2023/12/9に引用した。
-- holiday_regionの指定を追加した。

#standardSQL
CREATE OR REPLACE MODEL `bqml_tutorial.nyc_citibike_arima_model_with_limits`
OPTIONS
  (model_type = 'ARIMA_PLUS',
   holiday_region = 'US',
   time_series_timestamp_col = 'date',
   time_series_data_col = 'num_trips',
   forecast_limit_lower_bound = 0
  ) AS
SELECT
   EXTRACT(DATE from starttime) AS date,
   COUNT(*) AS num_trips
FROM
  `bigquery-public-data`.new_york.citibike_trips
WHERE starttime > '2014-07-11' AND starttime < '2015-02-11'
GROUP BY date

モデルが作成できたら、以下のように推論を行いました。

-- https://cloud.google.com/bigquery/docs/time-series-forecasting-holidays-tutorial?hl=jaより2023/12/9に引用した。

#standardSQL
  SELECT
  forecast_timestamp AS forecast_timestamp,
  history_value AS history_value,
  forecast_value AS forecast_value
  FROM ( (
     SELECT
        DATE(forecast_timestamp) AS forecast_timestamp,
        NULL AS history_value,
        forecast_value AS forecast_value
     FROM
        ML.FORECAST(MODEL `bqml_tutorial.nyc_citibike_arima_model_with_limits`,
        STRUCT(365 AS horizon,
           0.9 AS confidence_level)) )
  UNION ALL (
     SELECT
        DATE(date_name) AS forecast_timestamp,
        num_trips AS history_value,
        NULL AS forecast_value
     FROM (
        SELECT
        EXTRACT(DATE
        FROM
           starttime) AS date_name,
        COUNT(*) AS num_trips
        FROM
        `bigquery-public-data`.new_york.citibike_trips
        WHERE
        starttime > '2014-07-11'
        AND starttime < '2015-02-11'
        GROUP BY
        date_name ) ))
  ORDER BY
  forecast_timestamp

以下のように0に近づく推定結果が作成されました。

制限ありの推定結果

今回は休日の効果も含めてみましたが、傾向としてそこまで大きな違いは出ませんでした。

休日の効果の確認

ML.HOLIDAY_INFO関数で考慮された休日の一覧を取得

以下のようにML.HOLIDAY_INFOで考慮された休日の一覧を確認してみました。

SELECT *
FROM
  ML.HOLIDAY_INFO(
    MODEL `bqml_tutorial.nyc_citibike_arima_model_with_limits`);

以下のようにクリスマスの考慮がされていることが分かりました。

休日効果の確認

primary_dateで休日がどの日付か、preholiday_dayspostholiday_daysで前後何日を休日期間として考慮に入れているかが分かります。

ほかにも多くの休日が考慮されていることが分かります。

WITH tmp AS (
  SELECT *
  FROM
    ML.HOLIDAY_INFO(MODEL `bqml_tutorial.nyc_citibike_arima_model_with_limits`)
)
SELECT 
  holiday_name,
  COUNT(holiday_name) AS cnt
FROM tmp
GROUP BY holiday_name;

考慮された休日の一覧

今回は組み込みの休日のみモデルで使用を指定したので、ML.HOLIDAY_INFO関数の対象は組み込みのものだけですが、直近でカスタム休日についても確認できるようになっています。

この関数の仕様については以下のガイドをご確認下さい。

ML.EXPLAIN_FORECAST関数も使えるのか確認

ML.EXPLAIN_FORECAST関数については、少なくとも記事執筆時点ではFORECAST_LIMIT_LOWER_BOUNDとは一緒に使うことはできないようでした。

EXPLAIN_FORECASTは一緒に使用できない

このオプションを有効にしてモデルを運用する場合は、ほかの機能とは競合する可能性があることは念頭におきつつ、検証段階でやりたいことができるのかは確認しておくと良さそうですね。

ちなみにML.EXPLAIN_FORECAST関数についても、カスタム休日もサポートされるようになっています。

最後に

BigQuery MLの時系列予測でFORECAST_LIMIT_LOWER_BOUNDを使った制限オプションを使った際の出力イメージを、チュートリアルの内容に追加して休日の効果も取り込んだバージョンで確認してみました。

また、休日に関する関数と組み合わせた際の現時点での挙動について確認しました。

参考になりましたら幸いです。

追記: ARIMA_PLUS_XREGモデルとの組み合わせ

Xでご指摘頂いたのでARIMA_PLUS_XREGモデルとオプションの組み合わせも確認しました。

ARIMA_PLUS_XREG時系列モデルは、linear external regressorsを備えたARIMA_PLUSモデルです。

以下のように手法をARIMA_PLUS_XREGに差し替えたところ、forecast_limit_lower_boundはサポートしていない旨が分かりました。

-- https://cloud.google.com/bigquery/docs/time-series-forecasting-holidays-tutorial?hl=jaより2023/12/10に引用した。
-- holiday_regionの指定を追加した。model_typeを変更した。

#standardSQL
CREATE OR REPLACE MODEL `bqml_tutorial.nyc_citibike_arima_xreg_model_with_limits`
OPTIONS
  (model_type = 'ARIMA_PLUS_XREG',
   time_series_timestamp_col = 'date',
   time_series_data_col = 'num_trips',
   forecast_limit_lower_bound = 0
  ) AS
SELECT
   EXTRACT(DATE from starttime) AS date,
   COUNT(*) AS num_trips
FROM
  `bigquery-public-data`.new_york.citibike_trips
WHERE starttime > '2014-07-11' AND starttime < '2015-02-11'
GROUP BY date

ARIMA_PLUS_XREGの例

オプションと手法との相性があると思うので、自分が使いたい手法と一緒に使えるのかは調査段階で簡単な例で試しておくと良さそうです。