如何将模型从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 to cpu
.
--log-level
: To set log level which in 'CRITICAL', 'FATAL', 'ERROR', 'WARN', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'
. If not specified, it will be set to INFO
.
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')