Vertex AI AutoML で作成した機械学習モデルを Cloud Run にデプロイする

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では Google Cloud(旧称 GCP)の機械学習サービスである Vertex AIAutoML で作成した機械学習モデルを、サーバーレスなコンテナ実行基盤である Cloud Run にデプロイしていきます。

Vertex AI & Cloud Run

Vertex AI および Cloud Run とは?

Vertex AI および Cloud Run がどんなサービスなのかについては、以下の記事で解説しています。

blog.g-gen.co.jp

blog.g-gen.co.jp

Vertex AI で作成したモデルのデプロイについて

Vertex AI では、サービスの機能の 1 つである Vertex AI Endpoints を使用することで、数クリックでモデルをデプロイし、提供されたエンドポイントに対して予測リクエストを送信することができます。
この方法では、モデルを簡単にデプロイして Vertex AI で管理することができる反面、デプロイされたモデルに対しては、予測リクエストが全くない場合でも常に課金されてしまいます(参考)。

そこで、サーバーレスコンピューティングのサービスである Cloud Run にモデルをデプロイすることで、予測リクエストを処理するときだけ、モデルを利用可能な状態にします。
Cloud Run では、リクエストがないときはコンテナインスタンス数を 0 までスケールインすることができ、コンピューティング料金は実行時間分の課金となっているため、リクエストの頻度によっては、 Vertex AI Endpoints でモデルをデプロイするよりもかなり安く済ませることができます。

ただし、Cloud Run では GPU を使用することができない点には注意が必要です。

当記事で Cloud Run にデプロイするモデル

以下の記事で作成した、表形式データを学習に使用した二項分類モデルをデプロイしていきます。

機械学習初心者がVertex AIでモデルを構築してみた(AutoML) - G-gen Tech Blog

このモデルでは、ある個人に関する様々な情報(年齢、職業、結婚歴など)をもとに、「年収が $50,000 よりも高いか、$50,000 以下か」を予測することができます。

Vertex AI Model Registry からモデルをエクスポートする

Vertex AI の Model Registry から、Cloud Storage にモデルをエクスポートします。
今回は sasashun-vertexai-test という名前の Cloud Storage バケットを使用していきます。

モデルのエクスポート①

モデルのエクスポート②

Cloud Storage へのエクスポートが完了したら、ローカル環境から以下のコマンドを実行し、モデルを Cloud Storage からローカルにコピーします。

$ gsutil cp -r gs://sasashun-vertexai-test .

コピーした Cloud Storage バケット名のディレクトリに移動します。
以降、ローカル環境で実行するコマンドは、ここから実行していきます。

$ cd sasashun-vertexai-test
 
$ ls
model-5478593762324119552

ローカルの Docker コンテナで予測を実行する

まずは、エクスポートしたモデルをローカルの Docker 環境にデプロイし、予測リクエストを処理してみます。
基本的には ドキュメント に記載されている手順を参考にしていきます。

モデルは以下のようなディレクトリの配下にコピーされています。

./model-<model-id>/tf-saved-model/<export-timestamp>

今回モデルが存在するディレクトリは ./model-5478593762324119552/tf-saved-model/2022-08-17T15:13:50.712659Z となっています。

$ ls -l model-5478593762324119552/2022-08-17T15\:13\:50.712659Z/
total 28
-rw-r--r-- 1 sasashun sasashun  206 Aug 18 00:21 environment.json
-rw-r--r-- 1 sasashun sasashun  454 Aug 18 00:21 feature_attributions.yaml
-rw-r--r-- 1 sasashun sasashun 3080 Aug 18 00:21 final_model_structure.pb
-rw-r--r-- 1 sasashun sasashun 1249 Aug 18 00:21 instance.yaml
drwxr-xr-x 1 sasashun sasashun    6 Aug 18 00:21 predict
-rw-r--r-- 1 sasashun sasashun  697 Aug 18 00:21 prediction_schema.yaml
-rw-r--r-- 1 sasashun sasashun   13 Aug 18 00:21 tables_server_metadata.pb
-rw-r--r-- 1 sasashun sasashun  219 Aug 18 00:21 transformations.pb

Docker ではタイムスタンプが含まれるディレクトリが無効にされてしまうようなので、ディレクトリ名を変更します。
今回は model というディレクトリ名に変更しています。

$ mv model-5478593762324119552/tf-saved-model/2022-08-17T15\:13\:50.712659Z/ \
  model-5478593762324119552/tf-saved-model/model

次に、Google Cloud が提供する、 Vertex AI のモデルを実行するためのモデルサーバーのコンテナイメージを使用して、モデルをデプロイしていきます。

先述のドキュメント通りにコマンドを実行した場合、 asia-docker.pkg.dev/vertex-ai/automl-tabular/prediction-server-v1 からモデルサーバーの Docker イメージを pull しますが、このイメージを使用してデプロイした場合、予測リクエストに対してエラーが返り、リクエストを正常に処理することができませんでした。

そこで、この Issue を参考に、asia-docker.pkg.dev/vertex-ai/automl-tabular/prediction-server:20220616_1125 のイメージを pull し、コンテナを実行します。 ここでは、コンテナに adult-census-pred という名前をつけています。

$ docker run -dit --name adult-census-pred \
 -v `pwd`/model-5478593762324119552/tf-saved-model/model:/models/default \
 -p 8080:8080 \
 asia-docker.pkg.dev/vertex-ai/automl-tabular/prediction-server:20220616_1125

次に、予測リクエストの際に payload フィールドに指定する JSON 形式のファイルを作成します。
JSON には予測に必要な列の列名と値をすべて含めます(複数行も可能)。
今回は ファイル名を request.json としています。

{
  "instances": [
    {
        "age": "47",
        "workclass": "Private",
        "fnlwgt": "264052",
        "education": "Bachelors",
        "education.num": "13",
        "marital.status": "Married-civ-spouse",
        "occupation": "Exec-managerial",
        "relationship": "Husband",
        "race": "White",
        "sex": "Male",
        "capital.gain": "15024",
        "capital.loss": "0",
        "hours.per.week": "50",
        "native.country": "United-States"
    }
  ]
}

ローカルで実行されているモデルサーバーのコンテナに対して、予測リクエストを送信します。

$ curl -X POST --data @request.json http://localhost:8080/predict
{"predictions": [{"scores": [0.0009153289720416069, 0.9990846514701843], "classes": ["<=50K", ">50K"]}]}

今回使用するモデルでは、「年収が $50,000 よりも高い」場合は >50K、そうでない場合は <=50K に分類されます。
予測リクエストの結果は、モデルに与えたデータは 99.9% の確率で >50K に分類されることを示しています。

Artifact Registry にモデルをアップロードする

Cloud Run にモデルをデプロイするために、Google Cloud 上でコンテナイメージを管理する Artifact Registry のリポジトリにモデルをアップロードします。

まず、Artifact Registry のリポジトリを作成します。
リポジトリの作成時に Docker 形式を選択します。

Artifact Registry リポジトリの作成

次に、ローカル環境で、モデルを内包した Docker イメージを作成していきます。
先ほどローカル環境で起動したコンテナは、モデルが配置されているローカルのディレクトリに対して、コンテナの /models/default ディレクトリをマウントしているだけであり、コンテナ側にモデルの実体は存在していません。

以下のコマンドを使用して、ディレクトリのマウントを設定していないコンテナ(adult-census-pred-2)を新たに作成し、モデルをコンテナの /models/default 配下にコピーします。

$ docker create --name adult-census-pred-2 -p 8080:8080 asia-docker.pkg.dev/vertex-ai/automl-tabular/prediction-server:20220616_1125
2fa13f09689d0007423654a3dbb254304f8d4ffc75ad786d015a554908c0ae42
 
$ docker cp `pwd`/model-5478593762324119552/tf-saved-model/model adult-census-pred-2:/models/default

adult-census-pred-2 コンテナから、モデルを内包したコンテナイメージを新たに作成します。
Artifact Registry のリポジトリにイメージを push する場合、イメージ名に Google Cloud のプロジェクト ID などを含めたリポジトリの情報を含めます(参考)。
イメージ名は以下の形式となります。

<location>-docker.pkg.dev/<project-id>/<repository-name>/<image-name>:<tag>

今回は、以下のようにイメージを作成しました。

$ docker commit adult-census-pred-2 asia-northeast1-docker.pkg.dev/sasashun/vertexai-docker-repo/adult-census-pred:20220818
sha256:7fc68d6458dcda72e9bec6e4432792d071c81b6e23d9bf409cde92ed904cafdb
 
$ docker image ls
REPOSITORY                                                                         TAG             IMAGE ID       CREATED         SIZE
asia-northeast1-docker.pkg.dev/sasashun/vertexai-docker-repo/adult-census-pred     20220818        7fc68d6458dc   4 seconds ago   3.06GB
asia-docker.pkg.dev/vertex-ai/automl-tabular/prediction-server                     20220616_1125   46441e5efec4   2 months ago    3.06GB

Artifact Registry のリポジトリに、新たに作成したコンテナイメージを push します。

$ docker push asia-northeast1-docker.pkg.dev/sasashun/vertexai-docker-repo/adult-census-pred:20220818

push したコンテナイメージ

Cloud Run にモデルをデプロイする

Artifact Registry のリポジトリから、コンテナイメージを Cloud Run にデプロイします。
リポジトリ上でコンテナイメージを選択し、Cloud Run にデプロイする を選択します。

コンテナイメージを Cloud Run にデプロイ

今回は 未認証の呼び出しを許可 にチェックを入れ、Cloud Run サービスを公開した状態で作成します。

Cloud Run サービスの作成

デプロイが失敗しました。
ログを見てみると、どうやらサービスに割り当てたメモリが不足しているようです(参考)。

Memory limit of 512M exceeded with 515M used. Consider increasing the memory limit, see https://cloud.google.com/run/docs/configuring/memory-limits

Cloud Run へのデプロイの失敗

メモリの割り当てを変更し、再度デプロイします。

メモリの値を変更

今度はデプロイに成功しました。
URL の項目に、Cloud Run サービスのエンドポイントが記載されています。

サービスのエンドポイント

Cloud Run サービスに予測リクエストを送信する

サービスのエンドポイントの URL に対して、ローカル環境から予測リクエストを送信します。
リクエストには、ローカル環境で試したときと同じ request.json を使用しています。

$ curl -X POST --data @request.json https://adult-census-pred-ai4qoprwhq-an.a.run.app/predict
{"predictions": [{"classes": ["<=50K", ">50K"], "scores": [0.0009153289720416069, 0.9990846514701843]}]}

Cloud Run にデプロイしたモデルを用いて、予測リクエストを処理することができました。

Cloud Run のログ

佐々木 駿太 (記事一覧)

G-gen最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。