部署過程主要遇到的坑是簽名的問題這里做下記錄參考文檔地址
https://www.tensorflow.org/tfx/serving/serving_basic
https://www.tensorflow.org/api_docs/python/tf/saved_model/signature_constants
這里的部署方式以windows docker為例子,linux系統(tǒng)也是一樣的操作,路徑相應(yīng)改變下就行
github demo地址https://github.com/Caigengliang/exportKerasForTensorflowServer
拉取鏡像
安裝完docker后,可以用一下命令直接拉取最新的tensorflow server鏡像
docker pull tensorflow/serving
導(dǎo)出keras模型保存為tensorflow-server指定格式
先創(chuàng)建一個方法,改方法用于創(chuàng)建指定目錄的文件夾,存在則不動作,不存在則創(chuàng)建。如果改目錄下存在文件應(yīng)該刪除它,以方便模型更新。
def mkdir(path):
import os
import shutil
path=path.strip()
path=path.rstrip("\\")
isExists=os.path.exists(path)
if not isExists:
os.makedirs(path)
return True
else:
filelist=os.listdir(path)
for f in filelist:
filepath = os.path.join( path, f ) #將文件名映射成絕對路勁
if os.path.isfile(filepath): #判斷該文件是否為文件或者文件夾
os.remove(filepath) #若為文件,則直接刪除
print(str(filepath)+" removed!")
elif os.path.isdir(filepath):
shutil.rmtree(filepath,True) #若為文件夾,則刪除該文件夾及文件夾內(nèi)所有文件
print("dir "+str(filepath)+" removed!")
模型導(dǎo)出
在prediction_signature定義了一下參數(shù)
inputs={'images': tensor_info_x}指定輸入張量信息。outputs={'scores': tensor_info_y}指定分?jǐn)?shù)張量信息。method_name是用于推理的方法。對于預(yù)測請求,應(yīng)將其設(shè)置為tensorflow/serving/predict。有關(guān)其他方法名稱,請參閱signature_constants.py 和相關(guān)的 TensorFlow 1.0 API文檔。
其中method_name映射為api的路徑方法名
import tensorflow as tf
import os
import tensorflow.keras.backend as K
from tensorflow.keras.losses import categorical_crossentropy
from tensorflow.keras.optimizers import Adadelta
def export_model(model,
export_model_dir,
model_version
):
"""
:param export_model_dir: type string, save dir for exported model url
:param model_version: type int best
:return:no return
"""
with tf.get_default_graph().as_default():
# prediction_signature
tensor_info_input = tf.saved_model.utils.build_tensor_info(model.input)
tensor_info_output = tf.saved_model.utils.build_tensor_info(model.output)
print(model.output.shape, '**', tensor_info_output)
prediction_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={'images': tensor_info_input}, # Tensorflow.TensorInfo
outputs={'result': tensor_info_output},
#method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)
method_name= "tensorflow/serving/predict")
)
print('step1 => prediction_signature created successfully')
# set-up a builder
mkdir(export_model_dir)
export_path_base = export_model_dir
export_path = os.path.join(
tf.compat.as_bytes(export_path_base),
tf.compat.as_bytes(str(model_version)))
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
builder.add_meta_graph_and_variables(
# tags:SERVING,TRAINING,EVAL,GPU,TPU
sess=K.get_session(),
tags=[tf.saved_model.tag_constants.SERVING],
signature_def_map={
'predict':
prediction_signature,
tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
prediction_signature,
},
)
print('step2 => Export path(%s) ready to export trained model' % export_path, '\n starting to export model...')
#builder.save(as_text=True)
builder.save()
print('Done exporting!')
調(diào)用導(dǎo)出方法導(dǎo)出,這里假設(shè)已經(jīng)把模型保存為.h5文件了
model = tf.keras.models.load_model('./12308nenghao.h5')
export_model(
model,
'C:/tmp/tfserving/pow',
1
)

可以看到對應(yīng)目錄下生成了如下文件:
其中1這個父目錄是版本好,tensorflow-server會識別這個版本號

在docker中運行
指定好路徑
docker run -p 8501:8501 --mount type=bind,source=C:/tmp/tfserving/pow,target=/models/pow -e MODEL_NAME=pow -t tensorflow/serving '&'
server生成兩個接口一個restful一個gprc接口

驗證
直接用postman測試restful

遇到問題
在測試的時候要特別注意輸入的張量的形狀,在導(dǎo)出模型的時候查看下。
{ "error": "Serving signature name: "serving_default" not found in signature def" }
該問題是由簽名沒有設(shè)置默認(rèn)serving_default
檢查下signature_def_map是否缺少設(shè)置,在里面添加 tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
prediction_signature,
其中prediction_signature是tf.saved_model.signature_def_utils.build_signature_def的定義。