【入門記事】2020年時点のBigQuery MLまとめ

2020.12.22

こんにちは、Mr.Moです。

このエントリは『クラスメソッド BigQuery Advent Calendar 2020』22本目のエントリです。12/25のアドベントカレンダー終了まで、弊社クラスメソッド データアナリティクス事業本部のメンバーで Google BigQuery に関する記事を紡いでいこうと思います。

当エントリでは現時点(2020年12月)でのBigQuery MLについてまとめてみたいと思います。

BigQuery MLとは

image.png

BigQuery ML を使用すると、BigQuery で標準 SQL クエリを使用して、機械学習モデルを作成し実行できます。BigQuery ML では、既存の SQL ツールやスキルを活用できるので、誰でも簡単に機械学習を利用できます。BigQuery ML では、データを移動する必要がないため、開発スピードを向上させることができます。

BigQuery ML(以下、BQML)には下記の特徴があります。

  • SQLさえ分かれば専門的な知識が無くても機械学習を使うことができる
  • DWH上で機械学習できるので、BigQueryからデータを移動させる処理も不要
  • 入力値の変換補完をしてくれる(標準化やワンホットエンコーディング、欠損値の補完)

BigQuery(DWH)上で機械学習モデルの作成ができるということで、データの移動といった事前の工程を省略することができます。何回か試行するとなった時にも効率が良さそうです。また、BigQuery ML(以下、BQML)では機械学習モデルの作成までも普段使い慣れているSQLで実施できてしまうので学習コストを抑えることもできますね。機械学習とデータウェアハウス(DWH)の分野に強いGCPならではのこの機能、もう少し詳細に見ていきましょう。

サポートされているモデルと機械学習の手法

実行できる機械学習の手法は回帰分類クラスタリングレコメンデーション時系列予測であり、それぞれ下記のモデルがサポートされています。

  • 回帰
    • Linear regression(線形回帰)
    • Deep Neural Network(DNN、回帰)
    • XGBoost(回帰)
    • AutoML Tables(回帰)
  • 分類
    • Binary logistic regression(2項分類)
    • Multiclass logistic regression(多項分類)
    • Deep Neural Network(DNN、分類)
    • XGBoost(分類)
    • AutoML Tables(分類)
  • クラスタリング
    • K-means clustering(K 平均法クラスタリング)
  • レコメンデーション
    • Matrix Factorization
  • 時系列予測
    • Time series(ARIMA)

さらに上記のモデル以外を扱いたい場合も外部から TensorFlow モデルをインポートできる機能、TensorFlow model importingもサポートされていますね。

なお、上記のうちDNN,XGBoostやAutoMLは別のサービスを使うイメージのようで、それぞれDNN,XGBoost:AI PlatformサービスAutoML:AutoML Tablesサービスでトレーニングされるようです。(DNN,XGBoostやAutoMLは組み込み以外のモデルという扱いになります)

料金体系

料金体系については定額とオンデマンド(クエリ実行の都度処理したバイト数などで課金)があり、組み込みモデルと組み込み以外のモデル(DNN,XGBoostやAutoML以外)でも料金のかかり方が違ってきます。

下記は東京リージョンでオンデマンドでトレーニングを実施した時の料金です。

  • 組み込みモデル
    • $300.00 per TB
  • 組み込みモデル以外
    • $6.00 per TB + AI Platformでの料金

あとは評価(Evaluation)、検査(Inspection)、予測(Prediction)といったタスク時にも$6.00 per TBの料金がかかります。

BQMLの基本構文

BQMLで主に行うタスクは下記の3つです。

  • モデルのトレーニング
  • モデルの評価
  • 予測

機械学習のタスクですが、もちろん上記すべてSQLで実施できます。公式のチュートリアルを題材に見ていきましょう。

と、その前に下記のようにBigQuery web UIにアクセスし事前にデータセットの作成をしておきます。

image.png

モデルのトレーニング

CREATE MODEL ステートメントを使ってモデルのトレーニングを行います。SQLに慣れている方ならあまり違和感が無いのではないでしょうか。ポイントはOPTIONSの部分ですね。ここで使用するモデルのタイプ(model_type)や目的変数である列名(input_label_cols)、各モデルのタイプで指定できるパラメータなどを設定します。詳細は公式ドキュメントを参照ください。

CREATE MODEL `blog.natality_model`
OPTIONS
  (model_type='linear_reg',
    input_label_cols=['weight_pounds']) AS
SELECT
    weight_pounds,
    is_male,
    gestation_weeks,
    ML.QUANTILE_BUCKETIZE(mother_age,
      5) OVER() AS bucketized_mother_age,
    CAST(mother_race AS string) AS mother_race,
    ML.FEATURE_CROSS(STRUCT(is_male,
        CAST(mother_race AS STRING) AS mother_race)) is_male_mother_race
FROM
  `bigquery-public-data.samples.natality`
WHERE
  weight_pounds IS NOT NULL
  AND RAND() < 0.001

なお、BQMLにはTRANSFORMという機能が用意されており、これは下記のSQLを見ておわかりいただけると思いますが前処理の設定をするものです。TRANSFORMを使うと何が嬉しいかと言うと予測の時に前処理で指定した(TRANSFORM句で設定している)長い構文を指定する必要が無くなるという点です。詳しくは予測のところで見ていただこうと思います。

CREATE MODEL `blog.natality_model`
TRANSFORM(weight_pounds,
    is_male,
    gestation_weeks,
    ML.QUANTILE_BUCKETIZE(mother_age,
      5) OVER() AS bucketized_mother_age,
    CAST(mother_race AS string) AS mother_race,
    ML.FEATURE_CROSS(STRUCT(is_male,
        CAST(mother_race AS STRING) AS mother_race)) is_male_mother_race)
OPTIONS
  (model_type='linear_reg',
    input_label_cols=['weight_pounds']) AS
SELECT
  *
FROM
  `bigquery-public-data.samples.natality`
WHERE
  weight_pounds IS NOT NULL
  AND RAND() < 0.001

BQMLのWeb UI上では下記のような感じです。

image.png

モデルの評価

トレーニングが終わったら出来上がったモデルがどのような状態か評価をしていきます。BQMLでは評価関数(ML.EVALUATE)が用意されているのでそれを使うだけでモデルの状態(精度など)を把握することができます。なお、評価関数には他にもML.ROC_CURVE(ロジスティック回帰かつ2項分類でしか使えない)やML.CONFUSION_MATRIX(ロジスティック回帰でしか使えない)も用意されています。

SELECT
  *
FROM
  ML.EVALUATE(MODEL `blog.natality_model`,
    (
    SELECT
      *
    FROM
      `bigquery-public-data.samples.natality`
    WHERE
      weight_pounds IS NOT NULL))

image.png

予測

トレーニングして評価関数でモデルの状態を確かめてを繰り返して納得するモデルが出来上がったらいよいよ予測ができる段階です。BQMLでは予測関数(ML.PREDICT)が用意されているのでまたもやこれを使うだけで簡単にモデルに予測のタスクを実行させることができます。ただし注意点としては、トレーニング時に渡していたデータと同じ状態のデータをモデルに入力する必要があるため、下記のように前処理を施したSQLを再び使うことになります。ちょっと面倒ですね...そこでTRANSFORMの出番です。

SELECT
  predicted_weight_pounds
FROM
  ML.PREDICT(MODEL `blog.natality_model`,
    (
    SELECT
      weight_pounds,
      is_male,
      gestation_weeks,
      ML.QUANTILE_BUCKETIZE(mother_age,
        5) OVER() AS bucketized_mother_age,
      CAST(mother_race AS string) AS mother_race,
      ML.FEATURE_CROSS(STRUCT(is_male,
          CAST(mother_race AS STRING) AS mother_race)) is_male_mother_race
    FROM
      `bigquery-public-data.samples.natality`
    WHERE
      state = "WY"))

TRANSFORMを使うとトレーニング時に指定した前処理を覚えてくれているので、下記のようにシンプルなSQL文でモデルに予測を実行させることができます。(上記のSQLと下記のSQLは内容的には同じことを実施しています。)

SELECT
  predicted_weight_pounds
FROM
  ML.PREDICT(MODEL `blog.natality_model`,
    (
    SELECT
      *
    FROM
      `bigquery-public-data.samples.natality`
    WHERE
      state = "WY"))

image.png

ちなみに、予測を実行する時に使う予測関数は使用したモデルのタイプで若干異なる関数を使うことになるので気にしておきましょう。具体的には時系列モデルを選択してトレーニングした場合はML.FORECAST、レコメンデーションのモデルを選択してトレーニングした場合はML.RECOMMENDの予測関数を使用することになります。

その他

他にもモデルの状態を確かめることができる検査関数がいくつか用意されていますので、適宜使用して作成されたモデルの内容を把握すると良いでしょう。

下記は特徴量の重要度を確認するML.WEIGHTSを使っているところです。(各特徴量が予測結果に与える影響度を確認することができます)

image.png

まとめ

GCPのサービスの中でも中心的なサービスであるBigQuery、そしてその機能の1つであるBQML。年々アップデートも入っていて今後もさらなる期待感があります。SQLの世界で機械学習が使えるというのも機械学習の民主化がぐっと加速しそうですね。個人的にもSQL好きなので使っていてものすごく楽です(笑)。新たに追加されたAutoML Tablesも大変強力ですし、今後のさらなる機能強化が待ち遠しいサービスです。

参考