GCP AI Platformで画像認識してみる(モデルデプロイ編)
学習編に続いてモデルのデプロイと推論クライアントアプリの作成をしていきます。
目次
目標
学習済みモデルをGCP上にデプロイしてPythonのクライアントアプリを作る。
GCP上でモデルを定義する
モデルの作成
GCPのAI Platform画面を開いて「モデル」を選択する。新しいモデルを任意の名前で作る。 ここではモデルの名称(クライアントからのアクセス時に使用する)やリージョンを指定する。
バージョンの作成
つぎに、モデルの詳細画面を開いて新しいバージョンを追加する。モデルを実行する際のリソースやPythonバージョンを選択する。 またTensorFlowのバージョンも2.0は選べないが1.13.1で動くだろうということでそれを使うことにする。
注意点
- 現在はGPUマシンタイプを選択できない
- Pythonバージョンとして2.7と3.5のどちらかが選択できる。Python3.5ではバッチトレーニングが出来ないみたい。TensorFlowつかってるならSavedModelにした時点で、サーバーがPython2.7でも問題ないのではとも思う?とりあえず2.7で作ってみる。
- ドキュメントでも言及されている通りモデルサイズは250MB以下にしないといけない。(これを超えるとメモリアロケーションエラーで落ちる)
クライアント環境の準備
サービスアカウント発行(GCPコンソール)
Python クライアント ライブラリの使用 | TensorFlow 用 Cloud ML Engine | Google Cloudの手順に従って、サービス アカウント キーの作成 - vpn-project - Google Cloud Platform のページでサービスアカウントキーを発行する。
クライアントマシンに認証ファイルをJSON形式で保存する。
環境変数の設定(クライアントマシン)
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-credential.json
Pythonライブラリのインストール(クライアントマシン)
GCPにアクセスするためのクライアントライブラリを入れる。
pip install --upgrade google-api-python-client oauth2client
また、サービスアカウントの認証ファイルへのパスを環境変数に追加しておく。 これによってクライアントアプリからOAuth2.0で認証が通るようになる。
Pythonクライアントアプリの作成
AI Platformの推論APIを叩くアプリを作る。
大まかな流れは以下の通り。それぞれかいつまんで説明する。
クライアントアプリの全容は cifar-10-ai-platform/inference.py at master · chmod644/cifar-10-ai-platform を参照。
なお、事前情報として、学習済みモデル(SavedModel形式)がどんな入出力をとるか知っておく必要がある。分からない場合はTensorFlowのsaved_model_cli
コマンドで調べればよい。
saved_model_cli show --all --dir gs://path/to/saved_model_dir/
今回のモデルは以下のようなモデルである。signature_def['serving_default']:
以降を見ると、28x28x3の画像(x)を入力して、スカラー値の推論クラス(class)と10クラス分の確率(probabilities)を出力するものとわかる ※1次元目は省いて説明している
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs: signature_def['__saved_model_init_op']: The given SavedModel SignatureDef contains the following input(s): The given SavedModel SignatureDef contains the following output(s): outputs['__saved_model_init_op'] tensor_info: dtype: DT_INVALID shape: unknown_rank name: NoOp Method name is: signature_def['serving_default']: The given SavedModel SignatureDef contains the following input(s): inputs['x'] tensor_info: dtype: DT_UINT8 shape: (-1, 28, 28, 3) name: serving_default_x:0 The given SavedModel SignatureDef contains the following output(s): outputs['classes'] tensor_info: dtype: DT_INT64 shape: (-1) name: StatefulPartitionedCall:0 outputs['probabilities'] tensor_info: dtype: DT_FLOAT shape: (-1, 10) name: StatefulPartitionedCall:1 Method name is: tensorflow/serving/predict
ペイロードの作成
ペイロードはdict形式で作成する。今回はCIFAR-10の各画像の中央28x28ピクセルを送るので以下のようにする。ここでは、入力imageはshape=[32, 32, 3], dtype=np.uint8の形式になっている。注意点としてはバッチの次元を入れないこと。複数のイメージを推論したい場合はリストに追加するものと思われる。
def generate_payload(image): image = image[2:30, 2:30, :] return {"instances": [{"x": image.tolist()}]} image = something_to_parse_cifar10() # 32x32x3 uint8 image as np.ndarray payload = generate_payload(image)
URLの作成
URLのフォーマットはprojects/<GCPのプロジェクトID>/models/<モデル名>/[versions/<バージョン名>]
である。バージョン名を指定しなかった場合はデフォルトバージョンで処理される。
url = 'projects/{}/models/{}'.format(project, model) if version is not None: url += '/versions/{}'.format(version)
リクエストを送信
service.projectsのpredict関数を使ってリクエストを作って処理する。
service = discovery.build('ml', 'v1') request = service.projects().predict( name=url, body=payload ) response = request.execute() return response
レスポンスをパース
responseはdict型で返ってくる。predictions
というキーに対して推論結果がリストで返ってくる。なお返ってきた時点でバッチ次元(1次元目)が落とされているので、例えばresponse['predictions'][0]['classes']
はスカラー値となる。
probabilities = response['predictions'][0]['probabilities'] pred = response['predictions'][0]['classes']
Pythonクライアントの実行(クライアントマシン)
実際にクライアントアプリを実行してみる。
pip install git+https://github.com/chmod644/cifar-10-ai-platform.git --upgrade cifar-10-inference --project <GCPのプロジェクトID> --model <モデル名> --version <バージョン名>
きちんと画像認識が動いている。
まとめ
とりあえずクライアントアプリから推論できることは確認しました。
このやり方だとRESTful APIにアクセスすることになります(多分)。gRPCのAPIにアクセスする方法も探してみたんですが見つかりませんでした。知ってる人いたら教えてください。
参考URL
モデルをデプロイする | TensorFlow 用 Cloud ML Engine | Google Cloud
Python クライアント ライブラリの使用 | TensorFlow 用 Cloud ML Engine | Google Cloud
Sample Applications | API Client Library for Python | Google Developers