BigQuery で数百万の時系列を使用してスケーラブルな予測を行う


このチュートリアルでは、1 つのクエリで複数の時系列予測を行うために、一連の時系列モデルのトレーニングを大幅に高速化する方法について説明します。また、予測精度を評価する方法についても学習します。

最後のステップを除くすべてのステップで、new_york.citibike_trips データを使用します。このデータには、ニューヨーク市でのシティバイクの利用状況に関する情報が含まれています。このデータセットには数百の時系列しか含まれていません。このデータセットを使用して、モデルのトレーニングを高速化するさまざまな方法を説明します。最後のステップでは、iowa_liquor_sales.sales データを使用して 100 万を超える時系列を予測します。

このチュートリアルを読む前に、ニューヨーク市のシティバイクの利用状況について 1 つのクエリで複数の時系列を予測するをご覧ください。また、大規模な時系列予測のベスト プラクティスもご覧ください。

目標

このチュートリアルでは、次のものを使用します。

わかりやすくするため、このチュートリアルでは ML.FORECAST または ML.EXPLAIN_FORECAST を使用して(説明可能な)予測を生成する方法について説明しません。これらの関数の使用方法については、ニューヨーク市のシティバイクの利用状況について 1 つのクエリで複数の時系列を予測するをご覧ください。

費用

このチュートリアルでは、Google Cloud の課金対象となる以下のコンポーネントを使用します。

  • BigQuery
  • BigQuery ML

費用の詳細については、BigQuery の料金BigQuery ML の料金をご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  5. Google Cloud プロジェクトで課金が有効になっていることを確認します

  6. 新しいプロジェクトでは、BigQuery が自動的に有効になります。既存のプロジェクトで BigQuery を有効にするには、

    BigQuery API を有効にします。

    API を有効にする

    にアクセスします。

ステップ 1: データセットを作成する

ML モデルを保存する BigQuery データセットを作成します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] ページに移動

  2. [エクスプローラ] ペインで、プロジェクト名をクリックします。

  3. (アクションを表示)> [データセットを作成] をクリックします。

    データセットを作成する。

  4. [データセットの作成] ページで、次の操作を行います。

    • [データセット ID] に「bqml_tutorial」と入力します。

    • [ロケーション タイプ] で [マルチリージョン] を選択してから、[US (米国の複数のリージョン)] を選択します。

      一般公開データセットは US マルチリージョンに保存されています。わかりやすくするため、データセットを同じロケーションに保存します。

    • 残りのデフォルトの設定は変更せず、[データセットを作成] をクリックします。

      データセットの作成ページ

ステップ 2: 予測する時系列を作成する

次のクエリでは、FROM bigquery-public-data.new_york.citibike_trips 句を使用して、new_york データセット内の citibike_trips テーブルのデータを取得します。

CREATE OR REPLACE TABLE
  `bqml_tutorial.nyc_citibike_time_series` AS
WITH input_time_series AS
(
  SELECT
    start_station_name,
    EXTRACT(DATE FROM starttime) AS date,
    COUNT(*) AS num_trips
  FROM
    `bigquery-public-data.new_york.citibike_trips`
  GROUP BY
    start_station_name, date
)
SELECT table_1.*
FROM input_time_series AS table_1
INNER JOIN (
  SELECT start_station_name,  COUNT(*) AS num_points
  FROM input_time_series
  GROUP BY start_station_name) table_2
ON
  table_1.start_station_name = table_2.start_station_name
WHERE
  num_points > 400

クエリを実行する手順は次のとおりです。

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、前述の GoogleSQL クエリを入力します。

  3. [実行] をクリックします。

クエリの SELECT ステートメントで EXTRACT 関数を使用して、starttime 列から日付情報を抽出します。さらに、COUNT(*) 句を使用して、1 日あたりのシティバイクの合計利用回数を取得します。

table_1 には 679 の時系列があります。このクエリでは、追加の INNER JOIN ロジックを使用して、400 を超える時点を持つすべての時系列を選択し、時系列の合計は 383 になります。

ステップ 3: デフォルトのパラメータを使用して複数の時系列を同時に予測する

このステップでは、さまざまなシティバイク ステーションでの 1 日あたりの合計利用回数を予測します。これを行うには、複数の時系列を予測する必要があります。複数の CREATE MODEL クエリを作成できますが、時系列が非常に多い場合は、作成に手間や時間がかかる可能性があります。

この作業を効率的に行うため、BigQuery ML では、1 つのクエリで複数の時系列を予測する一連の時系列モデルを作成できます。また、すべての時系列モデルが同時に適合されます。

次の GoogleSQL クエリでは、CREATE MODEL 句を使用して、bqml_tutorial.nyc_citibike_arima_model_default という名前のモデルセットを作成してトレーニングします。

CREATE OR REPLACE MODEL `bqml_tutorial.nyc_citibike_arima_model_default`
OPTIONS
  (model_type = 'ARIMA_PLUS',
   time_series_timestamp_col = 'date',
   time_series_data_col = 'num_trips',
   time_series_id_col = 'start_station_name'
  ) AS
SELECT *
FROM bqml_tutorial.nyc_citibike_time_series
WHERE date < '2016-06-01'

CREATE MODEL クエリを実行してモデルを作成し、トレーニングする手順は次のとおりです。

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、前述の GoogleSQL クエリを入力します。

  3. [実行] をクリックします。

    クエリが完了するまでに 14 分 25 秒ほどかかります。

OPTIONS(model_type='ARIMA_PLUS', time_series_timestamp_col='date', ...) 句で、一連の ARIMA ベースの時系列 ARIMA_PLUS モデルを作成します。time_series_timestamp_coltime_series_data_col のほかに、time_series_id_col を指定する必要があります。これは、異なる入力時系列にアノテーションを付けるために使用します。

この例では、2016 年 6 月 1 日以降の時系列の時点が除外されていますが、後でこれらの時点を使用して ML.EVALUATE 関数で予測精度を評価できます。

ステップ 4: 各時系列の予測精度を評価する

このステップでは、次の ML.EVALUATE クエリを使用して、各時系列の予測精度を評価します。

SELECT *
FROM
  ML.EVALUATE(MODEL `bqml_tutorial.nyc_citibike_arima_model_default`,
              TABLE `bqml_tutorial.nyc_citibike_time_series`,
              STRUCT(7 AS horizon, TRUE AS perform_aggregation))

これらのクエリを実行するには、次の手順を行います。

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、前述の GoogleSQL クエリを入力します。

  3. [実行] をクリックします。このクエリは、次のような予測指標を報告します。

    結果は次のようになります。 ML.EVALUATE output1。

ML.EVALUATE は、前のステップでトレーニングした ARIMA_PLUS モデルを最初の引数として受け取ります。

2 番目の引数は、正解データを含むデータテーブルです。これらの予測結果を正解データと比較して精度の指標を計算します。この場合、nyc_citibike_time_series には 2016 年 6 月 1 日以前と 2016 年 6 月 1 日以降の時系列ポイントの両方が含まれます。2016 年 6 月 1 日以降のポイントは正解データです。2016 年 6 月 1 日より前のポイントは、その日付以降の予測を生成するためにモデルのトレーニングに使用されます。指標の計算に必要なのは、2016 年 6 月 1 日以降のポイントのみです。2016 年 6 月 1 日より前のポイントは指標の計算で無視されます。

3 つ目の引数は STRUCT で、2 つのパラメータが含まれています。ホライズンは 7 ですが、これはクエリが 7 点予測に基づいて予測精度を計算することを意味します。正解データの比較ポイントが 7 点未満の場合、精度の指標は使用可能なポイントのみに基づいて計算されます。perform_aggregation の値は TRUE です。これは、予測精度の指標がその時点の指標に基づいて集計されることを意味します。perform_aggregation を FALSE に指定すると、予測された時点ごとに予測精度が返されます。

ステップ 5: すべての時系列の包括的な予測精度を評価する

このステップでは、次のクエリを使用して 383 の時系列全体の予測精度を評価します。

SELECT
  AVG(mean_absolute_percentage_error) AS MAPE,
  AVG(symmetric_mean_absolute_percentage_error) AS sMAPE
FROM
  ML.EVALUATE(MODEL `bqml_tutorial.nyc_citibike_arima_model_default`,
              TABLE `bqml_tutorial.nyc_citibike_time_series`,
              STRUCT(7 AS horizon, TRUE AS perform_aggregation))

ML.EVALUATE によって返される予測指標のうち、平均絶対誤差率対称平均絶対誤差率のみが時系列値に依存しません。したがって、一連の時系列の予測精度全体を評価するには、これら 2 つの指標の集計のみが有意となります。

このクエリの結果、MAPE は 0.3471、sMAPE は 0.2563 になります。

ステップ 6: 小さいハイパーパラメータ検索空間を使用して多数の時系列を同時に予測する

ステップ 3 では、auto_arima_max_order を含むすべてのトレーニング オプションにデフォルト値を使用しました。このオプションは、auto.ARIMA アルゴリズムでのハイパーパラメータ調整の検索空間を制御します。

このステップでは、ハイパーパラメータに使用する検索空間を小さくします。

CREATE OR REPLACE MODEL bqml_tutorial.nyc_citibike_arima_model_max_order_2
OPTIONS
  (model_type = 'ARIMA_PLUS',
   time_series_timestamp_col = 'date',
   time_series_data_col = 'num_trips',
   time_series_id_col = 'start_station_name',
   auto_arima_max_order = 2
  ) AS
SELECT *
FROM bqml_tutorial.nyc_citibike_time_series
WHERE date < '2016-06-01'

このクエリでは、auto_arima_max_order が 5(デフォルト値)から 2 に減らします。

クエリを実行する手順は次のとおりです。

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、前述の GoogleSQL クエリを入力します。

  3. [実行] をクリックします。

    クエリが完了するまでに 1 分 45 秒ほどかかります。auto_arima_max_order が 5 の場合は、クエリが完了するまでに 14 分 25 秒ほどかかりました。auto_arima_max_order を 2 に設定すると、速度ゲインは約 7 倍になります。速度ゲインが 5/2=2.5x でないのが不思議かもしれません。これは auto_arima_max_order の順序を増やすと、候補モデルの数が増えるだけでなく、モデルのトレーニング時間も長くなるためです。

ステップ 7: 小さいハイパーパラメータ検索空間に基づいて予測精度を評価する

SELECT
  AVG(mean_absolute_percentage_error) AS MAPE,
  AVG(symmetric_mean_absolute_percentage_error) AS sMAPE
FROM
  ML.EVALUATE(MODEL `bqml_tutorial.nyc_citibike_arima_model_max_order_2`,
              TABLE `bqml_tutorial.nyc_citibike_time_series`,
              STRUCT(7 AS horizon, TRUE AS perform_aggregation))

このクエリの結果、MAPE は 0.3337、sMAPE は 0.2337 になります。

ステップ 5 では、大きいハイパーパラメータ検索空間を使用して auto_arima_max_order = 5 となったため、MAPE は 0.3471、sMAPE は 0.2563 となりました。つまり、この場合はハイパーパラメータ検索空間が小さいほど、予測精度が高くなります。理由の 1 つは、auto.ARIMA アルゴリズムが、モデリング パイプライン全体のトレンド モジュールに対してのみハイパーパラメータ調整を実行したためです。auto.ARIMA アルゴリズムによって選択された最良の ARIMA モデルが、パイプライン全体に対して最良の予測結果を生成するとは限りません。

ステップ 8: 小さいハイパーパラメータ検索空間とスマートな高速トレーニング戦略で多数の時系列を同時に予測する

このステップでは、小さいハイパーパラメータ検索空間と、1 つ以上の max_time_series_lengthmax_time_series_length、または time_series_length_fraction トレーニング オプションを使用したスマートな高速トレーニング戦略の両方を使用します。

季節性などの定期的なモデリングには一定数の時点が必要ですが、トレンド モデリングの場合、必要な時点は少なくなります。一方、トレンド モデリングは、季節性などの他の時系列コンポーネントよりも計算コストがはるかに高くなります。上記の高速トレーニング オプションを使用すると、他の時系列コンポーネントでは時系列全体を使用しながら、時系列のサブセットを使用してトレンド コンポーネントを効率的にモデル化できます。

この例では、高速トレーニングを実現するため、max_time_series_length を使用します。

CREATE OR REPLACE MODEL `bqml_tutorial.nyc_citibike_arima_model_max_order_2_fast_training`
OPTIONS
  (model_type = 'ARIMA_PLUS',
   time_series_timestamp_col = 'date',
   time_series_data_col = 'num_trips',
   time_series_id_col = 'start_station_name',
   auto_arima_max_order = 2,
   max_time_series_length = 30
  ) AS
SELECT *
FROM `bqml_tutorial.nyc_citibike_time_series`
WHERE date < '2016-06-01'

max_time_series_length オプションの値は 30 であるため、383 の時系列ごとに、直近 30 の時点のみがトレンド コンポーネントのモデル化に使用されます。トレンド以外のコンポーネントのモデル化には、引き続きすべての時系列が使用されます。

クエリを実行する手順は次のとおりです。

  1. Google Cloud コンソールで、[クエリを新規作成] ボタンをクリックします。

  2. [クエリエディタ] のテキスト領域に、前述の GoogleSQL クエリを入力します。

  3. [実行] をクリックします。

    このクエリが完了するまでに 35 秒ほどかかります。これは、高速トレーニング戦略を使用しないトレーニング クエリ(1 分 45 秒)よりも 3 倍速くなっています。データの前処理など、クエリのトレーニング以外のオーバーヘッドが一定であるため、この例よりも時系列の数がはるかに多い場合、速度ゲインが大幅に向上します。100 万の時系列の場合、速度ゲインは時系列の長さと max_time_series_length の値の比率に近づきます。この場合、速度ゲインは 10 倍以上になります。

ステップ 9: 小さいハイパーパラメータ検索空間とスマートな高速トレーニング戦略でモデルの予測精度を評価する

SELECT
  AVG(mean_absolute_percentage_error) AS MAPE,
  AVG(symmetric_mean_absolute_percentage_error) AS sMAPE
FROM
  ML.EVALUATE(MODEL `bqml_tutorial.nyc_citibike_arima_model_max_order_2_fast_training`,
              TABLE `bqml_tutorial.nyc_citibike_time_series`,
              STRUCT(7 AS horizon, TRUE AS perform_aggregation))

このクエリの結果、MAPE は 0.3515、sMAPE は 0.2473 になります。

高速トレーニング戦略を使用しない場合、予測精度の結果は MAPE が 0.3337、sMAPE が 0.2337 でした。2 つの指標値の差は 3% 以内であり、統計的に有意ではありません。

つまり、予測精度を犠牲にすることなく、モデル トレーニングを 20 倍以上高速化するため、小さいハイパーパラメータ検索空間とスマートな高速トレーニング戦略を使用しています。前述のように、時系列が多いほど、スマートな高速トレーニング戦略による速度ゲインが大幅に向上する可能性があります。さらに、ARIMA_PLUS で使用されている基盤となる ARIMA ライブラリは、以前よりも 5 倍速く実行されるよう最適化されています。これにより、何百万もの時系列を数時間で予測できるようになります。

ステップ 10: 100 万時系列で予測を行う

このステップでは、公開されているアイオワ州の酒類販売データを使用して、さまざまな店舗での 100 万を超える酒類製品の酒類販売を予測します。

CREATE OR REPLACE MODEL
  `bqml_tutorial.liquor_forecast_by_product`
OPTIONS(
  MODEL_TYPE = 'ARIMA_PLUS',
  TIME_SERIES_TIMESTAMP_COL = 'date',
  TIME_SERIES_DATA_COL = 'total_bottles_sold',
  TIME_SERIES_ID_COL = ['store_number', 'item_description'],
  HOLIDAY_REGION = 'US',
  AUTO_ARIMA_MAX_ORDER = 2,
  MAX_TIME_SERIES_LENGTH = 30
) AS
SELECT
  store_number,
  item_description,
  date,
  SUM(bottles_sold) as total_bottles_sold
FROM
  `bigquery-public-data.iowa_liquor_sales.sales`
WHERE date BETWEEN DATE("2015-01-01") AND DATE("2021-12-31")
GROUP BY store_number, item_description, date

モデルのトレーニングでは、引き続き小さいハイパーパラメータ検索空間とスマートな高速トレーニング戦略が使用されます。このクエリが完了するまでに 1 時間 16 分ほどかかります。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

  • 作成したプロジェクトを削除する。
  • または、プロジェクトを保存して、データセットを削除する。

データセットを削除する

プロジェクトを削除すると、プロジェクト内のデータセットとテーブルがすべて削除されます。プロジェクトを再利用する場合は、このチュートリアルで作成したデータセットを削除できます。

  1. 必要に応じて、Google Cloud コンソールで [BigQuery] ページを開きます。

    [BigQuery] ページに移動

  2. ナビゲーションで、作成した bqml_tutorial データセットをクリックします。

  3. [データセットの削除] をクリックして、データセット、テーブル、すべてのデータを削除します。

  4. [データセットの削除] ダイアログ ボックスでデータセットの名前(bqml_tutorial)を入力し、[削除] をクリックして確定します。

プロジェクトの削除

プロジェクトを削除するには:

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ