美文网首页
利用gunicorn+flask将MXNet深度学习模型服务化

利用gunicorn+flask将MXNet深度学习模型服务化

作者: zbharper | 来源:发表于2020-04-17 16:58 被阅读0次

利用mxnet完成深度学习模型的训练后,需要考虑如何将推理模型应用到实际工程中。比较常见的方式是将模型部署为RESTful服务,有几个好处:
1)模型服务与业务解耦。模型服务的更改或升级不影响业务代码。
2)接口标准统一,客户端可跨平台调用,不需要依赖额外的库或环境,只需要支持http协议通信即可。
3)利用反向代理与负载均衡,模型服务可以方便的横向扩展,提高处理能力。

下面将一个图像分类器,采用flask、flask_restful模块编写服务代码,并使用gunicorn启动服务。并将服务纳入supervisor管理。

代码目录结构:

wdpredictor
    |----__init__.py
    |---- model/          # 模型文件目录
    |---- wdplib/         # 预测模型代码 
         |---- __init__.py
         |---- predictor.py    # 分类器对象
    |---- flask_resource.py   # flask服务对象
    |---- server.py     # 服务启动入口
    |---- run.sh

已知通过predictor.InitImagePredictor()可以构建一个图像分类器,resource.py 中编写flask服务对象,并编写server.py 程序入口

flask服务对象

flask_resource.py:

import sys
import logging
import traceback
import time
import json
import os
import base64

from flask import request
from flask_restful import Resource

class ImagePrediction(Resource):
    def __init__(self, predictor):
        self.predict_type = "image"  # 模型类型:图像推理
        self.predictor = predictor     # 模型实例需要在资源外初始化,避免每次服务重新实例化浪费时间

    def post(self):
        logging.info("get post requests! from %s" %(request.url))
        if not request.json:
            logging.error("Invalid format of received body!")
            return {}
        else:
            req = self.decode(request.json) 
            score, category = self.predictor.process(req.get("data"))  #调用模型推理,得到预测结果
            response = {
                "id": request.json.get('id'),
                "results": {
                        "score": score,            # 评分
                        "category": category,   # 类型
                },
            }
            return response

    def decode(self, meta):
        meta['data'] = base64.b64decode(meta['data'])
        return meta

服务入口

server.py

import sys
import logging
import traceback
import os

from flask import Flask
from flask_restful import Api

from wdpredictor import wdplib
from wdpredictor import flask_resource

app = Flask(__name__)
api = Api(app)

image_predictor = wdplib.InitImagePredictor()   #初始化,加载mxnet,绑定模型

api.add_resource(flask_resource.ImageRemotePrediction, '/image', resource_class_args=(image_predictor, ))

if __name__ == '__main__':
    print ("run from local")
    app.run('0.0.0.0', debug=True)

启动gunicorn

编写run.sh,将环境配置与启动命令脚本化

#!/bin/bash
proj_base_path=$(cd $(dirname $BASH_SOURCE);pwd)

export WDPREDICTOR_BASE="$proj_base_path"
export PYTHONPATH="$proj_base_path:$PYTHONPATH"
export MXNET_CUDNN_AUTOTUNE_DEFAULT=0
gunicorn -w 2 -b 0.0.0.0:9000 wdpredictor.server:app
bash run.sh

supervisor管理

编写image_server.supervisor.conf

[program:image_server]
directory = /app/wdpredictor ; 程序的启动目录
command = bash run.sh  ; 启动命令
autostart = true     ; 在 supervisord 启动的时候也自动启动
startsecs = 5        ; 启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true   ; 程序异常退出后自动重启
startretries = 3     ; 启动失败自动重试次数,默认是 3
user = deepctrl
redirect_stderr = true  ; 把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 50MB  ; stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20     ; stdout 日志文件备份数
; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile = /tmp/image_server.log
killasgroup = true
stopasgroup = true

将image_server.supervisor.conf 拷贝到/etc/supervisor/conf.d目录中,重启supervisor服务

sudo supervisorctl reread
sudo supervisorctl reload

相关文章

网友评论

      本文标题:利用gunicorn+flask将MXNet深度学习模型服务化

      本文链接:https://www.haomeiwen.com/subject/qgdyvhtx.html