Mxnet 框架 Insightface( MMS)模型部署教程

一、Docker 镜像准备

直接pull mms images

cpu版本:

docker pull awsdeeplearningteam/multi-model-server

gpu版本:

拉取官方项目

git clone https://github.com/awslabs/multi-model-server.git

拉起官方镜像:

docker pull awsdeeplearningteam/mxnet-model-server:1.0.0-mxnet-gpu

自定义gpu版本:

修改Dockerfile.gpu内容

vim Dockerfile.gpu

以cuda10.2为例

FROM nvidia/cuda:10.2-cudnn8-runtime-ubuntu18.04

ENV PYTHONUNBUFFERED TRUE

RUN apt-get update && apt-get install sudo
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
    fakeroot \
    ca-certificates \
    dpkg-dev \
    g++ \
    python3-dev \
    openjdk-8-jdk-headless \
    libglib2.0-dev \
    libgl1-mesa-dev
    libxrender1 \
    libgl1-mesa-glx \
    libxext-dev \
    curl \
    vim \
    && rm -rf /var/lib/apt/lists/* \
    && cd /tmp \
    && curl -O https://bootstrap.pypa.io/get-pip.py \
    && python3 get-pip.py


RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1
RUN update-alternatives --install /usr/local/bin/pip pip /usr/local/bin/pip3 1
RUN pip install--no-cache-dir -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com numpy==1.16.1 insightface mtcnn scipy==1.2.2 matplotlib pillow uwsgi opencv-python django keras==2.2.4 jupyterlab
RUN pip install --no-cache-dir -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com multi-model-server \
    && pip install --no-cache-dir -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com mxnet-cu102mkl

RUN useradd -m model-server \
    && mkdir -p /home/model-server/tmp

COPY dockerd-entrypoint.sh /usr/local/bin/dockerd-entrypoint.sh
COPY config.properties /home/model-server

RUN chmod +x /usr/local/bin/dockerd-entrypoint.sh \
    && chown -R model-server /home/model-server

EXPOSE 8080 8081
RUN usermod -a -G sudo model-server
USER model-server
WORKDIR /home/model-server
ENV TEMP=/home/model-server/tmp
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh"]
CMD ["serve"]

LABEL maintainer="[email protected]"

生成GPU镜像

docker build -f Dockerfile.gpu -t mms1-gpu .

也可以直接使用本人创的镜像 !!!!!

dockhub:

docker push lian01110/mms_mxnet_cu102:1.0

阿里云镜像仓库:

docker pull registry.cn-hangzhou.aliyuncs.com/docker_yangjian/mms_mxnet_cuda102:1.0

二、模型转化为mar文件

本地(如windos)或者服务器(linux)里新建文件夹insightface_deploy,把所有文件都放入此目录中

  1. 模型结构文件: insightface-symbol.json # 模型文件也可以放到其他文件夹下,在mxnet_model_service.py中需要修改def initialize() 的checkpoint_prefix

  2. 模型权重文件: insightface-0000.params # 跟模型结构文件放在一起

  3. 模型签名文件: 定义API的输入输出signature.json,非必须,看需求

  4. 模型label信息(可选): sysnet.txt,记录各个分类的名字,如果模型不是分类模型,这个文件不必要

  5. 处理程序代码文件: 模型前处理与后处理

signature.json文件内容:

{
  "inputs": [
    {
      "data_name": "data",
      "data_shape": [
        0,
        3,
        112,
        112
      ]
    }
  ]
}

其中"data" 为Body的KEY,图片形状为[0,3,112,112] 其实代表的是[1,3,112,112],这里我们只需要填写输入内容即可

如果不懂输入输出,可新建一个文件test_out_put.py,内容如下

import* mxnet *as* mx

model = 'insightface'
model_path = "insightface_model"
input_shape = (1, 3, 112, 112)
# 加载模型
load_symbol, args, auxs = mx.model.load_checkpoint(model_path, 0)
mod = mx.mod.Module(load_symbol, label_names=None, data_names=['data'], context=mx.cpu())
mod.bind(data_shapes=[('data', input_shape)])
print(mod.data_names)
print(mod.data_shapes)
print(mod.output_names)
print(mod.output_shapes)
['data']
[DataDesc[data,(1, 3, 112, 112),,NCHW]]
['fc1_output']
[('fc1_output', (1, 512))]

custom service class

mms支持自己写一个服务的代码,这个代码可以进行图片的预处理和模型返回结果后的后处理,相当于写了一个小型web服务,mms在启动的时候,会找到里面写好的一个handle,调用相应的类来处理模型的输入输出。

我们直接用官方的模板https://github.com/awslabs/multi-model-server/tree/master/examples/model_service_template的所有内容

文件夹mxnet_utils: 里面有一些图片处理文件image.py ndarray.py nlp.py

gluon_base_service.py

model_handler.py : 读取data跟模型进行推导过程文件

mxnet_model_service.py

mxnet_vison_batching.py

mxnet_vision_service.py :最后执行文件,包括子类的前处理与后处理,后处理根据自己需求修改,我的修改如下:

!!!如果有有中文注释 ,也要在文件首行输入: # -*- coding: UTF-8 -*-

# 导入numpy
import numpy as np

# 在后处理函数修改
    def postprocess(self, data):
        这里data是2维
        # return [d.asnumpy().tolist() for d in data]
        emb =data[0].asnumpy()   
        norm =np.sqrt(np.sum(emb*emb)+0.00001)
        emb /=norm  #归一化
        return emb.tolist()   # 返回文件不支持numpy格式,需转为list
    

根据需求更改mxnet_model_service.py,这里只有一个输出并不需要需改,如果需要更改输出层:

 # todo  Load MXNet module 加载模型
        self.mxnet_ctx = mx.cpu() if gpu_id is None else mx.gpu(gpu_id)
        sym, arg_params, aux_params = mx.model.load_checkpoint(checkpoint_prefix, self.epoch)
        
        # 如果要改变输出层
        # all_layers = sym.get_internals() # 获得所有层
        # output_layers = sym.output_names() # 获得输出层名字 在外查看用,不需要执行此行,见test_out_put.py
        # output_layer = all_layers[layer + '_output']  # 指定输出层 ,layer为输出层前缀,见test_out_put.py
        # model = mx.mod.Module(symbol=output_layer, context=ctx, label_names=None) 

        # noinspection PyTypeChecker 
        self.mx_model = mx.mod.Module(symbol=sym, context=self.mxnet_ctx, data_names=data_names, label_names=None)
        self.mx_model.bind(for_training=False, data_shapes=data_shapes)
        self.mx_model.set_params(arg_params, aux_params, allow_missing=True, allow_extra=True)

整个文件夹结构如下:

insightface_deploy
├── mxnet_utils
│   ├── image.py
│   ├── __init__.py
│   ├── ndarray.py
│   └── nlp.py
├── models
│   ├── retinaface_mnet025_v1
│      ├── mnet.caffemodel
│      ├── mnet.prototxt
├── insightface-0000.params
├── insightface-symbol.json
├── gluon_base_service.py
├── model_handler.py
├── mxnet_model_service.py
├── mxnet_vision_batching.py
├── mxnet_vision_service.py
├── signature.json

压缩出mar文件

mms只需一个mar文件即可构建服务,这个mar文件就是上面这些文件的结合,现在使用mms的“model-archiver”来压缩它们。首先安装“model-archiver”:

pip install model-archiver

cd 到 arcface文件下,终端运行以下命令:

model-archiver --model-name insightface --model-path ./ --handler mxnet_vision_service:handle

参数解释:

  • model-name:模型的名字,即模型文件的前缀,这里为insightface也表示压缩后的mar文件的名字为insightface.mar, <<会把所有文件都压缩到mar中>>

  • model-path:存所有文件的文件夹路径,这里直接在insightface_deploy文件夹下,故只需"./"。

  • handler:自定义服务的handle,“mxnet_version_service:handle”的意思是使用“mxnet_version_service.py”文件里面的“handle”类来处理模型的输入输出。

最后得到一个以“insightface.mar”的文件。

多个模型:即最后的执行函数不同,生成多个mar文件, 所有文件都会按根目录方式进行解压. 即mxnet_veison_service等文件只能放根目录,不能放子目录.

三、 模型部署

为了更方便地部署模型,避免每次部署的时候都要写一大串命令,我们可以写一个配置文件来指定一些参数。新建一个名为“config.properties”的文件,复制以下内容:

vmargs=-Xmx128m -XX:-UseLargePages -XX:+UseG1GC -XX:MaxMetaspaceSize=32M -XX:MaxDirectMemorySize=10m -XX:+ExitOnOutOfMemoryError
model_store=/models/    # 这里为容器地址
load_models=ALL
inference_address=http://0.0.0.0:8080
management_address=http://0.0.0.0:8081
# management_address=unix:/tmp/management.sock
number_of_netty_threads=10
netty_client_threads=10
# default_response_timeout=120
# unregister_model_timeout=120
# default_workers_per_model=0
job_queue_size=100
# async_logging=false
number_of_gpu=1  # 使用gpu,如果是cpu,这里打上#,1为gpu个数,如果有2个:number_of_gpu=1
# cors_allowed_origin
# cors_allowed_methods
# cors_allowed_headers
# keystore=src/test/resources/keystore.p12
# keystore_pass=changeit
# keystore_type=PKCS12
# private_key_file=src/test/resources/key.pem
# certificate_file=src/test/resources/certs.pem
# blacklist_env_vars=
max_request_size=10000000   #默认为1M,修改为10M
vmargs=-Xms1024m -Xmx1024m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -Dio.netty.leakDetectionLevel=advanced -Xloggc:d:/gc.log -XX:MaxDirectMemorySize=30M -Dio.netty.allocator.pageSize=8192 -Dio.netty.allocator.maxOrder=10 -Dio.netty.recycler.maxCapacity=0 -Dio.netty.recycler.maxCapacity.default=0

参数说明
https://github.com/awslabs/multi-model-server/blob/master/docs/configuration.md#configure-mms-listening-port

JVM参数:

    vmargs=-Xmx128m:

    -XX:-UseLargePages 

    -XX:+UseG1GC 

    -XX:MaxMetaspaceSize=32M:设置metaspace(元空间)区域的最大值,如果不设置,默认的*capacity*until*GC为20M左右* ,此值会影响传入数据大小限制

    -XX:MaxDirectMemorySize=10m: java堆外内存的峰值,此值会影响传入数据大小限制

    -XX:+ExitOnOutOfMemoryError

- model-store:.mar模型存放的路径,注意这里是docker container里面的路径,一般都是“/models/”,不是本机模型的路径

- inference_address:模型监听的端口,即url要输入的端口

- number_of_gpu:使用的GPU数量,不是GPU序号,如写2为使用2张GPU,而且会使用前两张GPU,不能指定使用某张GPU。

max_request_size:最大post请求data数据大小,单位b(在传输大数据>1M,需要增加此项)

然后请把“config.properties”和“MODEL.mar”这两个文件放在服务器的同一个文件夹内,如“/tmp/arcmodel/”

2.部署

原始gpu-serving

docker run -itd --restart=on-failure:10 --runtime=nvidia --name mms1 -p 8061:8080  -p 8062:8081 -v \
/tmp/arcmodel/:/models \
awsdeeplearningteam/mxnet-model-server:1.0.0-mxnet-gpu \
mxnet-model-server --start --mms-config /models/config.properties \
--models arcface=arcface_model.mar

自定义gpu

docker run -itd --restart=on-failure:10 --runtime=nvidia --name mms_arcface_yj -p 8061:8080  -p 8062:8081 -v \
/tmp/mxnet_deploy/:/models \
mms-gpu \
multi-model-server --start --mms-config /models/config.properties --model-store /models \
--models arcface=arcface_model.mar

注意:如果映射到root里,有encode的问题,尝试了代码前加encoding utf-8 无效果

insightface:

docker run -itd --restart=on-failure:10 --gpus 1 --name mms_insightface_yj -p 8001:8080  -p 8066:8081 -v \
/tmp/insightface_ploy/:/models \
mms_insightface_yj:1.0 \
multi-model-server --start --mms-config /models/config.properties --model-store /models \
--models insightface=insightface.mar

参数解释:

--gpus 0 或者--runtime=nvidia:使用gpu

-v:把本机(服务器)存放.mar文件和config文件的文件夹(如:“/home/project_documents/Face_production/insightface_deploy/”,注意最后要加上"/")映射到容器内部的文件夹(如“/models”)。

mms_insightface_yj:1.0:pull下来的mms镜像名.

--name mms_insightface_yj : 给容器起名字,注意不能跟以有容器重名

-mxnet-model-server --start:启动mms (自定义改为multi-model-server --start)

--mms-config /models/config.properties:容器内部config.properties的路径。固定,不需要修改

--model-store 容器内的(.mar)文件路径

--models insightface=insightface.mar:选择要部署的模型,接口名=模型.mar名, 接口名自定义,url时需要输入

多模型部署

--models function1=function1.mar function2=function2

3.测试服务

cd到有测试图片文件下

curl -X POST http://192.168.46.230:8601/predictions/arcface -T kitten.jpg

可能会报curl: error while loading shared libraries: libssl.so.1.0.0错误.在本地windows电脑上输入即可

jerry@LAPTOP-0NITTTTQ MINGW64 /d/Ai/Facenet/ArcFace/insightface/mxnet_deploy/mms/insighface_dnn (master)
$ curl -X POST http://192.168.46.230:8601/predictions/arcface -T kitten.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  108k    0     0  100  108k      0  34656  0:00:03  0:00:03 --:--:-- 34656
{
    "code": 200,
    "message": "success",
    "datas": {
        "ismatch": true,
        "accept": 0.8,
        "score": 0.9497,
        "timeused": 107.86
    }

在potman运行:

你可能感兴趣的:(Mxnet 框架 Insightface( MMS)模型部署教程)