-
如何将模型从pytorch形式转换成其他后端形式,准备工作
-
安装目标后端。
-
安装目标代码库。
-
-
使用方法
-
python ./tools/deploy.py \ ${DEPLOY_CFG_PATH} \ ${MODEL_CFG_PATH} \ ${MODEL_CHECKPOINT_PATH} \ ${INPUT_IMG} \ --test-img ${TEST_IMG} \ --work-dir ${WORK_DIR} \ --calib-dataset-cfg ${CALIB_DATA_CFG} \ --device ${DEVICE} \ --log-level INFO \ --show \ --dump-info
-
-
参数描述
-
-
deploy_cfg
: mmdeploy 针对此模型的部署配置,包含推理框架类型、是否量化、输入 shape 是否动态等。 -
model_cfg
: mm 算法库的模型配置,例如mmpretrain/configs/vision_transformer/vit-base-p32_ft-64xb64_in1k-384.py
,与 mmdeploy 的路径无关。 -
checkpoint
: torch 模型路径。可以 http/https 开头,详见mmcv.FileClient
的实现。 -
img
: 模型转换时,用做测试的图像或点云文件路径。 -
--test-img
: 用于测试模型的图像文件路径。默认设置成None
。 -
--work-dir
: 工作目录,用来保存日志和模型文件。 -
--calib-dataset-cfg
: 此参数只有int8模式下生效,用于校准数据集配置文件。若在int8模式下未传入参数,则会自动使用模型配置文件中的’val’数据集进行校准。 -
--device
: 用于模型转换的设备。 默认是cpu
,对于 trt 可使用cuda:0
这种形式。 -
--log-level
: 设置日记的等级,选项包括'CRITICAL', 'FATAL', 'ERROR', 'WARN', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'
。 默认是INFO
。 -
--show
: 是否显示检测的结果。 -
--dump-info
: 是否输出 SDK 信息。
-
-
-
如何查找pytorch模型对应的部署配置文件
-
在
configs/
文件夹中找到模型对应的代码库文件夹。 -
根据模型的任务类型在
configs/codebase_folder/
下查找对应的文件夹。 -
在
configs/codebase_folder/task_folder/
下找到模型的部署配置文件。 -
## 示例 python ./tools/deploy.py \ configs/mmdet/detection/detection_tensorrt_dynamic-320x320-1344x1344.py \ $PATH_TO_MMDET/configs/yolo/yolov3_d53_8xb8-ms-608-273e_coco.py \ $PATH_TO_MMDET/checkpoints/yolo/yolov3_d53_mstrain-608_273e_coco_20210518_115020-a2c3acb8.pth \ $PATH_TO_MMDET/demo/demo.jpg \ --work-dir work_dir \ --show \ --device cuda:0
-
-
ONNX 配置描述了如何将PyTorch模型转换为ONNX模型。ONNX配置参数说明
-
-
type
: 配置类型。 默认为onnx
。 -
export_params
: 如果指定,将导出模型所有参数。如果您只想导出未训练模型将此项设置为 False。 -
keep_initializers_as_inputs
: 如果为 True,则所有初始化器(通常对应为参数)也将作为输入导出,添加到计算图中。 如果为 False,则初始化器不会作为输入导出,不添加到计算图中,仅将非参数输入添加到计算图中。 -
opset_version
: ONNX的算子集版本,默认为11。 -
save_file
: 输出ONNX模型文件。 -
input_names
: 模型计算图中输入节点的名称。 -
output_names
: 模型计算图中输出节点的名称。 -
input_shape
: 模型输入张量的高度和宽度。
-
-
onnx_config = dict( type='onnx', export_params=True, keep_initializers_as_inputs=False, opset_version=11, save_file='end2end.onnx', input_names=['input'], output_names=['output'], input_shape=None)
-
-
如果模型要求动态尺寸的输入和输出,您需要在ONNX配置中加入dynamic_axes配置。
dynamic_axes
: 描述输入和输出的维度信息。-
dynamic_axes={ 'input': { 0: 'batch', 2: 'height', 3: 'width' }, 'dets': { 0: 'batch', 1: 'num_dets', }, 'labels': { 0: 'batch', 1: 'num_dets', }, }
-
-
代码库配置参数说明:
type
: OpenMMLab 系列模型代码库的简称, 包括mmpretrain
,mmdet
,mmseg
,mmocr
,mmagic
。task
: OpenMMLab 系列模型任务类型, 具体请参考 OpenMMLab 系列模型任务列表。-
codebase_config = dict(type='mmpretrain', task='Classification')
-
-
推理框架配置主要用于指定模型运行在哪个推理框架,并提供模型在推理框架运行时所需的信息,具体参考 ONNX Runtime, TensorRT, ncnn, PPLNN。
type
: 模型推理框架, 包括onnxruntime
,ncnn
,pplnn
,tensorrt
,openvino
。-
backend_config = dict( type='tensorrt', common_config=dict( fp16_mode=False, max_workspace_size=1 << 30), model_inputs=[ dict( input_shapes=dict( input=dict( min_shape=[1, 3, 512, 1024], opt_shape=[1, 3, 1024, 2048], max_shape=[1, 3, 2048, 2048]))) ])
-
-
部署配置完整示例
-
codebase_config = dict(type='mmpretrain', task='Classification') backend_config = dict( type='tensorrt', common_config=dict( fp16_mode=False, max_workspace_size=1 << 30), model_inputs=[ dict( input_shapes=dict( input=dict( min_shape=[1, 3, 224, 224], opt_shape=[4, 3, 224, 224], max_shape=[64, 3, 224, 224])))]) onnx_config = dict( type='onnx', dynamic_axes={ 'input': { 0: 'batch', 2: 'height', 3: 'width' }, 'output': { 0: 'batch' } }, export_params=True, keep_initializers_as_inputs=False, opset_version=11, save_file='end2end.onnx', input_names=['input'], output_names=['output'], input_shape=[224, 224])
-
-
模型转换结束后,MMDeploy 提供了
tools/test.py
做为单测工具。需要参照 安装说明 完成依赖安装 ,按照 转换说明 转出模型。-
python tools/test.py \ ${DEPLOY_CFG} \ ${MODEL_CFG} \ --model ${BACKEND_MODEL_FILES} \ [--speed-test] \ [--warmup ${WARM_UP}] \ [--log-interval ${LOG_INTERVERL}] \ [--log2file ${LOG_RESULT_TO_FILE}]
-
-
参数详解
-
参数 备注 deploy_cfg 部署配置文件 deploy_cfg codebase 中的模型配置文件 log2file 保存日志和运行文件的路径 speed-test 是否做速度测试 warm-up 执行前是否 warm-up log-interval 日志打印间隔
-
-
执行模型推理(举例)
-
python tools/test.py \ configs/mmpretrain/classification_onnxruntime_static.py \ {MMPRETRAIN_DIR}/configs/resnet/resnet50_b32x8_imagenet.py \ --model model.onnx \ --out out.pkl \ --device cuda:0 ## profile 速度测试 python tools/test.py \ configs/mmpretrain/classification_onnxruntime_static.py \ {MMPRETRAIN_DIR}/configs/resnet/resnet50_b32x8_imagenet.py \ --model model.onnx \ --speed-test \ --device cpu
-
-
为什么要量化,相对于 fp32 模型,定点模型有诸多优点:
-
-
体积更小,8-bit 模型可降低 75% 文件大小
-
由于模型变小,Cache 命中率提升,速度更快
-
芯片往往有对应的定点加速指令,这些指令更快、能耗更低(常见 CPU 上 int8 大约只需要 10% 能量)
-
-
安装包体积、发热都是移动端评价 APP 的关键指标;而在服务端,“加速”意味着可以维持相同 QPS、增大模型换取精度提升。
-
-
mmdeploy 离线量化方案,mmdeploy 基于静态图(onnx)生成推理框架所需的量化表,再用后端工具把浮点模型转为定点。目前 mmdeploy 支持 ncnn PTQ。
-
模型怎么转定点,mmdeploy 安装完成后,加载 ppq 并安装
-
git clone https://github.com/openppl-public/ppq.git cd ppq pip install -r requirements.txt python3 setup.py install
-
回到 mmdeploy, 使用
tools/deploy.py --quant
选项开启量化。 -
cd /path/to/mmdeploy export MODEL_CONFIG=/path/to/mmpretrain/configs/resnet/resnet18_8xb16_cifar10.py export MODEL_PATH=https://download.openmmlab.com/mmclassification/v0/resnet/resnet18_b16x8_cifar10_20210528-bd6371c8.pth # 找一些 imagenet 样例图 git clone https://github.com/nihui/imagenet-sample-images --depth=1 # 量化模型 python3 tools/deploy.py configs/mmpretrain/classification_ncnn-int8_static.py ${MODEL_CONFIG} ${MODEL_PATH} /path/to/self-test.png --work-dir work_dir --device cpu --quant --quant-image-dir /path/to/imagenet-sample-images ...
-
–quant:是否开启量化,默认为 False
-
–quant-image-dir:校准数据集,默认使用 MODEL_CONFIG 中的验证集
-
-
-
把 OpenMMLab 模型转 onnx 格式。
-
python tools/torch2onnx.py \ ${DEPLOY_CFG} \ ${MODEL_CFG} \ ${CHECKPOINT} \ ${INPUT_IMG} \ --work-dir ${WORK_DIR} \ --device cpu \ --log-level INFO
-
参数说明
-
-
deploy_cfg
: The path of the deploy config file in MMDeploy codebase. -
model_cfg
: The path of model config file in OpenMMLab codebase. -
checkpoint
: The path of the model checkpoint file. -
img
: The path of the image file used to convert the model. -
--work-dir
: Directory to save output ONNX models Default is./work-dir
. -
--device
: The device used for conversion. If not specified, it will be set tocpu
. -
--log-level
: To set log level which in'CRITICAL', 'FATAL', 'ERROR', 'WARN', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'
. If not specified, it will be set toINFO
.
-
-
-
-
MMDETECTION 模型部署
-
安装 mmdet
-
安装 mmdeploy
-
-
模型转换
-
你可以使用 tools/deploy.py 把 mmdet 模型一键式转换为推理后端模型。
-
cd mmdeploy # download faster r-cnn model from mmdet model zoo mim download mmdet --config faster-rcnn_r50_fpn_1x_coco --dest . # convert mmdet model to onnxruntime model with dynamic shape python tools/deploy.py \ configs/mmdet/detection/detection_onnxruntime_dynamic.py \ faster-rcnn_r50_fpn_1x_coco.py \ faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth \ demo/resources/det.jpg \ --work-dir mmdeploy_models/mmdet/ort \ --device cpu \ --show \ --dump-info
-
{task}:mmdet 任务有2种:物体检测(detection)、实例分割(instance-seg)。例如,
RetinaNet
、Faster R-CNN
、DETR
等属于前者。Mask R-CNN
、SOLO
等属于后者。请务必使用detection/detection_*.py
转换检测模型,使用instance-seg/instance-seg_*.py
转换实例分割模型。 -
{backend}: 推理后端名称。比如,onnxruntime、tensorrt、pplnn、ncnn、openvino、coreml 等等
-
{precision}: 推理精度。比如,fp16、int8。不填表示 fp32
-
{static | dynamic}: 动态、静态 shape
-
{shape}: 模型输入的 shape 或者 shape 范围
-
-
在使用转换后的模型进行推理之前,有必要了解转换结果的结构。 它存放在
--work-dir
指定的路路径下。-
mmdeploy_models/mmdet/ort ├── deploy.json ├── detail.json ├── end2end.onnx └── pipeline.json
-
-
end2end.onnx: 推理引擎文件。可用 ONNX Runtime 推理
-
*.json: mmdeploy SDK 推理所需的 meta 信息
-
-
整个文件夹被定义为mmdeploy SDK model。换言之,mmdeploy SDK model既包括推理引擎,也包括推理 meta 信息。
-
-
以上述模型转换后的
end2end.onnx
为例,可以使用如下代码进行推理:-
from mmdeploy.apis.utils import build_task_processor from mmdeploy.utils import get_input_shape, load_config import torch deploy_cfg = 'configs/mmdet/detection/detection_onnxruntime_dynamic.py' model_cfg = './faster-rcnn_r50_fpn_1x_coco.py' device = 'cpu' backend_model = ['./mmdeploy_models/mmdet/ort/end2end.onnx'] image = './demo/resources/det.jpg' # read deploy_cfg and model_cfg deploy_cfg, model_cfg = load_config(deploy_cfg, model_cfg) # build task and backend model task_processor = build_task_processor(model_cfg, deploy_cfg, device) model = task_processor.build_backend_model(backend_model) # process input image input_shape = get_input_shape(deploy_cfg) model_inputs, _ = task_processor.create_input(image, input_shape) # do model inference with torch.no_grad(): result = model.test_step(model_inputs) # visualize results task_processor.visualize( image=image, model=model, result=result[0], window_name='visualize', output_file='output_detection.png')
-
-
MMPOSE 模型部署
-
安装 mmpose 安装 — MMPose 1.0.0 文档
-
安装 mmdeploy
-
-
模型转换
-
可以使用 tools/deploy.py 把 mmpose 模型一键式转换为推理后端模型。以下,我们将演示如何把
hrnet
转换为 onnx 模型。 -
cd mmdeploy # download hrnet model from mmpose model zoo mim download mmpose --config td-hm_hrnet-w32_8xb64-210e_coco-256x192 --dest . # convert mmdet model to onnxruntime model with static shape python tools/deploy.py \ configs/mmpose/pose-detection_onnxruntime_static.py \ td-hm_hrnet-w32_8xb64-210e_coco-256x192.py \ hrnet_w32_coco_256x192-c78dce93_20200708.pth \ demo/resources/human-pose.jpg \ --work-dir mmdeploy_models/mmpose/ort \ --device cpu \ --show
-
转换的关键之一是使用正确的配置文件。项目中已内置了各后端部署配置文件。 文件的命名模式是:
-
pose-detection_{backend}-{precision}_{static | dynamic}_{shape}.py
-
-
{backend}: 推理后端名称。比如,onnxruntime、tensorrt、pplnn、ncnn、openvino、coreml 等等
-
{precision}: 推理精度。比如,fp16、int8。不填表示 fp32
-
{static | dynamic}: 动态、静态 shape
-
{shape}: 模型输入的 shape 或者 shape 范围
-
-
-
模型规范
-
在使用转换后的模型进行推理之前,有必要了解转换结果的结构。 它存放在
--work-dir
指定的路路径下。上例中的mmdeploy_models/mmpose/ort
,结构如下: -
mmdeploy_models/mmpose/ort ├── deploy.json ├── detail.json ├── end2end.onnx └── pipeline.json
-
-
模型推理
-
以上述模型转换后的
end2end.onnx
为例,你可以使用如下代码进行推理: -
from mmdeploy.apis.utils import build_task_processor from mmdeploy.utils import get_input_shape, load_config import torch deploy_cfg = 'configs/mmpose/pose-detection_onnxruntime_static.py' model_cfg = 'td-hm_hrnet-w32_8xb64-210e_coco-256x192.py' device = 'cpu' backend_model = ['./mmdeploy_models/mmpose/ort/end2end.onnx'] image = './demo/resources/human-pose.jpg' # read deploy_cfg and model_cfg deploy_cfg, model_cfg = load_config(deploy_cfg, model_cfg) # build task and backend model task_processor = build_task_processor(model_cfg, deploy_cfg, device) model = task_processor.build_backend_model(backend_model) # process input image input_shape = get_input_shape(deploy_cfg) model_inputs, _ = task_processor.create_input(image, input_shape) # do model inference with torch.no_grad(): result = model.test_step(model_inputs) # visualize results task_processor.visualize( image=image, model=model, result=result[0], window_name='visualize', output_file='output_pose.png')
-