Tensor-serving部署
文章目录
- Tensor-serving部署
- Docker下载安装
- 模型转换
- Tensor-serving安装
Docker下载安装
由于本人系统是window10系统,所以下win10桌面版的docker系统,下载链接如下:
选择路径安装成功之后,去dockerhub注册一个账号,进行登录之后,点击桌面图标看到如下画面:
左下角和任务栏出现一个鲸鱼图标,就说明安装成功了。
模型转换
此处需要将之前训练中途保存为ckpt格式的模型进行转化,平时训练采用的保存方式产生的文件如下:
包含以上文件,这是每次只存储最新的模型文件产生的4个文件,当然有些每次保存几步的结果就可能不止4个文件。
然后说一下什么是.pb文件:
参考:
保存模型为 PB 文件,它具有语言独立性,可独立运行,封闭的序列化格式,任何语言都可以解析它,它允许其他语言和深度学习框架读取、继续训练和迁移 TensorFlow 的模型。
所以接下来需要利用tensorflow中tf.saved_model.builder.SavedModelBuilder这个方法进行对ckpt文件的转化,转化步骤如下。
输入ckpt路径:
input_checkpoint = './check/ckpt_ls128_sg20_cd100/'
输出pb文件路径:
export_path = './nerCheck/1'
PS:以上的说明为此处的1可以理解为版本号,后面给pb路径的时候只用给到nerCheck这一层,因为tensorserving会自动加载版本。
特别说明,该路径一定不能先创建,tf要自动去创建该路径,如果先创建之后会报已经存在的错误。
开始加载ckpt文件:
# 加载最近的ckpt
checkpoint_file = tf.train.latest_checkpoint(input_checkpoint)
创建默认图:
# 创建默认图
graph = tf.Graph()
由于是1.1x.0版本的tensorflow的转化所以要恢复默认图结构,tf2.0的占时还没接触到,后续更新,在默认图上进行转化。
with graph.as_default():
# 配置会话
session_conf = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)
# 创建会话
sess = tf.Session(config=session_conf)
with sess.as_default():
# 载入保存好的meta graph
saver = tf.train.import_meta_graph("{}.meta".format(checkpoint_file))
# 恢复图中变量
saver.restore(sess, checkpoint_file)
以上就通过import_meta_graph方法恢复了图中的变量,之后就用到刚提到的方法进行对模型的输入输出和中途的操作进行封装和转化。
接上面代码:
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
# 需要用到模型中定义的操作名称,需要找到
# 建立签名映射,需要包括计算图中的placeholder(ChatInputs, SegInputs, Dropout)
"""
build_tensor_info 建立一个基于提供的参数构造的TensorInfo protocol buffer,
输入:tensorflow graph中的tensor;
输出:基于提供的参数(tensor)构建的包含TensorInfo的protocol buffer
get_operation_by_name 通过name获取checkpoint中保存的变量,能够进行这一步的前提是在模型保存的时候给对应的变量赋予name
"""
char_inputs = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("ChatInputs").outputs[0])
seg_inputs = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("SegInputs").outputs[0])
dropout = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("Dropout").outputs[0])
logits = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("project/Reshape").outputs[0])
transition = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("crf_loss/transitions").outputs[0])
先通过graph.get_operation_by_name(“ChatInputs”)方法获取图中的输入变量和操作。
再建立接口的映射:
"""
signature_constants
SavedModel保存和恢复操作的签名常量。
在序列标注的任务中,这里的method_name是"tensorflow/serving/predict"
"""
# 定义模型的输入输出,建立调用接口与tensor签名之间的映射
labeling_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={
"charinputs": char_inputs,
"dropout": dropout,
"seginputs": seg_inputs,
},
outputs={
"logits": logits,
"transitions": transition,
},
method_name="tensorflow/serving/predict"
))
其中,method_name对应请求接口时候对应的predict方法,最后对模型进行封装保存。
"""
add_meta_graph_and_variables
建立一个Saver来保存session中的变量,输出对应的原图的定义,这个函数假设保存的变量已经被初始化;
对于一个SavedModelBuilder,这个API必须被调用一次来保存meta graph;
对于后面添加的图结构,可以使用函数 add_meta_graph()来进行添加
"""
# 建立模型名称与模型签名之间的映射
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
# 保存模型的方法名,与客户端的request.model_spec.signature_name对应
signature_def_map={
tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
labeling_signature
})
builder.save()
print("Build Done")
如果成功之后会在相应的路径下产生如下文件:
Tensor-serving安装
将模型转化好之后,开始Tensor-serving的安装,这里推荐docker的方式安装,方便快捷。直接通过一下命令拉去即可:
docker pull tensorflow/serving
如果要使用tensor-serving样例就需要去github上去拉取,地址如下:
https://github.com/tensorflow/serving
然后,Tensor-serving支持两种方式进行部署:
- gRPC
- REST FULL
以上分别对应的端口为8500和8501,接下来就使用docker命令进行模型部署,先展示REST FULL的方式启动:
docker run -p 8501:8501 --mount type=bind,source=D:\jupyter_space\tensorserving\nerCheck,target=/models/nerCheck -e MODEL_NAME=nerCheck -t tensorflow/serving &
以上说明,-p为绑定的端口,–mount为挂载对应到具体win10路径下对应的模型路径,source为对应pb文件的路径,target为映射到docker容器里面的路径,-e 为模型的名称对应的文件夹名称,&为后台启动模式。
启动成功之后如下图所示:
然后用postman进行接口测试如下:
可以看到已经返回结果了,下面再采用gRPC的模式进行部署,命令只需要改为8500即可。
docker run -p 8500:8500 --mount type=bind,source=D:\jupyter_space\tensorserving\nerCheck,target=/models/nerCheck -e MODEL_NAME=nerCheck -t tensorflow/serving &
启动成功界面如下:
测试请求,需要安装和导入依赖如下:
import grpc
from tensorflow_serving.apis import prediction_service_pb2_grpc, predict_pb2
然后定义请求方法:
def tfserving_grpc(charinputs, seginputs):
server = '192.168.0.166:8500'
channel = grpc.insecure_channel(server)
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
request = predict_pb2.PredictRequest()
request.model_spec.name = 'nerCheck'
# request.model_spec.version.value = 1000001
request.model_spec.signature_name = 'serving_default'
# 构造输入
request.inputs["charinputs"].CopyFrom(tf.contrib.util.make_tensor_proto(charinputs))
request.inputs["seginputs"].CopyFrom(tf.contrib.util.make_tensor_proto(seginputs))
request.inputs["dropout"].CopyFrom(tf.contrib.util.make_tensor_proto(1.0))
response = stub.Predict(request, 300)
# 获取结果
results = {}
for key in response.outputs:
tensor_proto = response.outputs[key]
results[key] = tf.contrib.util.make_ndarray(tensor_proto)
# 输出结果
logits = results["logits"]
transitions = results["transitions"]
return logits, transitions
以上参照代码进行对应自己本地IP,输入和输出的修改即可,测试结果如下:
可以看到已经返回了,logits和trans只不过后续你自己根据返回的结果进一步写自己的预测代码即可。
以上即为win10+docker+tensorserving的模型两种方式的部署,本人做过测试,传统实例化加载模型的方式进行预测和利用tensorserving部署进行预测时间分别为:2.31s和0.05s,所以极大的提高了预测速度。