Vertex AI を使用して Spark ML モデルを提供する

Last reviewed 2023-07-11 UTC

データ サイエンティストや機械学習(ML)エンジニアは、多くの場合、ML モデルからオンライン(またはリアルタイム)予測を生成するニーズに対して十分な速度を実現するサービス アーキテクチャを必要としています。Vertex AI は、このようなニーズに対応します。

Vertex AI を使用すると、さまざまな ML フレームワークのモデルを提供できます。TensorFlow、PyTorch、XGBoost、scikit-learn などのフレームワークの場合、Vertex AI にはこれらの ML モデルを実行するためのビルド済みコンテナが用意されています。これらの ML フレームワークをまだ使用していない場合は、Vertex AI で使用する独自のカスタム コンテナを作成する必要があります。

このドキュメントは、Spark ML モデルを提供するためにカスタム コンテナを作成する必要があるユーザーを対象としています。このドキュメントには、カスタム コンテナに必要なサービス提供アーキテクチャの説明と、Spark MLib モデル用のこのアーキテクチャを示すリファレンス実装の両方が掲載されています。

このドキュメントのリファレンス実装の部分を最大限に活用するには、Spark MLlib モデルを MLeap 形式にエクスポートして、予測の提供を目的とした Vertex AI の使用方法を理解し、コンテナ イメージの使用を経験しておく必要があります。

アーキテクチャ

一部の ML フレームワークではビルド済みコンテナを使用できますが、Spark などの他の ML フレームワークのユーザーは、Vertex AI が予測を実行できるカスタム コンテナを構築する必要があります。次の図は、Spark MLib モデルと、カスタム コンテナを必要とする他のモデルを提供するために必要なサービス提供アーキテクチャを示しています。

ドキュメントで使用されているモデルのサービス提供アーキテクチャ。

このアーキテクチャには次のコンポーネントが含まれています。

  • Cloud Storage: モデルの実行に必要なモデル アーティファクト用のストレージを提供します。付随するリファレンス実装で使用されている Spark ML モデルの場合、モデル アーティファクトは MLeap Bundle とモデルスキーマで構成されます。
  • Cloud Build: ビルダー イメージを使用して、サービス提供コンテナ イメージと呼ばれるカスタム コンテナ イメージをビルドします。ビルドプロセスは、モデルのサービス提供コードをコンパイルしてパッケージ化し、サービス提供コンテナ イメージをビルドしてから、サービス提供コンテナ イメージを Artifact Registry に push します。
  • Artifact Registry: 次のオブジェクトが含まれます。
    • Cloud Build がサービス提供コンテナ イメージのビルドに使用する scala-sbt ビルダー コンテナ イメージ。
    • Cloud Build によってビルドされたサービス提供コンテナ イメージ。
  • Vertex AI: Cloud Storage からアップロードされた ML モデルが含まれています。アップロードされたモデルは、Cloud Storage 内のモデル アーティファクトの場所と、Artifact Registry 内のサービス提供コンテナ イメージの場所で構成されます。Vertex AI には、モデルがデプロイされているエンドポイントも含まれています。モデルがエンドポイントにデプロイされると、Vertex AI では物理リソースがモデルに関連付けられ、モデルがオンライン予測を提供できるようになります。

このサービス アーキテクチャの実装の一環として、他のアプリで使用できるように ML モデルをエクスポートし、独自のサービス提供コンテナ イメージを定義する必要があります。このドキュメントで示されているリファレンス実装では、サービス提供コンテナ イメージの定義とビルドに使用されるコードが用意されています。このコードには、以前にエクスポートされた Spark ML モデルのモデル アーティファクトも含まれています。一部の構成を変更すれば、このリファレンス実装を使用して独自の Spark ML モデルを提供できます。

ただし、リファレンス実装を使用せずに、このサービス提供アーキテクチャを独自に実装することもできます。独自のアーキテクチャを実装する場合は、次のことを行う必要があります。

  • モデルをエクスポートして、他のアプリケーションで使用できるようにします。このプロセスは、使用している ML フレームワークとツールによって異なります。たとえば、リファレンス実装で説明しているように、MLeap バンドルを作成して Spark MLlib モデルをエクスポートすることもできます。モデルをエクスポートする方法の他の例については、予測に使用するモデル アーティファクトをエクスポートするをご覧ください。
  • Vertex AI との互換性を保つためのカスタム コンテナの要件を満たすように、サービス提供コンテナ イメージを設計します。コードには、任意のプログラミング言語を使用できます。
  • 使用したプログラミング言語と互換性のあるパッケージ ファイル形式でコードをパッケージ化します。たとえば、Java コードには JAR ファイルを使用し、Python コードには Python wheel を使用できます。
  • カスタムモードのコードを提供できるカスタム コンテナ イメージを作成します。

リファレンス実装

次のリファレンス実装では、花のがくと花びらの長さと幅に基づいてあやめの種類を予測する Spark MLib モデルを提供しています。

この実装で使用されているモデルは、vertex-ai-spark-ml-serving.git リポジトリexample_model ディレクトリにあります。このディレクトリには、サービス提供コンテナで予測を実行するために使用されるモデル アーティファクトが含まれています。また、次のファイルが含まれています。

  • example_model/model.zip ファイルは、Spark MLlib を使用して構築されたロジスティック回帰モデルで、Iris データセットを使用してトレーニングされ、MLeap Bundle に変換されています。このモデルは、花のがくと花びらの長さと幅を使用して、アヤメの種を予測します。
  • example_model/schema.json ファイルは、モデルスキーマを記述する JSON ファイルです。モデルスキーマには、MLeap スキーマで必要となる、予測インスタンスの入力フィールドと予測結果の出力フィールドの想定が記述されます。

独自の Mlib モデルを使用する

このリファレンス実装で独自のモデルを使用するには、まず Spark MLlib モデルが MLeap Bundle にエクスポートされていることを確認してください。また、Spark MLib モデルを提供するには、適切なモデル アーティファクト(MLeap Bundle とモデルスキーマ)を指定する必要があります。

MLeap Bundle

使用中データのコンテナは、起動時に Vertex AI からコンテナに渡される AIP_STORAGE_URI 環境変数を使用して、MLeap Bundle の場所を決定します。AIP_STORAGE_URI 変数の値は、モデルを Vertex AI にアップロードする際に指定されます。

モデルのスキーマ

モデルスキーマには、モデルの入力特徴と予測出力が記述されます。モデルスキーマは JSON データを使用して表されます。このリファレンス実装では、花のがくと花びらの長さと幅に基づいて、アイリスの種類を予測するために、次のスキーマを使用しています。

{
  "input": [
    {
      "name": "sepal_length",
      "type": "FLOAT"
    },
    {
      "name": "sepal_width",
      "type": "FLOAT"
    },
    {
      "name": "petal_length",
      "type": "FLOAT"
    },
    {
      "name": "petal_width",
      "type": "FLOAT"
    }
  ],
  "output": [
    {
      "name": "probability",
      "type": "DOUBLE",
      "struct": "VECTOR"
    }
  ]
}

サンプル スキーマでは、input 配列にモデルへの入力フィールド(列)が含まれ、output 配列にモデルから返される出力フィールド(列)が含まれています。どちらの配列でも、配列の各オブジェクトには次のプロパティが含まれます。

  • name: フィールド(列)名。
  • type: フィールド(列)型。有効な型には BOOLEANBYTEDOUBLEFLOATINTEGERLONGSHORTSTRING があります。
  • (省略可)struct: スカラーや配列などのフィールド構造。有効な構造には、BASIC(スカラー型)、ARRAY(Spark Array)、VECTOR(Spark DenseVector)があります。BASIC は、struct フィールドが存在しない場合に使用されます。

モデルスキーマをサービス提供コンテナに渡すには、次のいずれかの方法を使用します。

  • スキーマを定義する JSON データを MLEAP_SCHEMA 環境変数に指定します。MLEAP_SCHEMA 環境変数には、JSON スキーマを含むファイルのパスではなく、JSON データ自体が含まれている必要があります。
  • JSON データを schema.json というファイルに保存し、このファイルを ${AIP_STORAGE_URI}/schema.json のコンテナで使用できるようにします。これは、このドキュメントに記載されているサンプル MLib モデルで使用されている方法です。

両方の方法でモデルスキーマをサービス提供コンテナに渡す場合は、MLEAP_SCHEMA 環境変数に保存されている JSON データが優先されます。

費用

このリファレンス実装では、課金対象である次の Google Cloud コンポーネントを使用します。

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

このリファレンス実装を終了した時点で、作成したリソースを削除すると、その後の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

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

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

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

  3. Vertex AI, Cloud Build, Cloud Storage, and Artifact Registry API を有効にします。

    API を有効にする

  4. Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。

    Cloud Shell をアクティブにする

  5. プロジェクト ID を検索して Cloud Shell に設定します。
    export PROJECT_ID=YOUR_PROJECT_ID
    gcloud config set project ${PROJECT_ID}
    

    YOUR_PROJECT_ID は、実際のプロジェクト ID に置き換えます。

scala-sbt ビルダー イメージを作成する

Cloud Build と scala-sbt コミュニティ ビルダーを使用して、サービス提供コンテナのイメージをビルドします。このビルドプロセスでは、プロジェクトの Container Registry に sbt-scala ビルダー イメージが配置されている必要があります。

  1. Cloud Shell で cloud-builders-community リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
    
  2. プロジェクト ディレクトリに移動します。

    cd cloud-builders-community/scala-sbt
    
  3. scala-sbt ビルダー イメージをビルドし、Container Registry に push します。

    gcloud builds submit .
    

サービス提供コンテナのイメージをビルドする

Vertex AI は、サービス提供コンテナを使用してサンプルモデルの予測リクエストを実行します。サービス提供コンテナのイメージをビルドする最初のステップは、Artifact Registry にイメージを格納する Docker リポジトリを作成することです。次に、リポジトリからサービス提供コンテナのイメージを pull するための権限を Vertex AI に付与する必要があります。リポジトリを作成して権限を付与したら、サービス提供コンテナのイメージをビルドし、イメージを Artifact Registry に push できます。

  1. Cloud Shell で、Artifact Registry に Docker リポジトリを作成します。

    REPOSITORY="vertex-ai-prediction"
    LOCATION="us-central1"
    
    gcloud artifacts repositories create $REPOSITORY \
        --repository-format=docker \
        --location=$LOCATION
    
  2. Vertex AI サービス エージェントに Artifact Registry 読み取りロールを付与します。

    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
        --format="value(projectNumber)")
    SERVICE_ACCOUNT="service-$PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$SERVICE_ACCOUNT" \
        --role="roles/artifactregistry.reader"
    
  3. spark-ml-serving リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/vertex-ai-spark-ml-serving.git
    
  4. プロジェクト ディレクトリに移動します。

    cd vertex-ai-spark-ml-serving
    
  5. プロジェクトにサービス提供コンテナのイメージをビルドします。

    IMAGE=spark-ml-serving
    
    gcloud builds submit --config=cloudbuild.yaml \
        --substitutions="_LOCATION=$LOCATION,_REPOSITORY=$REPOSITORY,_IMAGE=$IMAGE" .
    

    cloudbuild.yaml ファイルには、scala-sbt ビルダーと docker イメージ ビルダーの 2 つのビルダーが指定されています。Cloud Build は、scala-sbt ビルダーを使用して Cloud Storage からのモデルのサービス提供コードをコンパイルし、コンパイルされたコードを実行可能な JAR ファイルにパッケージ化します。Cloud Build は、docker ビルダーを使用して、JAR ファイルを含むサービス提供コンテナのイメージをビルドします。サービス提供コンテナ イメージがビルドされると、イメージは Artifact Registry に push されます。

モデルを Vertex AI にインポートする

サービス提供コンテナは Cloud Storage からモデル アーティファクトを読み取ります。モデルを Vertex AI にインポートする前に、これらのアーティファクトの保存場所を作成する必要があります。モデルをインポートする際は、モデル アーティファクトの保存場所と Artifact Registry のサービス提供コンテナ イメージの両方が必要です。

  1. Cloud Shell で、モデル アーティファクト用のバケットを作成します。

    REGION="us-central1"
    BUCKET="YOUR_BUCKET_NAME"
    gsutil mb -l $REGION gs://$BUCKET
    

    YOUR_BUCKET_NAME は、実際のバケット名を置き換えます。

  2. モデル アーティファクトをバケットにコピーします。

    gsutil cp example_model/* gs://$BUCKET/example_model/
    
  3. モデルを Vertex AI にインポートします。

    DISPLAY_NAME="iris-$(date +'%Y%m%d%H%M%S')"
    IMAGE_URI="${LOCATION}-docker.pkg.dev/$PROJECT_ID/${REPOSITORY}/${IMAGE}"
    ARTIFACT_URI="gs://$BUCKET/example_model/"
    
    gcloud ai models upload \
        --region=$REGION \
        --display-name=$DISPLAY_NAME \
        --container-image-uri=$IMAGE_URI \
        --artifact-uri=$ARTIFACT_URI \
        --container-health-route="/health" \
        --container-predict-route="/predict"
    

    gcloud ai models upload コマンドでは、--artifact-uri パラメータの値に AIP_STORAGE_URI 変数の値を指定します。この変数は、Vertex AI にインポートされる MLeap Bundle の場所を指定します。

モデルを新しいエンドポイントにデプロイする

Vertex AI が予測を実行するには、インポートしたモデルをエンドポイントにデプロイする必要があります。モデルをデプロイする際は、エンドポイントの ID とモデルの ID の両方が必要です。

  1. Cloud Shell で、モデルのエンドポイントを作成します。

    gcloud ai endpoints create \
        --region=$REGION \
        --display-name=$DISPLAY_NAME
    

    gcloud コマンドライン ツールがエンドポイントを作成するまでに数秒かかる場合があります。

  2. 新しく作成したエンドポイントのエンドポイント ID を取得します。

    ENDPOINT_ID=$(gcloud ai endpoints list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print ENDPOINT_ID to the console
    echo "Your endpoint ID is: $ENDPOINT_ID"
    
  3. Vertex AI にモデルをインポートするセクションでインポートしたモデルのモデル ID を取得します。

    MODEL_ID=$(gcloud ai models list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print MODEL_ID to the console
    echo "Your model ID is: $MODEL_ID"
    
  4. エンドポイントにモデルをデプロイします。

    gcloud ai endpoints deploy-model $ENDPOINT_ID \
        --region=$REGION \
        --model=$MODEL_ID \
        --display-name=$DISPLAY_NAME \
        --traffic-split="0=100"
    

    gcloud コマンドで、モデルをエンドポイントにデプロイします。マシンのリソースタイプ、ノードの最小数と最大数、その他の構成オプションには、デフォルト値が使用されます。モデルのデプロイ オプションの詳細については、Vertex AI のドキュメントをご覧ください。

エンドポイントをテストする

モデルをエンドポイントにデプロイすると、実装をテストできます。エンドポイントをテストするには、リファレンス実装コードに組み込まれているサンプル クライアントを使用します。サンプル クライアントは予測インスタンスを生成し、エンドポイントに予測リクエストを送信します。各予測インスタンスには、sepal_lengthsepal_widthpetal_lengthpetal_width のランダム化された値が含まれています。デフォルトでは、サンプル クライアントは複数の予測インスタンスを組み合わせて 1 つのリクエストにします。エンドポイントからのレスポンスには、リクエストで送信された各インスタンスの予測が含まれます。予測には、Iris データセットの各クラスの確率(setosaversicolorvirginica)が含まれます。

  • Cloud Shell で、サンプルの予測クライアントを実行します。

    cd example_client
    ./run_client.sh --project $PROJECT_ID \
        --location $LOCATION \
        --endpoint $ENDPOINT_ID
    

    スクリプトを初めて実行すると、Python 仮想環境が作成され、依存関係がインストールされます。依存関係がインストールされてから、スクリプトでサンプル クライアントが実行されます。リクエストごとに、クライアントは予測インスタンスと対応するクラス確率をターミナルに出力します。出力の抜粋を以下に示します。

    Sending 10 asynchronous prediction requests with 3 instances per request ...
    
    ==> Response from request #10:
    
    Instance 1:     sepal_length:   5.925825137450266
                    sepal_width:    4.5047557888651
                    petal_length:   1.0432434310300223
                    petal_width:    0.5050397721287457
    
    Prediction 1:   setosa:         0.2036041134824573
                    versicolor:     0.6062980065549213
                    virginica:      0.1900978799626214
    
    Instance 2:     sepal_length:   6.121228622484405
                    sepal_width:    3.406317728235072
                    petal_length:   3.178583759980504
                    petal_width:    2.815141143581328
    
    Prediction 2:   setosa:         0.471811302254083
                    versicolor:     0.2063720436033448
                    virginica:      0.3218166541425723
    
    Instance 3:     sepal_length:   7.005781590327274
                    sepal_width:    2.532116893508745
                    petal_length:   2.6351337947193474
                    petal_width:    2.270855223519198
    
    Prediction 3:   setosa:         0.453579051699638
                    versicolor:     0.2132869980698818
                    virginica:      0.3331339502304803
    

クリーンアップ

このリファレンス実装で使用したリソースによって Google Cloud アカウントへの課金が発生するのを避けるには、リソースを含むプロジェクトを削除するか、プロジェクトを保持して個別のリソースを削除します。

プロジェクトを削除する

  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.

リソースを個別に削除する

  1. Cloud Shell で、エンドポイントからモデルのデプロイを解除します。

    DEPLOYED_MODEL_ID=$(gcloud ai endpoints describe $ENDPOINT_ID \
        --region=$REGION \
        --format='value(deployedModels.id)')
    
    gcloud ai endpoints undeploy-model $ENDPOINT_ID \
        --region=$REGION \
        --deployed-model-id=$DEPLOYED_MODEL_ID
    
  2. エンドポイントを削除します。

    gcloud ai endpoints delete $ENDPOINT_ID \
        --region=$REGION \
        --quiet
    
  3. モデルを削除します。

    gcloud ai models delete $MODEL_ID \
        --region=$REGION
    
  4. サービス提供コンテナのイメージを削除します。

    gcloud artifacts docker images delete \
        $LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE \
        --delete-tags \
        --quiet
    
  5. scala-sbt ビルダー コンテナを削除します。

    gcloud container images delete gcr.io/$PROJECT_ID/scala-sbt \
        --force-delete-tags \
        --quiet
    
  6. 不要になった Cloud Storage バケットを削除します。

    gsutil rm -r YOUR_BUCKET_NAME
    

    バケットを削除すると、バケットに保存されているすべてのオブジェクトも削除されます。削除したバケットやオブジェクトは復元できません。

次のステップ