Docker部署深度学习模型及微服务化

环境:

  • CentOS 7
  • Pytorch
  • Flask
  • Nvidia显卡

以人脸检测、人脸识别任务为例,使用Pytorch框架构建MTCNN人脸检测和FaceNet人脸识别网络,检测数据集使用wider face,识别数据集使用casia-maxpy-clean。
使用Flask进行算法接口封装,并使用docker打包成镜像进行快捷部署、容器化

一、宿主机

需安装GPU相关包和驱动,例如Nvidia GPU驱动、CUDA和cudnn;需安装Docker环境(一般使用社区版Docker-CE);

安装nvidia-container-toolkit,容器才能使用宿主机GPU

安装nvidia-container-toolkit,相应指令如下:

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo
sudo yum install -y nvidia-container-toolkit

然后,对宿主机docker服务进行重启

systemctl restart docker

二、Flask接口

封装算法模型的推理为一个接口,使用轻量级的Flask框架

app.py

import cv2
import json
import numpy as np
import time

from Facenet.facenet import Facenet
from MTCNN.core.detect import MtcnnDetector, create_mtcnn_net
from MTCNN.core.video_vision import plot_face
from flask import Flask, request, redirect
from PIL import Image

# 模型初始化
model = Facenet()
pnet, rnet, onet = create_mtcnn_net(p_model_path=r'./MTCNN/model/pnet_epoch.pt', r_model_path=r'./MTCNN/model/rnet_epoch.pt', o_model_path=r'./MTCNN/model/onet_epoch.pt', use_cuda=True)
mtcnn_detector = MtcnnDetector(pnet=pnet, rnet=rnet, onet=onet, min_face_size=24)

# 测试图
test_img = r"./012.jpg"
val_img = cv2.imread(test_img)
val_bbox, val_landmark = mtcnn_detector.detect_face(val_img)
val_img, val_crop = plot_face(val_bbox, val_landmark, val_img, color=(0, 0, 255))
val_crop = Image.fromarray(val_crop)

# numpy 序列化
class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)
    
@app.route('/')
def index():
    return "test"


@app.route('/detect', methods=['GET', 'POST'])
def detect():
    start_time = time.time()

    if request.method == 'POST':
        if 'file' not in request.files:
            return redirect(request.url)
        file = request.files.get('file')
        if not file:
            return
        img_bytes = file.read()
        image = cv2.imdecode(np.frombuffer(img_bytes, np.uint8), cv2.IMREAD_COLOR)
        bboxs, landmarks = mtcnn_detector.detect_face(image)
        img, crop = plot_face(bboxs, landmarks, image, color=(0, 0, 255))
        crop = Image.fromarray(crop)

        distance = model.detect_image(val_crop, crop)
        end_time = time.time()

        result = {}
        result['time'] = f'{end_time - start_time}s'
        result['distance'] = distance

    return json.dumps(result, cls=NumpyEncoder)


if __name__ == '__main__':
    app.run(host="0.0.0.0", debug=True, port=5000)

三、深度学习Docker环境构建

1.基础镜像

使用Pytorch官方提供的镜像,进入

https://hub.docker.com/r/pytorch/pytorch/tags?page=1&ordering=last_updated

选择符合宿主机版本的镜像

注意:pytorch镜像内环境是ubuntu内核

例:

docker pull pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime

此时,可以看到镜像仓库内拉下来了基础深度学习镜像,我们还需要使用Dockerfile来对我们的Flask及OpenCV环境封装一个更为完整的镜像。

2.Flask+Pytorch+OpenCV

将本地的Flask+算法模型相关代码放在宿主机某目录下,在该目录下编写Dockerfile

# 拉取Pytorch基础镜像
FROM pytorch/pytorch:1.9.0-cuda10.2-cudnn7-runtime

MAINTAINER luorunshu lrs0730@163.com
# 将算法模型代码加入容器的目录
ADD ./flask_face_detect /code
# 设置工作路径
WORKDIR /code

RUN apt-get update
# 安装OpenCV依赖
RUN apt-get install -y libsm6 libxext6 libgl1-mesa-glx libglib2.0-0
# 安装相应的代码所需包,使用豆瓣源
RUN pip install -r requirements.txt -i https://pypi.douban.com/simple
# 容器暴露端口5000
EXPOSE 5000

CMD ["python", "/code/app.py"]

编写好Dockerfile即可以开始构建新的算法镜像

sudo docker built -t luorunshu/flask-pytorch1.9-cuda10.2-cudnn7-runtime:latest .

等待构建完毕,使用相应的gpu指令运行docker

docker run --gpus=all -p 5000:5000 -itd luorunshu/flask-pytorch1.9-cuda10.2-cudnn7-runtime:latest

四、性能测试

使用POSTMAN进行测试,请求方式POST:

​ 宿主机的ip地址:5000/detect

Docker部署深度学习模型

使用gpu加速推理使算法速度加快了5倍(200+ms --> 48ms)

人脸图片输入:

Docker部署深度学习模型

测试图片:

Docker部署深度学习模型

返回值说明:

​ time算法推理时间

​ probability两张人脸之间的距离,越小代表两张人脸越相似