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

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

  • 使い慣れたフレームワークを使用してモデルをトレーニングする。
  • モデルを ONNX 形式に変換する。
  • ONNX モデルを BigQuery にインポートし、BigQuery ML を使用して予測を行う。

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

省略可: モデルをトレーニングして ONNX 形式に変換する

次のコードサンプルは、事前トレーニング済みの分類モデルを PyTorch にインポートする方法と、生成されたモデルを ONNX 形式に変換する方法を示しています。このチュートリアルでは、gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx に保存されている事前構築済みのサンプルモデルを使用します。サンプルモデルを使用する場合は、これらの手順を完了する必要はありません。

画像分類用の 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 ビジョンモデルをエクスポートします。エクスポートされた ONNX ファイルの名前は resnet18.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 にアップロードする

モデルを保存したら、次の操作を行います。

データセットを作成する

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

コンソール

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

    [BigQuery] ページに移動

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

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

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

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

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

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

bq

新しいデータセットを作成するには、--location フラグを指定した bq mk コマンドを使用します。使用可能なパラメータの一覧については、bq mk --dataset コマンドのリファレンスをご覧ください。

  1. データの場所が US に設定され、BigQuery ML tutorial dataset という説明の付いた、bqml_tutorial という名前のデータセットを作成します。

    bq --location=US mk -d \
     --description "BigQuery ML tutorial dataset." \
     bqml_tutorial

    このコマンドでは、--dataset フラグの代わりに -d ショートカットを使用しています。-d--dataset を省略した場合、このコマンドはデフォルトでデータセットを作成します。

  2. データセットが作成されたことを確認します。

    bq ls

API

定義済みのデータセット リソースを使用して datasets.insert メソッドを呼び出します。

{
  "datasetReference": {
     "datasetId": "bqml_tutorial"
  }
}

BigQuery DataFrames

このサンプルを試す前に、BigQuery DataFrames を使用した BigQuery クイックスタートの手順に沿って BigQuery DataFrames を設定してください。詳細については、BigQuery DataFrames のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の ADC の設定をご覧ください。

import google.cloud.bigquery

bqclient = google.cloud.bigquery.Client()
bqclient.create_dataset("bqml_tutorial", exists_ok=True)

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

次の手順では、CREATE MODEL ステートメントを使用して、サンプル ONNX モデルを Cloud Storage からデータセットにインポートする方法について説明します。

コンソール

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

    [BigQuery Studio] に移動

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

    CREATE OR REPLACE MODEL `bqml_tutorial.imported_onnx_model`
     OPTIONS (MODEL_TYPE='ONNX',
      MODEL_PATH='BUCKET_PATH')

    BUCKET_PATH は、Cloud Storage にアップロードしたモデルのパスに置き換えます。サンプルモデルを使用する場合は、BUCKET_PATH を値 gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx に置き換えます。

    処理が完了すると、「Successfully created model named imported_onnx_model」のようなメッセージが表示されます。

    新しいモデルが [リソース] パネルに表示されます。モデルにはモデルアイコン [リソース] パネルのモデルアイコン。 がついています。[リソース] パネルで新しいモデルを選択すると、そのモデルに関する情報がクエリエディタの横に表示されます。

    imported_onnx_model の情報パネル。

bq

  1. 次の CREATE MODEL ステートメントを入力して Cloud Storage から ONNX モデルをインポートします。

    bq query --use_legacy_sql=false \
    "CREATE OR REPLACE MODEL
      `bqml_tutorial.imported_onnx_model`
    OPTIONS
      (MODEL_TYPE='ONNX',
       MODEL_PATH='BUCKET_PATH')"

    BUCKET_PATH は、Cloud Storage にアップロードしたモデルのパスに置き換えます。サンプルモデルを使用している場合は、BUCKET_PATHgs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx に置き換えます。

  2. モデルをインポートしたら、モデルがデータセットに表示されていることを確認します。

    bq ls -m bqml_tutorial

    出力は次のようになります。

    tableId               Type
    --------------------- -------
    imported_onnx_model  MODEL

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

画像データを分析するオブジェクト テーブルを BigQuery で作成する

オブジェクト テーブルは、Cloud Storage 内にある非構造化データ オブジェクトの読み取り専用テーブルです。オブジェクト テーブルを使用すると、BigQuery の非構造化データを分析できます。

このチュートリアルでは、ML.PREDICT 関数を使用して、Cloud Storage バケットに保存されている入力画像の予測クラスラベルを出力します。

オブジェクト テーブルを作成するには、次のことを行う必要があります。

  • Cloud Storage バケットを作成し、金魚の画像をアップロードする。
  • オブジェクト テーブルへのアクセスに使用する Cloud リソース接続を作成する。
  • リソース接続のサービス アカウントへのアクセス権を付与する。

バケットを作成して画像をアップロードする

次の手順で Cloud Storage バケットを作成し、金魚の画像をアップロードします。

コンソール

  1. Google Cloud コンソールで Cloud Storage の [バケット] ページに移動します。

    [バケット] に移動

  2. [ 作成] をクリックします。

  3. [バケットの作成] ページでユーザーのバケット情報を入力します。

    1. [始める] セクションで、次の操作を行います。

      1. ボックスに bqml_images を入力します。

      2. [続行] をクリックします。

    2. [データの保存場所の選択] セクションで、次の操作を行います。

      1. [ロケーション タイプ] で [マルチリージョン] を選択します。

      2. ロケーション タイプのメニューから、[US(米国の複数のリージョン)] を選択します。

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

    3. [データのストレージ クラスを選択する] セクションで、次の操作を行います。

      1. [デフォルトのクラスを設定する] を選択します。

      2. [標準] を選択します。

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

    4. 残りのセクションはデフォルト値のままにします。

  4. [作成] をクリックします。

コマンドライン

次の gcloud storage buckets create コマンドを入力します。

gcloud storage buckets create gs://bqml_images --location=us

リクエストが成功すると、コマンドから次のメッセージが返されます。

Creating gs://bqml_images/...

画像を Cloud Storage バケットにアップロードします。

バケットが作成されたら、金魚の画像をダウンロードして Cloud Storage バケットにアップロードします。

画像をアップロードする手順は次のとおりです。

コンソール

  1. Google Cloud コンソールで Cloud Storage の [バケット] ページに移動します。

    [バケット] に移動

  2. バケットのリストで bqml_images をクリックします。

  3. バケットのオブジェクト タブで、次のいずれかを行います。

    • デスクトップまたはファイル マネージャーから Google Cloud コンソールのメインペインにファイルをドラッグします。

    • [アップロード] > [ファイルをアップロード] をクリックし、表示されたダイアログでアップロードする画像ファイルを選択してから、[開く] をクリックします。

コマンドライン

次の gcloud storage cp コマンドを入力します。

gcloud storage cp OBJECT_LOCATION gs://bqml_images/IMAGE_NAME

次のように置き換えます。

  • OBJECT_LOCATION: 画像ファイルのローカルパス。例: Desktop/goldfish.jpg
  • IMAGE_NAME: 画像の名前。例: goldfish.jpg

成功すると、レスポンスは次のようになります。

Completed files 1/1 | 164.3kiB/164.3kiB

BigQuery クラウド リソース接続を作成する

このチュートリアルの後半で作成するオブジェクト テーブルに接続するには、Cloud リソース接続が必要です。

Cloud リソース接続を使用すると、BigQuery の外部に保存されているデータをクエリできます。たとえば、Cloud Storage や Spanner などの Google Cloud サービス、または AWS や Azure などのサードパーティ ソースにあるデータです。これらの外部接続では、BigQuery Connection API を使用します。

Cloud リソース接続を作成する手順は次のとおりです。

コンソール

  1. [BigQuery Studio] ページに移動します。

    [BigQuery Studio] に移動

  2. 左側のペインで、 [エクスプローラ] をクリックします。

    エクスプローラ ペインのボタンがハイライト表示されている。

    左側のペインが表示されていない場合は、 左側のペインを開くをクリックしてペインを開きます。

  3. [エクスプローラ] ペインで、 [データを追加] をクリックします。

    [データを追加] ダイアログが開きます。

  4. [フィルタ条件] ペインの [データソースのタイプ] セクションで、[データベース] を選択します。

    または、[データソースを検索] フィールドに「Vertex AI」と入力します。

  5. [特徴量データソース] セクションで、[Vertex AI] をクリックします。

  6. [Vertex AI モデル: BigQuery フェデレーション] ソリューション カードをクリックします。

  7. [接続タイプ] リストで、[Vertex AI リモートモデル、リモート関数、BigLake(Cloud リソース)] を選択します。

  8. [接続 ID] フィールドに「bqml_tutorial」と入力します。

  9. [マルチリージョン - US] が選択されていることを確認します。

  10. [接続を作成] をクリックします。

  11. ウィンドウの下部にある [接続に移動] をクリックします。または、[エクスプローラ] ペインで [接続] をクリックし、[us.bqml_tutorial] をクリックします。

  12. [接続情報] ペインで、サービス アカウント ID をコピーします。この ID は、接続の権限を構成するときに必要になります。接続リソースを作成すると、BigQuery は、一意のシステム サービス アカウントを作成し、それを接続に関連付けます。

bq

  1. 接続を作成するには:

    bq mk --connection --location=US --project_id=PROJECT_ID \
        --connection_type=CLOUD_RESOURCE bqml_tutorial

    PROJECT_ID は、実際のGoogle Cloud プロジェクト ID に置き換えます。--project_id パラメータは、デフォルト プロジェクトをオーバーライドします。

    接続リソースを作成すると、BigQuery は、一意のシステム サービス アカウントを作成し、それを接続に関連付けます。

    トラブルシューティング: 次の接続エラーが発生した場合は、Google Cloud SDK を更新します。

    Flags parsing error: flag --connection_type=CLOUD_RESOURCE: value should be one of...
    
  2. 後の手順で使用するため、サービス アカウント ID を取得してコピーします。

    bq show --connection PROJECT_ID.us.bqml_tutorial

    出力は次のようになります。

    name                          properties
    1234.REGION.CONNECTION_ID {"serviceAccountId": "connection-1234-9u56h9@gcp-sa-bigquery-condel.iam.gserviceaccount.com"}
    

接続アクセスを設定する

Cloud リソース接続のサービス アカウントに Storage オブジェクト管理者ロールを付与します。このロールは、イメージ ファイルをアップロードしたプロジェクトで付与する必要があります。

ロールを付与する手順は次のとおりです。

  1. [IAM と管理] ページに移動します。

    [IAM と管理] に移動

  2. [アクセス権を付与] をクリックします。

  3. [新しいプリンシパル] フィールドに、前にコピーした Cloud リソース接続のサービス アカウント ID を入力します。

  4. [ロールを選択] フィールドで、[Cloud Storage] を選択し、続いて [Storage オブジェクト管理者] を選択します。

  5. [保存] をクリックします。

オブジェクト テーブルを作成する

Cloud Storage にアップロードした金魚の画像を使用して、goldfish_image_table という名前のオブジェクト テーブルを作成する手順は次のとおりです。

コンソール

  1. [BigQuery Studio] ページに移動します。

    BigQuery Studio に移動

  2. クエリエディタで、次のクエリを入力してオブジェクト テーブルを作成します。

    CREATE EXTERNAL TABLE `bqml_tutorial.goldfish_image_table`
    WITH CONNECTION `us.bqml_tutorial`
    OPTIONS(
    object_metadata = 'SIMPLE',
    uris = ['gs://bqml_images/IMAGE_NAME'],
    max_staleness = INTERVAL 1 DAY,
    metadata_cache_mode = 'AUTOMATIC');

    IMAGE_NAME は、画像ファイルの名前に置き換えます(例: goldfish.jpg)。

    オペレーションが完了すると、This statement created a new table named goldfish_image_table のようなメッセージが表示されます。

bq

  1. 次の CREATE EXTERNAL TABLE ステートメントを入力して、オブジェクト テーブルを作成します。

    bq query --use_legacy_sql=false \
    "CREATE EXTERNAL TABLE `bqml_tutorial.goldfish_image_table`
    WITH CONNECTION `us.bqml_tutorial`
    OPTIONS(
    object_metadata = 'SIMPLE',
    uris = ['gs://bqml_images/IMAGE_NAME'],
    max_staleness = INTERVAL 1 DAY,
    metadata_cache_mode = 'AUTOMATIC')"

    IMAGE_NAME は、画像ファイルの名前に置き換えます(例: goldfish.jpg)。

  2. オブジェクト テーブルを作成したら、データセットに表示されることを確認します。

    bq ls bqml_tutorial

    出力は次のようになります。

    tableId               Type
    --------------------- --------
    goldfish_image_table  EXTERNAL

詳細については、オブジェクト テーブルを作成するをご覧ください。

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

ML.PREDICT 関数を含む次のクエリを使用して、入力オブジェクト テーブル goldfish_image_table の画像データから予測を行います。このクエリは、ImageNet ラベル辞書に基づいて入力画像の予測クラスラベルを出力します。

クエリでは、ML.PREDICT で解釈できるように画像データをデコードするために ML.DECODE_IMAGE 関数が必要です。ML.RESIZE_IMAGE 関数を呼び出して、モデルの入力サイズ(224*224)に合わせて画像のサイズを変更します。

画像オブジェクト テーブルで推論を実行する方法については、画像オブジェクト テーブルで推論を実行するをご覧ください。

画像データから予測を行う手順は次のとおりです。

コンソール

  1. [BigQuery Studio] ページに移動します。

    BigQuery Studio に移動

  2. クエリエディタで、次の ML.PREDICT クエリを入力します。

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

    クエリ結果は次のようになります。

    ML.PREDICT クエリの結果

bq

次の bq query コマンドを入力します。

bq query --use_legacy_sql=false \
'SELECT
  class_label
FROM
  ML.PREDICT(MODEL `bqml_tutorial.imported_onnx_model`,
    (
    SELECT
      ML.RESIZE_IMAGE(ML.DECODE_IMAGE(DATA),
        224,
        224,
        FALSE) AS input
    FROM
      bqml_tutorial.goldfish_image_table))'