マルチモーダル エンベディングの生成と検索

このチュートリアルでは、BigQuery と Vertex AI を使用して画像とテキストのマルチモーダル エンベディングを生成し、これらのエンベディングを使用してテキストから画像へのセマンティック検索を実行する方法について説明します。

このチュートリアルでは、次のタスクについて説明します。

このチュートリアルでは、Cloud Storage の公開バケット gcs-public-data--met にあるメトロポリタン美術館のパブリック ドメインのアート画像を使用します。

必要なロール

このチュートリアルを実行するには、次の Identity and Access Management(IAM)ロールが必要です。

  • BigQuery データセット、接続、モデル、ノートブックを作成して使用する: BigQuery Studio 管理者(roles/bigquery.studioAdmin)。
  • 接続のサービス アカウントに権限を付与する: Project IAM 管理者(roles/resourcemanager.projectIamAdmin)。

これらの事前定義ロールには、このドキュメントのタスクを実行するために必要な権限が含まれています。必要とされる正確な権限については、「必要な権限」セクションを開いてご確認ください。

必要な権限

  • データセットを作成する: bigquery.datasets.create
  • 接続を作成、委任、使用する: bigquery.connections.*
  • デフォルトの接続を設定する: bigquery.config.*
  • サービス アカウントの権限を設定する: resourcemanager.projects.getIamPolicyresourcemanager.projects.setIamPolicy
  • オブジェクト テーブルを作成する: bigquery.tables.createbigquery.tables.update
  • モデルを作成して推論を実行する
    • bigquery.jobs.create
    • bigquery.models.create
    • bigquery.models.getData
    • bigquery.models.updateData
    • bigquery.models.updateMetadata
  • ノートブックを作成して使用する:
    • resourcemanager.projects.get
    • resourcemanager.projects.list
    • bigquery.config.get
    • bigquery.jobs.create
    • bigquery.readsessions.create
    • bigquery.readsessions.getData
    • bigquery.readsessions.update
    • dataform.locations.get
    • dataform.locations.list
    • dataform.repositories.create

    • dataform.repositories.list
    • dataform.collections.create
    • dataform.collections.list
    • aiplatform.notebookRuntimeTemplates.apply
    • aiplatform.notebookRuntimeTemplates.get
    • aiplatform.notebookRuntimeTemplates.list
    • aiplatform.notebookRuntimeTemplates.getIamPolicy
    • aiplatform.notebookRuntimes.assign
    • aiplatform.notebookRuntimes.get
    • aiplatform.notebookRuntimes.list
    • aiplatform.operations.list
    • aiplatform.notebookRuntimeTemplates.apply

カスタムロールや他の事前定義ロールを使用して、これらの権限を取得することもできます。

費用

このドキュメントでは、課金対象である次の Google Cloudコンポーネントを使用します。

  • BigQuery ML: You incur costs for the data that you process in BigQuery.
  • Vertex AI: You incur costs for calls to the Vertex AI service that's represented by the remote model.

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。

新規の Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

BigQuery の料金の詳細については、BigQuery ドキュメントの BigQuery の料金をご覧ください。

Vertex AI の料金の詳細については、Vertex AI の料金のページをご覧ください。

始める前に

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. Enable the BigQuery, BigQuery Connection, and Vertex AI APIs.

    Enable the APIs

データセットを作成する

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)

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

公開 Cloud Storage gcs-public-data--met バケットの画像に対してオブジェクト テーブルを作成します。オブジェクト テーブルを使用すると、Cloud Storage から画像を移動せずに分析できます。

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

    [BigQuery] に移動

  2. [クエリエディタ] ペインで、次のクエリを実行します。

    CREATE OR REPLACE EXTERNAL TABLE `bqml_tutorial.met_images`
    WITH CONNECTION DEFAULT
    OPTIONS
      ( object_metadata = 'SIMPLE',
        uris = ['gs://gcs-public-data--met/*']
      );

画像データを調べる

BigQuery で Colab Enterprise ノートブックを作成して、画像データを調べます。

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

    [BigQuery] に移動

  2. BigQuery エディタを使用してノートブックを作成します

  3. ノートブックをデフォルトのランタイムに接続します

  4. ノートブックを設定します。

    1. ノートブックにコードセルを追加します。
    2. 次のコードをコピーして、コードセルに貼り付けます。

      #@title Set up credentials
      
      from google.colab import auth
      auth.authenticate_user()
      print('Authenticated')
      
      PROJECT_ID='PROJECT_ID'
      from google.cloud import bigquery
      client = bigquery.Client(PROJECT_ID)
      

      PROJECT_ID は、このチュートリアルで使用するプロジェクトの名前に置き換えます。

    3. コードセルを実行します。

  5. テーブル表示を有効にします。

    1. ノートブックにコードセルを追加します。
    2. 次のコードをコピーして、コードセルに貼り付けます。

      #@title Enable data table display
      %load_ext google.colab.data_table
      
    3. コードセルを実行します。

  6. 画像を表示する関数を作成します。

    1. ノートブックにコードセルを追加します。
    2. 次のコードをコピーして、コードセルに貼り付けます。

      #@title Util function to display images
      import io
      from PIL import Image
      import matplotlib.pyplot as plt
      import tensorflow as tf
      
      def printImages(results):
       image_results_list = list(results)
       amt_of_images = len(image_results_list)
      
       fig, axes = plt.subplots(nrows=amt_of_images, ncols=2, figsize=(20, 20))
       fig.tight_layout()
       fig.subplots_adjust(hspace=0.5)
       for i in range(amt_of_images):
         gcs_uri = image_results_list[i][0]
         text = image_results_list[i][1]
         f = tf.io.gfile.GFile(gcs_uri, 'rb')
         stream = io.BytesIO(f.read())
         img = Image.open(stream)
         axes[i, 0].axis('off')
         axes[i, 0].imshow(img)
         axes[i, 1].axis('off')
         axes[i, 1].text(0, 0, text, fontsize=10)
       plt.show()
      
    3. コードセルを実行します。

  7. 画像を表示します。

    1. ノートブックにコードセルを追加します。
    2. 次のコードをコピーして、コードセルに貼り付けます。

      #@title Display Met images
      
      inspect_obj_table_query = """
      SELECT uri, content_type
      FROM bqml_tutorial.met_images
      WHERE content_type = 'image/jpeg'
      Order by uri
      LIMIT 10;
      """
      printImages(client.query(inspect_obj_table_query))
      
    3. コードセルを実行します。

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

      メトロポリタン美術館の展示物を撮影した画像。

  8. ノートブックを met-image-analysis として保存します。

リモートモデルを作成する

ホストされる Vertex AI マルチモーダル エンベディング モデルを表すリモートモデルを作成します。

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

    [BigQuery] に移動

  2. [クエリエディタ] ペインで、次のクエリを実行します。

    CREATE OR REPLACE MODEL `bqml_tutorial.multimodal_embedding_model`
      REMOTE WITH CONNECTION DEFAULT
      OPTIONS (ENDPOINT = 'multimodalembedding@001');

    クエリが完了するまでに数秒かかります。完了後、multimodal_embedding_model モデルが [エクスプローラ] ペインの bqml_tutorial データセットに表示されます。クエリは CREATE MODEL ステートメントを使用してモデルを作成するため、クエリの結果はありません。

画像のエンベディングを生成する

ML.GENERATE_EMBEDDING 関数を使用してオブジェクト テーブル内の画像からエンベディングを生成し、次のステップで使用するためにテーブルに書き込みます。エンベディングの生成は負荷の高い処理であるため、クエリで 601,294 枚の画像を含むデータセット全体を対象にするのではなく、LIMIT 句を含むサブクエリを使用して、10,000 枚の画像に限定してエンベディングを生成します。また、ML.GENERATE_EMBEDDING 関数の上限である 25,000 未満の画像数を維持するためにも役立ちます。このクエリの実行には約 40 分かかります。

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

    [BigQuery] に移動

  2. [クエリエディタ] ペインで、次のクエリを実行します。

    CREATE OR REPLACE TABLE `bqml_tutorial.met_image_embeddings`
    AS
    SELECT *
    FROM
      ML.GENERATE_EMBEDDING(
        MODEL `bqml_tutorial.multimodal_embedding_model`,
        (SELECT * FROM `bqml_tutorial.met_images` WHERE content_type = 'image/jpeg' LIMIT 10000))

エンベディング生成エラーを修正する

エンベディング生成エラーがないか確認して修正します。Vertex AI での生成 AI の割り当てまたはサービスの利用不可が原因で、エンベディングの生成が失敗することがあります。

ML.GENERATE_EMBEDDING 関数は、ml_generate_embedding_status 列にエラーの詳細を返します。エンベディングの生成が成功した場合、この列は空になります。エンベディングの生成が失敗した場合は、エラー メッセージが表示されます。

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

    [BigQuery] に移動

  2. クエリエディタで次のクエリを実行して、エンベディング生成の失敗があったかどうかを確認します。

    SELECT DISTINCT(ml_generate_embedding_status),
      COUNT(uri) AS num_rows
    FROM bqml_tutorial.met_image_embeddings
    GROUP BY 1;
  3. エラーのある行が返された場合は、エンベディング生成に失敗した行をすべて削除します。

    DELETE FROM `bqml_tutorial.met_image_embeddings`
    WHERE ml_generate_embedding_status = 'A retryable error occurred: RESOURCE_EXHAUSTED error from remote service/endpoint.';

ベクトル インデックスを作成する

必要に応じて、CREATE VECTOR INDEX ステートメントを使用して、met_images_embeddings テーブルの ml_generate_embedding_result 列に met_images_index ベクトル インデックスを作成できます。ベクトル インデックスを使用すると、ベクトル検索をより迅速に実行できますが、再現率が低下するため、より近似的な結果が返されます。

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

    [BigQuery] に移動

  2. [クエリエディタ] ペインで、次のクエリを実行します。

    CREATE OR REPLACE
      VECTOR INDEX `met_images_index`
    ON
      bqml_tutorial.met_image_embeddings(ml_generate_embedding_result)
      OPTIONS (
        index_type = 'IVF',
        distance_type = 'COSINE');
  3. ベクトル インデックスは非同期で作成されます。ベクトル インデックスが作成されているかどうかを確認するには、INFORMATION_SCHEMA.VECTOR_INDEXES ビューをクエリして、coverage_percentage 値が 0 よりも大きく、last_refresh_time 値が NULL でないことを確認します。

    SELECT table_name, index_name, index_status,
      coverage_percentage, last_refresh_time, disable_reason
    FROM bqml_tutorial.INFORMATION_SCHEMA.VECTOR_INDEXES
    WHERE index_name = 'met_images_index';

検索テキストのエンベディングを生成する

指定したテキスト検索文字列に対応する画像を検索するには、まずその文字列のテキスト エンベディングを作成する必要があります。同じリモートモデルを使用して、画像エンベディングの作成に使用したテキスト エンベディングを作成します。次に、テキスト エンベディングをテーブルに書き込んで、次の手順で使用できるようにします。検索文字列は pictures of white or cream colored dress from victorian era です。

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

    [BigQuery] に移動

  2. [クエリエディタ] ペインで、次のクエリを実行します。

    CREATE OR REPLACE TABLE `bqml_tutorial.search_embedding`
    AS
    SELECT * FROM ML.GENERATE_EMBEDDING(
      MODEL `bqml_tutorial.multimodal_embedding_model`,
      (
        SELECT 'pictures of white or cream colored dress from victorian era' AS content
      )
    );

VECTOR_SEARCH 関数を使用して、テキスト エンベディングで表される検索文字列に最も一致する画像のセマンティック検索を行います。

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

    [BigQuery] に移動

  2. クエリエディタで次のクエリを実行して、セマンティック検索を実行し、結果をテーブルに書き込みます。

    CREATE OR REPLACE TABLE `bqml_tutorial.vector_search_results` AS
    SELECT base.uri AS gcs_uri, distance
    FROM
      VECTOR_SEARCH(
        TABLE `bqml_tutorial.met_image_embeddings`,
        'ml_generate_embedding_result',
        TABLE `bqml_tutorial.search_embedding`,
        'ml_generate_embedding_result',
        top_k => 3);

セマンティック検索の結果を可視化する

ノートブックを使用してセマンティック検索結果を可視化します。

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

    [BigQuery] に移動

  2. 先ほど作成した met-image-analysis ノートブックを開きます。

  3. ベクトル検索結果を可視化します。

    1. ノートブックにコードセルを追加します。
    2. 次のコードをコピーして、コードセルに貼り付けます。

      query = """
        SELECT * FROM `bqml_tutorial.vector_search_results`
        ORDER BY distance;
      """
      
      printImages(client.query(query))
      
    3. コードセルを実行します。

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

      マルチモーダル ベクトル検索クエリから返された画像。

クリーンアップ

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.