TensorFlow Servingを理解するために訓練済モデル作成から推論リクエストまでを整理してみました。
いつも適当にTensorFlow Serving系のサービスに推論リクエストを送っていたので、理解が浅いままで気持ち悪かったので少し頑張りました。
#環境
種類 | バージョン | 内容 |
---|---|---|
OS | Ubuntu18.04.01 LTS | 仮想で動かしています |
TensorFlow Serving (tensorflow-model-server) |
1.13.0 | tensorflow-model-server-universalというのもあるそうですが、無難な方にしておきます |
Pyenv | 1.2.11 | Pyenvインストールは別記事「UbuntuにpyenvとvenvでPython開発環境構築」参照 |
Python | Python3.6.8 | Pyenv上でPythonバージョン管理。ライブラリはvenvで管理しています。 |
1. 訓練済モデル作成
1.1. venv仮想環境作成
まっさらなvenv仮想環境を"py36"という名前で作成し、有効化とpipの最新化。詳しくは、別記事「UbuntuにpyenvとvenvでPython開発環境構築」を参照ください。
# From venv directory
python -m venv py36
source py36/bin/activate
pip install --upgrade pip
1.2. 訓練済モデル作成
訓練モデル作成をします。ローカル環境でPythonプログラムを実行してSavedModelを作るのですが、Google Colaboratoryで直接実行して、SavedModelをダウンロードしてもOKです。別記事「Google Colaboratory概要と使用手順(TensorFlowもGPUも使える)」に概要を書いています。
公式TensorFlow-Servingチュートリアルはmnistを使うのですが、より単純なモデルの方がわかりやすいと考え、あえてオリジナルプログラムにしています。
###1.2.1. 訓練モデル作成プログラムクローン
GitHubから簡単なSavedModel作成プログラムをダウンロードします。
プログラム内容については以下の記事を参照ください。
git clone https://github.com/YoheiFukuhara/keras-for-beginner.git
1.2.2. パッケージインストールとJupyter起動
訓練用に使うパッケージをインストールして、Jupyter Labを起動します。
pip install tensorflow numpy jupyterlab
jupyter lab
1.2.3. SavedModel保存
Keras03_Serving.ipynbを実行します。
あとはセルを実行していくだけなのですが、以下のセルでSavedModelを保存しています。
tf.contrib.saved_model.save_keras_model(model, './models/keras_export')
「./models/keras_export」以下にフォルダがあります、保存されています。
途中、こんなセルがある部分では、「./models/keras_export」以下のフォルダ名(以下の例では「1558705852」)を変更して実行してください。自動的に命名され生成されるフォルダです。これで、SavedModelの内容が参照できます。
# フォルダ名が動的に生成されるので、都度変更が必要
!saved_model_cli show --all --dir ./models/keras_export/1558705852
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: init_1
Method name is:
signature_def['serving_default']:
The given SavedModel SignatureDef contains the following input(s):
inputs['dense_input'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 2)
name: dense_input:0
The given SavedModel SignatureDef contains the following output(s):
outputs['dense_1'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 1)
name: dense_1/Sigmoid:0
Method name is: tensorflow/serving/predict
作ったSavedModelファイル(./models/keras_export/<自動生成フォルダ>以下のファイル郡)を適当なフォルダに放り込んでおきます。私はtmpフォルダにmodel->1という階層で置いています。ここの1はモデルバージョン管理用なので1から連番の数字にします(次に訓練済モデルを更新する場合は「2」)。
tmp
└── model
└── 1
├── assets
│ └── saved_model.json
├── saved_model.pb
└── variables
├── checkpoint
├── variables.data-00000-of-00001
└── variables.index
2. モデルサーバー(Model Server)構築
公式サイトの手順に従ってインストールします。
今回はDockerを使わずにAPTでインストールします。Dockerを使わない理由は、単純にDocker環境に新たに色々とインストールするのが面倒だったからです。
2.1. パッケージソースの追加
TensorFlow Serving配布URIをパッケージソースに追加します。
echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.list && \
curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -
2.2. モデルサーバーインストール
APTを使ってモデルサーバー(Model Server)のインストール
sudo apt-get update && sudo apt-get install tensorflow-model-server
2.3. モデルサーバー起動
訓練済モデルを置いてモデルサーバー起動。基本的にDockerで動かすことが推奨らしく、あまり直接起動する解説がなかったので、公式のRunning a serving imageあたりを見ながらパラメータを指定。
tensorflow_model_server --port=9000 --model_name=test --model_base_path=/tmp/model
3. 推論実行
3.1. 推論Python環境作成
仮想環境は共用としています。別でも問題ないですが、たくさん仮想環境を作るのが面倒だったためです。必要なパッケージをインストールします(共用としない場合は、追加でtensorflowもインストールしてください)。
source <venv>/py36/bin/activate
pip install tensorflow-serving-api request grpcio
私が実行した時点のバージョンは以下の通りです。
Package | Version |
---|---|
tensorflow-serving-api | 1.13.0 |
request | 2019.4.13 |
grpcio | 1.20.1 |
3.2. 推論プログラム実行
「1.2.1. 訓練モデル作成プログラムクローン」でクローンした中の、Keras04_Serving_client.ipynbを実行
3.2.1. パッケージインポート
使うパッケージをインポート。
import grpc
import tensorflow as tf
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
3.2.2. 推論データ配列を作成
data = [ 0.123, 0.567]
3.2.3. リクエストデータの作成
リクエストデータを作成します。request.model_spec.signature_nameとrequest.inputsには「1.2.3. SavedModel保存」のsaved_model_cliで確認した名称を指定しています。
request = predict_pb2.PredictRequest()
request.model_spec.name = 'test' #モデル名
request.model_spec.signature_name = 'serving_default' #signature
request.inputs['dense_input'].CopyFrom(
tf.make_tensor_proto(data, shape=[1,2])) ##inputs
3.2.4. 推論実行
ローカルのポート9000に対して推論リクエストを投げます。
channel = grpc.insecure_channel("localhost:9000")
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
print(stub.Predict(request, 10)) #10秒のtimeout
jsonで答えが返ってきました!投げたデータが1以下なのに対して答えが0.287...なので正解です。
outputs {
key: "dense_1"
value {
dtype: DT_FLOAT
tensor_shape {
dim {
size: 1
}
dim {
size: 1
}
}
float_val: 0.28794631361961365
}
}
model_spec {
name: "test"
version {
value: 1
}
signature_name: "serving_default"
}