ONNX 形式の PyTorch モデルを使用して予測を行う

概要

Open Neural Network Exchange(ONNX)は、ML フレームワークを統一された形式で表現するためのフォーマットです。ONNX に対する BigQuery ML サポートにより、次のことが可能になります。

  • 使い慣れたフレームワークを使用してモデルをトレーニングします。
  • モデルを ONNX 形式に変換します。詳細については、ONNX 形式への変換をご覧ください。
  • ONNX モデルを BigQuery にインポートし、BigQuery ML を使用して予測を行います。

このチュートリアルでは、PyTorch でトレーニングされた ONNX モデルを BigQuery データセットにインポートし、SQL クエリから予測を行う方法について説明します。ONNX モデルのインポートに使用できるインターフェースは次のとおりです。

  • Google Cloud コンソール
  • bq コマンドライン ツールの bq query コマンド
  • BigQuery API

形式やストレージの要件など、ONNX モデルを BigQuery にインポートする方法については、ONNX モデルをインポートする CREATE MODEL ステートメントをご覧ください。

目標

このチュートリアルの内容は次のとおりです。

  • PyTorch を使用してモデルの作成とトレーニングを行います。
  • torch.onnx を使用してモデルを ONNX 形式に変換します。
  • ONNX モデルを BigQuery にインポートして予測を行います。

画像分類用の PyTorch ビジョンモデルを作成する

BigQuery ML の ML.DECODE_IMAGE 関数と ML.RESIZE_IMAGE 関数から返された、デコードされた画像データを受け入れる PyTorch の事前トレーニング済み resnet18 をインポートします。

import torch
import torch.nn as nn

# Define model input format to match the output format of
# ML.DECODE_IMAGE function: [height, width, channels]
dummy_input = torch.randn(1, 224, 224, 3, device="cpu")

# Load a pretrained pytorch model for image classification
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True)

# Reshape input format from [batch_size, height, width, channels]
# to [batch_size, channels, height, width]
class ReshapeLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        x = x.permute(0, 3, 1, 2)  # reorder dimensions
        return x

class ArgMaxLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
       return torch.argmax(x, dim=1)

final_model = nn.Sequential(
    ReshapeLayer(),
    model,
    nn.Softmax(),
    ArgMaxLayer()
)

モデルを ONNX 形式に変換して保存する

torch.onnx を使用して、PyTorch ビジョンモデルを resnet18.onnx という名前の ONNX ファイルにエクスポートします。

torch.onnx.export(final_model,            # model being run
                  dummy_input,            # model input
                  "resnet18.onnx",        # where to save the model
                  opset_version=10,       # the ONNX version to export the model to
                  input_names = ['input'],         # the model's input names
                  output_names = ['class_label'])  # the model's output names

ONNX モデルを Cloud Storage にアップロードする

ONNX モデルファイルを保存する Cloud Storage バケットを作成し、保存した ONNX モデルファイルを Cloud Storage バケットにアップロードします。詳細については、ファイル システムからオブジェクトをアップロードするをご覧ください。

ONNX モデルを BigQuery にインポートする

この手順では、ONNX モデルが Cloud Storage バケットにアップロードされていることを前提としています。サンプルのモデルは gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx に保存されています。

コンソール

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

    [BigQuery] ページに移動

  2. クエリエディタで、次のような CREATE MODEL ステートメントを入力します。

     CREATE OR REPLACE MODEL `mydataset.mymodel`
      OPTIONS (MODEL_TYPE='ONNX',
       MODEL_PATH='gs://bucket/path/to/onnx_model/*')
    

    例:

     CREATE OR REPLACE MODEL `example_dataset.imported_onnx_model`
      OPTIONS (MODEL_TYPE='ONNX',
       MODEL_PATH='gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx')
    

    上記のクエリでは、gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx にある ONNX モデルを imported_onnx_model という BigQuery モデルとしてインポートします。

  3. 新しいモデルが [リソース] パネルに表示されます。プロジェクト内の各データセットを展開すると、データセット内の他の BigQuery リソースとともに、モデルが一覧表示されます。モデルにはモデルアイコン モデルアイコン がついています。

  4. [リソース] パネルで新しいモデルを選択すると、そのモデルに関する情報がクエリエディタの下に表示されます。

    ONNX モデルの情報

bq

ONNX モデルを Cloud Storage からインポートするには、次のようなコマンドを入力して、バッチクエリを実行します。

bq query \
--use_legacy_sql=false \
"CREATE MODEL
  `mydataset.mymodel`
OPTIONS
  (MODEL_TYPE='ONNX',
   MODEL_PATH='gs://bucket/path/to/onnx_model/*')"

例:

bq query --use_legacy_sql=false \
"CREATE OR REPLACE MODEL
  `example_dataset.imported_onnx_model`
OPTIONS
  (MODEL_TYPE='ONNX',
   MODEL_PATH='gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx')"

モデルをインポートすると、bq ls [dataset_name] の出力に表示されます。

$ bq ls example_dataset

       tableId          Type    Labels   Time Partitioning
 --------------------- ------- -------- -------------------
  imported_onnx_model   MODEL

API

新しいジョブを挿入し、次に示すリクエストの本文のように jobs#configuration.query プロパティに値を入力します。

{
  "query": "CREATE MODEL `project_id:mydataset.mymodel` OPTIONS(MODEL_TYPE='ONNX' MODEL_PATH='gs://bucket/path/to/onnx_model/*')"
}

BigQuery で画像データにアクセスするオブジェクト テーブルを作成する

BigQuery で非構造化データにアクセスするには、オブジェクト テーブルを作成する必要があります。詳しい手順については、オブジェクト テーブルの作成をご覧ください。

gs://mybucket/goldfish.jpg に保存された goldfish イメージに、goldfish_image_table という名前のオブジェクト テーブルを作成します。

CREATE EXTERNAL TABLE `example_dataset.goldfish_image_table`
WITH CONNECTION `us.my-connection`
OPTIONS(
  object_metadata = 'SIMPLE',
  uris = ['gs://mybucket/goldfish.jpg'],
  max_staleness = INTERVAL 1 DAY,
  metadata_cache_mode = 'AUTOMATIC');

インポートした ONNX モデルを使用して予測を行う

コンソール

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

    [BigQuery] ページに移動

  2. クエリエディタで、次のように ML.PREDICT を使用してクエリを入力します。

     SELECT
       class_label
     FROM
       ML.PREDICT(MODEL example_dataset.imported_onnx_model,
         (
         SELECT
           ML.RESIZE_IMAGE(ML.DECODE_IMAGE(DATA),
             224,
             224,
             FALSE) AS input
         FROM
           example_dataset.goldfish_image_table) )
     

    上記のクエリでは、現在のプロジェクトのデータセット example_dataset にある imported_onnx_model というモデルを使用して、入力オブジェクト テーブル goldfish_image_table にある画像データから予測を行います。ML.PREDICT で解釈できるように画像データをデコードするには、ML.DECODE_IMAGE 関数が必要です。さらに ML.RESIZE_IMAGE 関数を呼び出して、モデルの入力サイズ(224*224)に合わせて画像のサイズを変更します。画像オブジェクト テーブルで推論を実行する方法については、画像オブジェクト テーブルで推論を実行するをご覧ください。

    このクエリは、ImageNet ラベル辞書に基づいて入力画像の予測クラスラベルを出力します。

    クエリ結果

bq

テーブル input_data の入力データから予測を行うには、インポートした ONNX モデル my_model を使用して、次のようなコマンドを入力します。

bq query \
--use_legacy_sql=false \
'SELECT *
 FROM ML.PREDICT(
   MODEL `my_project.my_dataset.my_model`,
   (SELECT * FROM input_data))'

API

新しいジョブを挿入し、次に示すリクエストの本文のように jobs#configuration.query プロパティに値を入力します。

{
  "query": "SELECT * FROM ML.PREDICT(MODEL `my_project.my_dataset.my_model`, (SELECT * FROM input_data))"
}

次のステップ