Tensorflow2.0+部署(tensorflow/serving)过程备忘记录
部署思路:采用Tensorflow自带的serving进模型部署,采用容器docker
1.首先安装docker
下载地址(下载windows版本):https://desktop.docker.com/
- docker安装
安装就按正常流程一步一步安装即可 - window环境检查
win10,win11版本及以上
虚拟化是否开启(用处不知道,反正大家都开启了,网上有教程,可以搜搜) - 安装wsl
下图是截别人的图
- 安装docker成功
(1)桌面会出现Docker Desktop图标,点击进入后界面如下
(2)给docker添加阿里云镜像源,为了后续下载东西更方便
注册、登录阿里云(支付宝、淘宝扫码都可)
(3)进入后,可以看到自己独立的镜像加速器,是一个网址,最下方一行是给docker配置镜像源的方法,或者直接在Docker Desktop里面,添加那一行命令即可
(4)打开Docker Desktop ,点击设置,Docker Engine,添加上图中的代码到窗口中,点击应用和重启按钮即可
(5)win+R,打开命令行,输入docker info,查看是否应用成功
2.安装tensorflow/serving服务
1.docker 拉取tensorflow/serving服务
安装tensorflow 2.6.0的GPU服务
docker pull tensorflow/serving:2.6.0-gpu
安装tensorflow 2.6.0的CPU服务
docker pull tensorflow/serving:2.6.0
2.查看是否拉取成功,其中,GPU版本比较大
docker images
3.准备模型测试
1.先拿官方例子测试一下,先下载一下tensorflow/serving2.6.0,然后在该目录结构下,找到 saved_model_half_plus_two_gpu例子,整体拷贝到想要放置的位置
2.开始发布一下该服务
(1)GPU版本,--gpus all 标注了下使用机器的所有GPU,我这边不加提示找不到GPU
注意:
下面的绝对路径表示模型存放的实际路径,最后一个参数项需要指定运行的容器和版本,里面的其他参数照猫画虎吧,很好理解,具体参数项也比较复杂
docker run --gpus all -t --rm -p 8501:8501 -v "C:/Users/lixia/.docker/tf_serving/saved_model_half_plus_two_gpu:/models/saved_model_half_plus_two_gpu" -e MODEL_NAME=saved_model_half_plus_two_gpu tensorflow/serving:2.6.0-gpu
出现了如下图,则表示发布成功
此时,在Docker Desktop中可以看到该服务信息
此时,浏览器访问localhost:8501,看是否能连通
http://localhost:8501/v1/models/saved_model_half_plus_two_gpu
出现该信息,则表示可以正常连通和访问了
3.测试调用一下该服务,是否能正常返回结果
#调用官方例子 线性回归小例子 y=0.5*x+2.0
import requests
import json
url='http://localhost:8501/v1/models/saved_model_half_plus_two_gpu:predict'
pdata = {"instances":[1.0, 2.0, 3.0]}
param = json.dumps(pdata)
res = requests.post(url, data= param)
print(res.text)
出现该结果表示部署成功
4.服务停止
(1)去Docker Desktop界面端中,手动终止,上面有图
(2)命令行的形式停止
查看运行中的服务
docker ps
终止服务 ****表示ID
docker stop ******
4.准备自己的模型部署测试
准备一个部署练习代码:是否佩戴口罩检测(YOLOv5)
1.首先需要有一个训练好的模型文件,如下图,是我训练好的一个模型
2.将.h5模型转换为.pb模型
直接使用TF自带的函数转(tf.keras.models.save_model),我的模型初始化+参数加载都在yolo.YOLO()中完成了
import tensorflow as tf
import yolo
def export_serving_model(path,version=1):
"""
导出标准的模型格式
:param path:
:return:
"""
#路径+模型名字+版本
export_path = './yolov5_mask_detection/1'
#调用模型,指定训练好的.h5文件
model = yolo.YOLO()
#导出模型
tf.keras.models.save_model(
model.yolo_model,
export_path,
overwrite=True,
include_optimizer=True,
save_format=None,
signatures=None,
options=None
)
运行完后,会生产出下面文件结构的模型.pb文件,直接拷贝上上级整体目录结构即可yolov5_mask_detection
3.将pb模型发布服务
(1)我直接拷贝到D盘根目录
(2)发布GPU服务
docker run --gpus all -t --rm -p 8501:8501 -v "D:/yolov5_mask_detection:/models/yolov5_mask_detection" -e MODEL_NAME=yolov5_mask_detection tensorflow/serving:2.6.0-gpu
(3)发布CPU服务
直接发布即可,发现GPU模型直接可以在CPU使用
docker run -t --rm -p 8501:8501 -v "D:/yolov5_mask_detection:/models/yolov5_mask_detection" -e MODEL_NAME=yolov5_mask_detection tensorflow/serving:2.6.0
出现如下,表示发布成功
4.调用模型
(1)新建一个裸的python环境,最好和tf用的版本一致,保不齐会出现问题啥的,如果缺少requests 、numpy、PIL库,pip install安装即可;
(2)调用代码前,如果不知道输入输出是啥,需要看下
进行conda环境,激活tf虚拟环境,输入命令查看
#打开anaconda命令行输入
conda activate tensorflow-gpu
#产看模型的输入输出和网络结构,绝对路径表示模型存放路径
saved_model_cli show --dir D:\yolov5_mask_detection\1 --all
输出参数包含三个,yolo_eval_1表示概率值;yolo_eval_2表示标签值;yolo_eval表示目标检测框
(3)调用代码,核心代码和上述官方例子一致,只不过加了些影像读取+预处理代码
代码如下:
import json
import time
import requests
import numpy as np
from PIL import Image
#---------------------------------------------------#
# 对输入图像进行resize,模型训练过程也采用了同样的方法
#---------------------------------------------------#
def resize_image(image, size, letterbox_image):
iw, ih = image.size
w, h = size
if letterbox_image:
scale = min(w/iw, h/ih)
nw = int(iw*scale)
nh = int(ih*scale)
image = image.resize((nw,nh), Image.BICUBIC)
new_image = Image.new('RGB', size, (128,128,128))
new_image.paste(image, ((w-nw)//2, (h-nh)//2))
else:
new_image = image.resize((w, h), Image.BICUBIC)
return new_image
#---------------------------------------------------#
# 对输入图像进行归一化,模型训练过程也采用了同样的方法
#---------------------------------------------------#
def preprocess_input(image):
image /= 255.0
return image
#服务网址
url = 'http://localhost:8501/v1/models/yolov5_mask_detection:predict'
#计时器
tt1 = time.time()
#输入的影像路径
image = Image.open("1.jpg")
#影像需要重采样成640*640
image_data = resize_image(image, (640, 640), True)
#维度扩展,和模型训练保持一致
image_data = np.expand_dims(preprocess_input(np.array(image_data, dtype='float32')), 0)
#原始影像大小,主要是为了将描框放缩到初始影像大小时用到的参数
input_image_shape = np.expand_dims(np.array([image.size[1], image.size[0]], dtype='float32'), 0)
#构造输入的参数类型,有两个参数,第一个表示影像数据1*640*640*3,第二个表示初始影像宽高
data = json.dumps({
"signature_name": "serving_default",
"inputs":
{"input_1": image_data.tolist(), "input_2": input_image_shape.tolist()}
})
#构造headers
headers = {"content-type":"application/json"}
#发送请求
r = requests.post(url, data=data, headers=headers)
#计时器终止
tt2 = time.time()
print(tt2-tt1)
#打印返回的结果,这里表示所有框的位置
print(r.text)
直接右键运行,得到结果,表示该程序检测出了9个目标,概率值+标签+目标框像素位置如下,通过解析json,可以得到目标检测结果
(4)我们看下,将检测结果标记到图上后,效果如下:
换个图片试一下
5.将docker环境整体打包到其他电脑测试(待续...)
有空了试试
6.一些备忘记录
1.conda 环境整体打包移植
//----------------------------------------------------------------------------------------------------------
conda 环境打包到其他电脑
要将 Conda 环境打包并迁移到其他电脑上使用,可以按照以下步骤进行操作:
导出 Conda 环境: 在源电脑上使用以下命令导出 Conda 环境的配置信息到一个 YAML 文件中:
conda env export > environment.yml
复制环境文件: 将生成的 environment.yml 文件复制到目标电脑上。
创建 Conda 环境: 在目标电脑上使用以下命令根据导出的环境文件创建相同的 Conda 环境:
conda env create -f environment.yml
激活环境: 激活新创建的 Conda 环境:
conda activate <environment_name>