通过 EasyDeploy 部署训练完成的 MMYOLO 模型 - 2023-03最新版

为什么需要工具来部署模型 ?
在模型训练阶段,我们经常会通过引入大量库,构建PyTorch、TensorFlow的学习环境,但是,真实生产环境下无法完成复杂的配置,保存庞大的模型。
现在比较有效的方式是把训练后的模型转换成描述网络结构的中间表示(比如ONNX),再部署到相应环境。

ONNX(英语:Open Neural Network Exchange)是一种针对机器学习所设计的开放式的文件格式,用于存储训练好的模型。它使得不同的人工智能框架(如Pytorch、MXNet)可以采用相同格式存储模型数据并交互。 ONNX的规范及代码主要由微软,亚马逊,Facebook和IBM等公司共同开发,以开放源代码的方式托管在Github上。目前官方支持加载ONNX模型并进行推理的深度学习框架有: Caffe2, PyTorch, MXNet,ML.NET,TensorRT 和 Microsoft CNTK,并且 TensorFlow 也非官方的支持ONNX。

部署步骤

  1. 进入安装好的conda虚拟环境

    1
    2
    3
    4
    5
    conda activate mmyolo
    pip install onnx
    pip install onnxruntime
    # 如果需要使用 simplify 功能需要安装
    pip install onnx-simplifier
  2. 训练完成的模型部署

    1
    2
    3
    4
    # 转到 MMYOLO 程序目录
    D:
    cd D:\yolo\202303-mmyolo
    python projects/easydeploy/tools/export.py configs/yolov5/yolov5_s-v61_fast_1xb12-40e_cat-202303.py work_dirs/yolov5_s-v61_fast_1xb12-40e_cat-202303/epoch_40.pth --work-dir work_dirs/yolov5_s-v61_fast_1xb12-40e_cat-202303 --img-size 640 640 --batch 1 --device cpu --simplify --opset 11 --backend 1 --pre-topk 1000 --keep-topk 100 --iou-threshold 0.65 --score-threshold 0.25

    转换后的模型存放于202303-mmyolo目录下的【work_dirs/yolov5_s-v61_fast_1xb12-40e_cat-202303\end2end.onnx】

  • 如果程序报错:ModuleNotFoundError: No module named ‘projects’
    可以在【projects/easydeploy/tools/export.py】的13行前加上以下代码
    1
    2
    3
    4
    5
    6
    # 添加如下两行
    import sys
    sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))

    # 13行原始代码
    from projects.easydeploy.model import DeployModel
  1. 验证转换后的onnx模型
    从网上寻找Free版权的猫片,进行验证。命令如下:
    1
    python projects/easydeploy/tools/image-demo.py data/cat/images/cat-test-202303.jpg configs/yolov5/yolov5_s-v61_fast_1xb12-40e_cat-202303.py work_dirs/yolov5_s-v61_fast_1xb12-40e_cat-202303/end2end.onnx --device cpu
    由于MMYOLO程序的pytorch版本有点旧,直接执行会报错误:AttributeError: module ‘torch’ has no attribute ‘asarray’
    可以修改 projects/easydeploy/tools/image-demo.py 来解决。
    1
    2
    3
    4
    5
    6
    # 修改前 100~104行
    pad_param = torch.asarray(
    [pad_param[2], pad_param[0], pad_param[2], pad_param[0]],
    device=args.device)
    scale_factor = samples.get('scale_factor', [1., 1])
    scale_factor = torch.asarray(scale_factor * 2, device=args.device)
    1
    2
    3
    4
    # 修改后
    pad_param = torch.from_numpy(np.array([pad_param[2], pad_param[0], pad_param[2], pad_param[0]]))
    scale_factor = samples.get('scale_factor', [1., 1])
    scale_factor = torch.from_numpy(np.array([scale_factor * 2]))

参考文档:https://mmyolo.readthedocs.io/zh_CN/latest/get_started/15_minutes_object_detection.html