🤗 ViTをVertex AIに展開する
Deploy 🤗 ViT to Vertex AI.
前の投稿では、Vision Transformers(ViT)モデルを🤗 Transformersを使用してローカルおよびKubernetesクラスター上に展開する方法を紹介しました。この投稿では、同じモデルをVertex AIプラットフォームに展開する方法を示します。Kubernetesベースの展開と同じスケーラビリティレベルを実現できますが、コードは大幅に簡略化されます。
この投稿は、上記にリンクされた前の2つの投稿を基に構築されています。まだチェックしていない場合は、それらを確認することをお勧めします。
この投稿の冒頭にリンクされたColab Notebookには、完全に作成された例があります。
- Hugging Face TransformersとHabana Gaudiを使用して、BERTを事前に学習する
- 🧨ディフューザーを使用した安定した拡散
- Hugging Face Spacesでタンパク質を可視化する
Google Cloudによると:
Vertex AIは、さまざまなモデルタイプと異なるレベルのMLの専門知識をサポートするツールを提供します。
モデルの展開に関しては、Vertex AIは次の重要な機能を統一されたAPIデザインで提供しています:
-
認証
-
トラフィックに基づく自動スケーリング
-
モデルのバージョニング
-
異なるバージョンのモデル間のトラフィックの分割
-
レート制限
-
モデルの監視とログ記録
-
オンラインおよびバッチ予測のサポート
TensorFlowモデルに対しては、この投稿で紹介されるいくつかの既製のユーティリティが提供されます。ただし、PyTorchやscikit-learnなどの他のフレームワークにも同様のサポートがあります。
Vertex AIを使用するには、請求が有効なGoogle Cloud Platform(GCP)プロジェクトと、次のサービスが有効になっている必要があります:
-
Vertex AI
-
Cloud Storage
最後の2つの投稿で実施したように、ViT B/16モデルをTensorFlowで実装します。モデルは、対応する前処理および後処理操作を埋め込んでシリアル化され、トレーニングとサービングのずれを減らすために使用されます。詳細については、これについて詳しく説明している最初の投稿を参照してください。最終的なシリアル化されたSavedModel
のシグネチャは次のようになります:
与えられたSavedModel SignatureDefには、次の入力が含まれています:
inputs['string_input'] tensor_info:
dtype: DT_STRING
shape: (-1)
name: serving_default_string_input:0
与えられたSavedModel SignatureDefには、次の出力が含まれています:
outputs['confidence'] tensor_info:
dtype: DT_FLOAT
shape: (-1)
name: StatefulPartitionedCall:0
outputs['label'] tensor_info:
dtype: DT_STRING
shape: (-1)
name: StatefulPartitionedCall:1
メソッド名はtensorflow/serving/predictです
このモデルは、画像のbase64エンコードされた文字列を受け入れ、前処理を行い、推論を実行し、最後に後処理の手順を実行します。文字列はネットワーク伝送中に変更されないように、base64エンコードされます。前処理には、入力画像を224×224の解像度にリサイズし、[-1, 1]
の範囲に標準化し、channels_first
のメモリレイアウトに変換することが含まれます。後処理には、予測されたロジットを文字列ラベルにマッピングすることが含まれます。
Vertex AIで展開を行うには、モデルのアーティファクトをGoogle Cloud Storage(GCS)バケットに保持する必要があります。関連するColab Notebookでは、GCSバケットを作成し、モデルのアーティファクトを保存する方法が説明されています。
以下の図は、既にトレーニングされたTensorFlowモデルをVertex AIに展開するための図解的なワークフローを示しています。
次に、Vertex AIのモデルレジストリとエンドポイントについて説明します。
Vertex AIモデルレジストリ
Vertex AIモデルレジストリは、完全に管理された機械学習モデルレジストリです。ここで完全に管理されているということについて注意する点がいくつかあります。まず、モデルがどのようにどこに格納されるかを心配する必要はありません。また、同じモデルの異なるバージョンを管理します。
これらの機能は、本番の機械学習において重要です。高可用性とセキュリティを保証するモデルレジストリを構築することは困難です。また、ブラックボックスの機械学習モデルの内部を制御できないため、現在のモデルを過去のバージョンに戻す必要がある場合があります。Vertex AIモデルレジストリを使用すると、これらを容易に実現できます。
現在サポートされているモデルタイプには、TensorFlow、scikit-learn、およびXGBoostからのSavedModel
が含まれます。
Vertex AI エンドポイント
ユーザーの視点から見ると、Vertex AI エンドポイントは単にリクエストを受け取り、レスポンスを送信するためのエンドポイントを提供するものです。しかし、機械学習オペレーターが設定するための多くの機能が内部にあります。以下は選択できるいくつかの設定です:
-
モデルのバージョン
-
CPU、メモリ、アクセラレータに関する VM の指定
-
コンピュートノードの最小/最大数
-
トラフィックの分割割合
-
モデルの監視ウィンドウの長さと目標
-
予測リクエストのサンプリング率
google-cloud-aiplatform
Python SDK では、Vertex AI 上の展開のライフサイクルを管理するための簡単な API を提供しています。これは以下の 4 つのステップに分かれています:
- モデルのアップロード
- エンドポイントの作成
- モデルをエンドポイントにデプロイする
- 予測リクエストを行う。
これらのステップを通じて、Vertex AI とやり取りするために ModelServiceClient
、EndpointServiceClient
、PredictionServiceClient
モジュールが google-cloud-aiplatform
Python SDK から必要となります。
1. ワークフローの最初のステップは、SavedModel
を Vertex AI のモデルレジストリにアップロードすることです:
tf28_gpu_model_dict = {
"display_name": "ViT Base TF2.8 GPU モデル",
"artifact_uri": f"{GCS_BUCKET}/{LOCAL_MODEL_DIR}",
"container_spec": {
"image_uri": "us-docker.pkg.dev/vertex-ai/prediction/tf2-gpu.2-8:latest",
},
}
tf28_gpu_model = (
model_service_client.upload_model(parent=PARENT, model=tf28_gpu_model_dict)
.result(timeout=180)
.model
)
コードを一部ずつ解説しましょう:
-
GCS_BUCKET
は、モデルアーティファクトが格納されている GCS バケットのパスを示します(例:gs://hf-tf-vision
)。 -
container_spec
では、予測を提供するために使用される Docker イメージの URI を指定します。Vertex AI では TensorFlow モデルを提供するための事前構築済みのイメージを提供していますが、異なるフレームワークを使用する場合には独自の Docker イメージも使用できます(例)。 -
model_service_client
は、モデルを Vertex AI モデルレジストリにアップロードするためのメソッドを公開するModelServiceClient
オブジェクトです。 -
PARENT
は、モデルが GCP 内のどこにスコープされるかを Vertex AI に示すためにf"projects/{PROJECT_ID}/locations/{REGION}"
と設定されています。
2. 次に、Vertex AI エンドポイントを作成する必要があります:
tf28_gpu_endpoint_dict = {
"display_name": "ViT Base TF2.8 GPU エンドポイント",
}
tf28_gpu_endpoint = (
endpoint_service_client.create_endpoint(
parent=PARENT, endpoint=tf28_gpu_endpoint_dict
)
.result(timeout=300)
.name
)
ここでは、endpoint_service_client
を使用して、EndpointServiceClient
オブジェクトを作成および設定します。
3. これで実際のデプロイメントを実行する準備が整いました!
tf28_gpu_deployed_model_dict = {
"model": tf28_gpu_model,
"display_name": "ViT Base TF2.8 GPU デプロイ済みモデル",
"dedicated_resources": {
"min_replica_count": 1,
"max_replica_count": 1,
"machine_spec": {
"machine_type": DEPLOY_COMPUTE, # "n1-standard-8"
"accelerator_type": DEPLOY_GPU, # aip.AcceleratorType.NVIDIA_TESLA_T4
"accelerator_count": 1,
},
},
}
tf28_gpu_deployed_model = endpoint_service_client.deploy_model(
endpoint=tf28_gpu_endpoint,
deployed_model=tf28_gpu_deployed_model_dict,
traffic_split={"0": 100},
).result()
ここでは、Vertex AI Model Registry にアップロードしたモデルと、上記の手順で作成したエンドポイントを連鎖させています。最初に、tf28_gpu_deployed_model_dict
の下にデプロイの設定を定義しています。
dedicated_resources
の下では以下の設定を行っています:
-
デプロイのオートスケーリングに関する
min_replica_count
とmax_replica_count
。 -
machine_spec
ではデプロイのハードウェアの設定を定義します:-
machine_type
は、Docker イメージの実行に使用されるベースのマシンタイプです。基になるオートスケーラは、トラフィックの負荷に応じてこのマシンをスケールします。サポートされるマシンタイプから1つを選択できます。 -
accelerator_type
は、推論に使用されるハードウェアアクセラレータです。 -
accelerator_count
は、各レプリカに接続するハードウェアアクセラレータの数を示します。
-
注意:Vertex AI でモデルをデプロイする際、アクセラレータを指定する必要はありません。
次に、上記の仕様を使用してエンドポイントをデプロイします:
tf28_gpu_deployed_model = endpoint_service_client.deploy_model(
endpoint=tf28_gpu_endpoint,
deployed_model=tf28_gpu_deployed_model_dict,
traffic_split={"0": 100},
).result()
モデルのトラフィック分割を定義していることに注目してください。モデルの複数のバージョンがある場合、キーはモデルのバージョンを示し、値はモデルが提供するトラフィックの割合を示す辞書を定義できます。
Model Registry とエンドポイントを管理するための専用のインターフェースを使用することで、Vertex AI ではデプロイの重要な側面を簡単に制御することができます。
デプロイのスコープを確定するには、約15〜30分かかります。完了すると、コンソール上で確認できるはずです。
デプロイが成功した場合は、予測リクエストを行うことでデプロイされたエンドポイントをテストできます。
まず、base64 エンコードされた画像文字列を準備します:
import base64
import tensorflow as tf
image_path = tf.keras.utils.get_file(
"image.jpg", "http://images.cocodataset.org/val2017/000000039769.jpg"
)
bytes = tf.io.read_file(image_path)
b64str = base64.b64encode(bytes.numpy()).decode("utf-8")
4. 以下のユーティリティは、まずインスタンスのリスト(この場合は 1 つのインスタンスのみ)を準備し、その後予測サービスクライアント(PredictionServiceClient
タイプ)を使用します。 serving_input
は、提供されたモデルの入力シグネチャキーの名前です。この場合、serving_input
は string_input
です。これは、上記に示した SavedModel
シグネチャ出力から確認できます。
from google.protobuf import json_format
from google.protobuf.struct_pb2 import Value
def predict_image(image, endpoint, serving_input):
# 各インスタンスの形式は、デプロイされたモデルの予測入力スキーマに準拠する必要があります。
instances_list = [{serving_input: {"b64": image}}]
instances = [json_format.ParseDict(s, Value()) for s in instances_list]
print(
prediction_service_client.predict(
endpoint=endpoint,
instances=instances,
)
)
predict_image(b64str, tf28_gpu_endpoint, serving_input)
Vertex AI にデプロイされた TensorFlow モデルの場合、リクエストペイロードは特定の形式でフォーマットする必要があります。ViT のような画像のようなバイナリデータを扱うモデルの場合、それらは base64 エンコードする必要があります。公式ガイドによると、各インスタンスのリクエストペイロードは次のようにする必要があります:
{serving_input: {"b64": base64.b64encode(jpeg_data).decode()}}
predict_image()
ユーティリティは、この仕様に準拠したリクエストペイロードを準備します。
デプロイがうまくいけば、predict_image()
を呼び出すと次のような出力が得られるはずです:
predictions {
struct_value {
fields {
key: "confidence"
value {
number_value: 0.896659553
}
}
fields {
key: "label"
value {
string_value: "Egyptian cat"
}
}
}
}
deployed_model_id: "5163311002082607104"
model: "projects/29880397572/locations/us-central1/models/7235960789184544768"
model_display_name: "ViT Base TF2.8 GPU model"
ただし、この方法がVertex AIエンドポイントを使用して予測を取得する唯一の方法ではありません。エンドポイントコンソールに移動し、エンドポイントを選択すると、予測を取得するための2つの異なる方法が表示されます:
cURLリクエストを回避し、Vertex AI SDKを使用せずにプログラムで予測を取得することも可能です。詳細については、このノートブックを参照してください。
TensorFlowモデルを展開するためにVertex AIを使用する方法を学んだので、次にVertex AIが提供するいくつかの有益な機能について説明しましょう。これらの機能により、デプロイメントの深い洞察を得ることができます。
Vertex AIを使用すると、設定なしでモデルを監視することもできます。エンドポイントコンソールから、エンドポイントのパフォーマンスや割り当てられたリソースの利用状況に関する詳細情報を取得できます。
上のチャートで見ると、一時的にアクセラレータのデューティサイクル(利用率)が約100%になっていることがわかります。その後の時間帯は処理するリクエストがなかったため、アイドル状態でした。
この種のモニタリングは、現在展開されているエンドポイントを迅速に特定し、必要に応じて調整するのに役立ちます。モデルの説明のモニタリングを要求することも可能です。詳細については、こちらを参照してください。
ローカルの負荷テストを実行して、エンドポイントの制限をよりよく理解しました。以下の表は、リクエストの統計をまとめたものです:
表に示されているさまざまな統計の中で、「平均(ミリ秒)」はエンドポイントの平均レイテンシを指します。Locustは約17230のリクエストを送信し、報告された平均レイテンシは646ミリ秒で、印象的です。実際には、負荷テストを分散的に実行してより実際のトラフィックに近いものにしたいと考えるでしょう。詳細については、こちらを参照してください。
このディレクトリには、負荷テストの実施方法に関するすべての情報が含まれています。
GCPのコストエスティメータを使用して使用料金を見積もることができ、正確な時間単位の価格表はこちらで確認できます。実際の予測リクエストを処理しているときにのみ料金が発生し、GPUを使用する場合と使用しない場合で価格を計算する必要があります。
カスタムトレーニングモデルのVertex予測では、n1-standard-2
からn1-highcpu-32
のN1マシンタイプを選択できます。この記事ではn1-standard-8
を使用しました。これは8つのvCPUと32GBのRAMが搭載されています。
また、コンピュートノードにアクセラレータを搭載する場合、希望するアクセラレータのタイプに応じて追加料金が発生します。このブログ記事ではNVIDIA_TESLA_T4
を使用しましたが、ほぼすべての最新のアクセラレータ、TPUもサポートされています。詳細については、こちらを参照してください。
🤗 TransformersのTensorFlowビジョンモデルのコレクションが増えています。SegFormerを使用した最新のセマンティックセグメンテーションもサポートしています。この記事で学んだ展開ワークフローをSegFormerなどのセマンティックセグメンテーションモデルに拡張することをお勧めします。
この記事では、Vertex AIプラットフォームを使用してVision Transformerモデルを展開する方法と、その提供する簡単なAPIの使用方法について学びました。Vertex AIの機能により、宣言的な設定に焦点を当て、複雑な部分を取り除くことで、モデルの展開プロセスを支援します。Vertex AIはまた、カスタム予測ルートを介してPyTorchモデルの展開もサポートしています。詳細については、こちらを参照してください。
このシリーズでは、🤗 Transformersからビジョンモデルをローカルに展開するためのTensorFlow Servingが最初に紹介されました。2番目の記事では、そのローカル展開をDockerとKubernetesでスケーリングする方法について学びました。このTensorFlowビジョンモデルのオンライン展開に関するシリーズが、MLツールボックスを次のレベルに進めるのに役立つことを願っています。これらのツールを使用して作成するものを楽しみにしています。
実験のためにGoogleのML Developer Relations Programチームから提供されたGCPクレジットに感謝します。
デプロイメントコードの一部は、Vertex AIコードサンプルの公式GitHubリポジトリのこのノートブックから参照されました。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles