深度学习技术已经广泛应用在各个行业领域。实际应用,通过大量数据往往可以训练一个泛化能力好的模型,但如何将模型进行快捷、方便的远程部署,已成为好多企业考虑的问题。现阶段,常用的深度学习模型远程部署工具有tensrflow/serving、onnx、OpenVINO、paddlepaddle/serving。本文就来详细介绍如何用Docker完成tensorflow/serving远程部署深度学习模型

1、环境准备

1.1、 系统:ubuntu16.04/centos7.2
1.2、 NVIDIA驱动:要求满足cuda10.0+cudnn7.6
1.3、 docker+nvidia-docker2:安装教程[link](https://editor.csdn.net/md/?articleId=106342751)
1.4、 tensorflow1.14.0 + keras2.3
1.5、 深度学习模型:keras的.h5模型,tensorflow的.ckpt或.pb模型

2、模型转换

2.1、keras训练得到的.h5模型
from keras import backend as K
import tensorflow as tf
from tensorflow.python import saved_model
from tensorflow.python.saved_model.signature_def_utils_impl import (build_signature_def, predict_signature_def)
from keras_retinanet import models
import shutil
import os#tensorflow/serving模型保存路径
export_path = 'keras-retinanet-master/snapshots/fire_models'
#导入keras模型
num_classes = 1
model = models.convert_model(    model=models.backbone(backbone_name='resnet50').retinanet(num_classes=num_classes),nms=True,class_specific_filter=True,anchor_params=None
)
model.load_weights('keras-retinanet-master/snapshots/resnet50_csv_11.h5')
#打印模型的输入、输出层
print('Output layers', [o.name[:-2] for o in model.outputs])
print('Input layer', model.inputs[0].name[:-2])
#建立一个builder
if os.path.isdir(export_path):shutil.rmtree(export_path)
builder = saved_model.builder.SavedModelBuilder(export_path)#定义模型的输入输出,建立调用接口与tensor签名之间的映射
signature = predict_signature_def(inputs={'input': model.input},   #创建输入字典,key为自己定义名字,value为.h5模型的输入outputs={'loc_box': model.outputs[0],  #创建输出字典,key为自定义名字,value为.h5模型的输出'fire_pre': model.outputs[1],'fire_class': model.outputs[2]})
sess = K.get_session()       #创建会话#建立模型名称与模型签名之间的映射
builder.add_meta_graph_and_variables(sess=sess,\tags=[saved_model.tag_constants.SERVING],\signature_def_map={'predict': signature}   )
#保存模型
builder.save()
2.2、tensorflow训练得到的.pb模型转化为tf_serving .pb模型
import tensorflow as tf
import osdef export_model(PATH_TO_PB):tf.reset_default_graph()output_graph_def = tf.GraphDef()with tf.gfile.GFile(PATH_TO_PB, 'rb') as fid:# 将*.pb文件读入serialized_graphserialized_graph = fid.read()# 将serialized_graph的内容恢复到图中output_graph_def.ParseFromString(serialized_graph)# print(output_graph_def)# 将output_graph_def导入当前默认图中(加载模型)tf.import_graph_def(output_graph_def, name='')print('模型加载完成')# 使用默认图,此时已经加载了模型detection_graph = tf.get_default_graph()# self.sess = tf.Session(graph=detection_graph)config = tf.ConfigProto()config.gpu_options.allow_growth = Truesess = tf.Session(config=config, graph=detection_graph)#导出图中输入变量image_tensor = detection_graph.get_tensor_by_name('input_1:0')#导出图中输出变量boxes=detection_graph.get_tensor_by_name('filtered_detections/map/TensorArrayStack/TensorArrayGatherV3:0')scores = detection_graph.get_tensor_by_name('filtered_detections/map/TensorArrayStack_1/TensorArrayGatherV3:0')classes = detection_graph.get_tensor_by_name('filtered_detections/map/TensorArrayStack_2/TensorArrayGatherV3:0')return sess, image_tensor, boxes,scores, classes
def main(export_model_dir):sess, image_tensor, boxes,scores, classes = export_model(PATH_TO_CKPT)#创建一个builderexport_path_base = export_model_direxport_path = os.path.join(tf.compat.as_bytes(export_path_base))builder = tf.compat.v1.saved_model.builder.SavedModelBuilder(export_path)print('step2 => Export path(%s) ready to export trained model' % export_path)#创建tensorflow/serving模型输入输出映射inputs = {'input': tf.compat.v1.saved_model.utils.build_tensor_info(image_tensor)}outputs = {'loc_box': tf.compat.v1.saved_model.utils.build_tensor_info(boxes),'fire_pre': tf.compat.v1.saved_model.utils.build_tensor_info(scores),'fire_class': tf.compat.v1.saved_model.utils.build_tensor_info(classes)}prediction_signature = (tf.compat.v1.saved_model.signature_def_utils.build_signature_def(inputs, outputs, method_name=tf.saved_model.PREDICT_METHOD_NAME))print('step3 => prediction_signature created successfully')# 建立模型名称与模型签名之间的映射builder.add_meta_graph_and_variables(sess, [tf.saved_model.SERVING],signature_def_map={'predict': prediction_signature})# tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY:prediction_signature,#         })print('step4 => builder successfully add meta graph and variables\nNext is to export model...')builder.save()print('Done exporting!')if __name__ == '__main__':PATH_TO_PB = 'snapshots/model.pb'outputs = 'snapshots/my_models'main(outputs)
2.3、tensorflow训练得到的.pb模型
import tensorflow as tf
import osdef export_model(PATH_TO_CKPT):checkpoint_file = tf.train.latest_checkpoint(PATH_TO_CKPT)graph = tf.Graph()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 graphsaver = tf.train.import_meta_graph("{}.meta".format(PATH_TO_CKPT))saver.restore(sess, checkpoint_file)#恢复图中输入变量image_tensor = detection_graph.get_tensor_by_name('input_1:0')#恢复图中输出变量boxes=graph.get_tensor_by_name('filtered_detections/map/TensorArrayStack/TensorArrayGatherV3:0')scores = graph.get_tensor_by_name('filtered_detections/map/TensorArrayStack_1/TensorArrayGatherV3:0')classes = graph.get_tensor_by_name('filtered_detections/map/TensorArrayStack_2/TensorArrayGatherV3:0')return sess, image_tensor, boxes,scores, classesdef main(export_model_dir):sess, image_tensor, boxes,scores, classes = export_model(PATH_TO_CKPT)# 创建一个builderexport_path_base = export_model_direxport_path = os.path.join(tf.compat.as_bytes(export_path_base))builder = tf.compat.v1.saved_model.builder.SavedModelBuilder(export_path)print('step2 => Export path(%s) ready to export trained model' % export_path)# 定义模型的输入输出,建立调用接口与tensor签名之间的映射inputs = {'input': tf.compat.v1.saved_model.utils.build_tensor_info(image_tensor)}outputs = {'loc_box': tf.compat.v1.saved_model.utils.build_tensor_info(boxes),'fire_pre': tf.compat.v1.saved_model.utils.build_tensor_info(scores),'fire_class': tf.compat.v1.saved_model.utils.build_tensor_info(classes)prediction_signature = (tf.compat.v1.saved_model.signature_def_utils.build_signature_def(inputs, outputs, method_name=tf.saved_model.PREDICT_METHOD_NAME))print('step3 => prediction_signature created successfully')# 建立模型名称与模型签名之间的映射builder.add_meta_graph_and_variables(sess, [tf.saved_model.SERVING],signature_def_map={'predict': prediction_signature})# tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY:prediction_signature,#         })print('step4 => builder successfully add meta graph and variables\nNext is to export model...')builder.save()print('Done exporting!')if __name__ == '__main__':PATH_TO_CKPT = 'snapshots/model.ckpt'outputs = 'snapshots/my_models'        main(outputs)

3、远程部署

3.1、拉取镜像$: docker pull tensorflow/serving:latest        #cpu版本$: docker pull tensorflow/serving:gpu-latest    #gpu版本,nvidia驱动要求满足cuda10.0以上
3.2、模型文件夹结构(--表示文件夹,-表示文件):-- mul_models-- fire-model-- 1               #文件夹名必须是数字-  *.pb;--  variable
3.3、启动服务$: docker run -d --runtime=nvidia --rm -p 8500:8500 -p 8501:8501 --mount type=bind,source=${model_path},target=/models/fire-model -e MODEL_NAME=fire-model -e NVIDIA_VISIBLE_DEVICES=0 -t tensorflow/serving:latest-gpu#注意:(1)tensorflow/serving镜像默认的端口是8500和8501,其中8500访问方式是grpc方式,8501访问方式是HTTP方式;(2)执行该命令时,mount、source、target命令之间不能存在空格,否则会报错(3)更新模型时,直接将新的模型文件丢进fire-model 文件夹里面即可,无需停止服3.4、参数说明--mount:   表示要进行挂载source:    指定要运行部署的tensorflow/serving模型地址,target:     挂载到docker容器中/models/目录下,如果改变路径会出现找不到model的错误-t:         指定的是挂载到哪个容器-d:         后台运行-p:         指定主机到docker容器的端口映射-e:         环境变量-v:         docker数据卷  #可选择--name:     指定容器name,后续使用比用container_id更方便   #可选择--per_process_gpu_memory_fraction:模型启动时占用gpu的显存

4、多个模型同时远程部署

第3步是针对单个深度学习模型进行远程部署.但在实际应用中,我们可能有多个深度学习模型需要部署,其实很简单,tensorflow/serving镜像允许通过配置文件来同时\
部署多个模型。
4.1、模型文件夹结构(--表示文件夹,-表示文件):-- mul_models- model.config-- my_models1-- 1 -  *.pb;--  variable-- 2 -  *.pb-- variables-- my_models2 -- 1-  *.pb--  variables-- my_models3 -- 3-  *.pb--  variables4.2、编写model.config配置文件:model_config_list:{config:{name:"my_models1",         #模型名称,一般用文件夹名称即可base_path:"/models/mul_models/my_models1",  #模型在容器中的路径model_platform:"tensorflow",model_version_policy:{      #部署该文件下模型的所有版本all:{}}},config:{name:"my_models2",base_path:"/models/mul_models/my_models2",model_platform:"tensorflow",model_version_policy:{        #部署该文件下模型最新版本latest:{num_verision:1}}},config:{name:"my_model3",base_path:"/models/mul_models/my_model3",model_platform:"tensorflow",model_version_policy: {      #部署该文件下模型指定版本specific: {versions: 1}}} }
4.3、启动服务:$: docker run --runtime=nvidia --rm -p 8500:8500 --mount type=bind,source=${model_path},target=/models/deep_models -e NVIDIA_VISIBLE_DEVICES=0 -t tensorflow/serving:latest-gpu --model_config_file=/models/deep_models/model.config

5、测试

tensorflow/serving镜像默认有两种访问方式,分别为grpc方式和HTTP方式,从响应速度方面来看,grpc方式速度更快。

5.1 grpc方式

5.1.1 安装tensorflow-serving-api
   $: pip install tensorflow-serving-api(注:该api安装的版本必须要与tensorflow版本对应)
5.1.2 测试代码
import tensorflow as tf
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
import grpc                #如果报错找不到grpc模块,终端进行安装:pip install grpc
import cv2
import numpy as np
from time import timechannel = grpc.insecure_channel("localhost:8500")
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
request1 = predict_pb2.PredictRequest()
request1.model_spec.name = "fire_models"
#request1.model_spec.signature_name = tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY
request1.model_spec.signature_name = "predict"
preprocess(image):'''模型输入前期处理'''def postprocess(boxes,scores,labels):'''模型输出后期处理'''def main():img_path = "path/to/image"image = cv.imread(img_path)preprocess(image)a1 = time()request1.inputs["input"].ParseFromString(tf.contrib.util.make_tensor_proto(image_np_expanded, dtype=tf.float32).SerializeToString())response = stub.Predict(request1)a2 = time()print('目标检测响应时间{}'.format(a1 - a2))results = {}for key in response.outputs:tensor_proto = response.outputs[key]results[key] = tf.contrib.util.make_ndarray(tensor_proto)boxes = results["loc_box"]scores = results["fire_pre"]labels = results["fire_class"]postprocess(boxes,scores,labels)      if __name__ == '__main__': main()   
5.2 HTTP方式
import requests
from time import time
import json
import numpy as np
import cv2
def preprocess(image):'''模型输入前期处理'''
def postprocess(boxes,scores,labels):'''模型输出后期处理'''
def main():url = 'http://localhost:8501/v1/models/my_models:predict'    #配置IP和portimg_path = "path/to/image"image = cv.imread(img_path)preprocess(image)a1 = time()predict_request = { "inputs" : image_np_expanded.tolist()}      #准备需要发送的数据,"inputs"与与.pb模型设置的输入节点一致r = requests.post(url, json=predict_request)                    #发送请求a2 = time()print('目标检测响应时间{}'.format(a1 - a2))prediction = json.loads(r.content.decode("utf-8"))['outputs']   #获取响应结果boxes = np.array(prediction.get("loc_box"))scores = np.array(prediction.get('fire_pre'))labels = np.array(prediction.get("fire_class"))postprocess(boxes,scores,labels) if __name__ == '__main__': main()      

至此,tensorflow/serving深度学习模型在线部署已全部完成。

nvidia-docker2完成tensorflow/serving深度学习模型在线部署相关推荐

  1. 如何使用Keras和TensorFlow建立深度学习模型以预测员工留任率

    The author selected Girls Who Code to receive a donation as part of the Write for DOnations program. ...

  2. 深度学习模型DNN部署到安卓设备上全流程示例——{pytorch->onnx>ncnn->Android studio}

    之前写过一篇文章 "Windows配置pytorch转onnx转ncnn转android设备" 如何配置环境设置,可以参考这篇如何配置 目录 "Windows配置pyto ...

  3. 深度学习模型DNN部署到安卓(移动)设备上——pytorch->onnx->ncnn->Android

    最近,由于实验要求,我需要把在服务器上训练好的pytorch模型预训练.pth文件部署到安卓端测试推理时间,但是一直不知道应该怎么转变模型和部署,查了很多资料,遇到了很多问题,在同学的帮助下,尝试成功 ...

  4. Transfer Learning Toolkit (TLT) + DeepStream (DS)快速部署深度学习模型(以口罩检测为例)

    文章目录 简介 TLT DS 基于TLT进行迁移学习 环境准备 模型训练 基于DS的模型部署 总结 最近在做一个深度学习的横向,被实时性搞的很头疼,遂打算研究研究新的技术路线,做点技术储备.TLT+D ...

  5. 在英特尔硬件上部署深度学习模型的无代码方法 OpenVINO 深度学习工作台的三部分系列文章 - CPU AI 第一部

    作者 Taylor, Mary, 翻译 李翊玮 关于该系列 了解如何转换.微调和打包推理就绪的 TensorFlow 模型,该模型针对英特尔®硬件进行了优化,仅使用 Web 浏览器.每一步都在云中使用 ...

  6. tflearn教程_利用 TFLearn 快速搭建经典深度学习模型

    使用 TensorFlow 一个最大的好处是可以用各种运算符(Ops)灵活构建计算图,同时可以支持自定义运算符(见本公众号早期文章<TensorFlow 增加自定义运算符>).由于运算符的 ...

  7. 如何在浏览器上跑深度学习模型?并且一行JS代码都不用写

    翻译 | 林椿眄 编辑 | 周翔 2017 年 8 月,华盛顿大学的陈天奇团队发布了 TVM,和 NNVM 一起组成深度学习到各种硬件的完整优化工具链,支持手机.CUDA.OpenCL.Metal.J ...

  8. 深度学习模型压缩与加速综述!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:Pikachu5808,编辑:极市平台 来源丨https://zh ...

  9. 深度学习模型压缩与加速综述

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 导读 本文详细介绍了4种主流的压缩与加速技术:结构优化.剪枝.量化 ...

最新文章

  1. CMS之图片管理(3)
  2. git查看改变的方法
  3. Maven配置阿里镜像仓库
  4. mac中打开nginx位置
  5. python虚拟环境可以运行pyspark_pyspark使用自定义的python
  6. python可以做什么工作-python都能干什么用
  7. Android 内存泄露作业
  8. 第六届蓝桥杯--奇妙的数字和移动距离
  9. php左内连接,内连接和外连接的区别是什么
  10. XMind 8破解教程
  11. Windows10系统旧电脑打包迁移新电脑
  12. Activiti6在Springboot下的使用 6 并行网关的处理
  13. nginx: [warn] conflicting server name “xxx“ on 0.0.0.0:80解决
  14. 从天津滨海新区大爆炸、危化品监管聊聊 IT人背负的社会责任感
  15. 最受中国人欢迎的10种日本药
  16. 区块链研究生专业_“区块链大数据赋能低碳发展”高端研讨活动 在增城低碳总部举行...
  17. python3将unicode编码\u60f3\u4f60\u4e86转换成中文
  18. OPENCV针对图像EXIF旋转问题
  19. shader 顶点属性——颜色
  20. mamp 配置php,mamp如何修改php.ini

热门文章

  1. virtualbox搭建一个局域网
  2. 逐年缩招,7成毕业生留沪,上交电院近年招生情况如何?
  3. C++基础:面向对象编程
  4. 五个人来自不同地方,住不同房子,养不同动物,吸不同牌子香烟,喝不同饮料,喜欢不同食物
  5. 【智能家居】Home Assistant入门安装并内网穿透实现远程安全控制
  6. SpringCloud第七章:Hystrix断路器
  7. Python-用动漫小姐姐实现马赛克拼图
  8. 电子计算机的多种功能课件,电子计算机与多媒体教学课件 - 教学课件
  9. ffalcon电视html接口,FFALCON雷鸟新极客智屏,新极客,新选择
  10. 计算机专业大学新生笔记本,计算机专业大一新生,有什么合适的笔记本推荐