G-gen の佐々木です。当記事では Google Cloud(旧称 GCP)の機械学習サービスである Vertex AI の AutoML で作成した機械学習モデルを、サーバーレスなコンテナ実行基盤である Cloud Run にデプロイしていきます。
- Vertex AI および Cloud Run とは?
- Vertex AI で作成したモデルのデプロイについて
- 当記事で Cloud Run にデプロイするモデル
- Vertex AI Model Registry からモデルをエクスポートする
- ローカルの Docker コンテナで予測を実行する
- Artifact Registry にモデルをアップロードする
- Cloud Run にモデルをデプロイする
- Cloud Run サービスに予測リクエストを送信する
Vertex AI および Cloud Run とは?
Vertex AI および Cloud Run がどんなサービスなのかについては、以下の記事で解説しています。
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 形式を選択します。
次に、ローカル環境で、モデルを内包した 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
Cloud Run にモデルをデプロイする
Artifact Registry のリポジトリから、コンテナイメージを 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
メモリの割り当てを変更し、再度デプロイします。
今度はデプロイに成功しました。
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 にデプロイしたモデルを用いて、予測リクエストを処理することができました。
佐々木 駿太 (記事一覧)
G-gen最北端、北海道在住のクラウドソリューション部エンジニア
2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。
趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。
Follow @sasashun0805