前言
本文主要分为两部分,分别为:
第一部分介绍了
HorNet
gf
\texttt{HorNet}_{\texttt{gf}}
HorNetgf模型转化为
HorNet
gf
-ONNX
\texttt{HorNet}_{\texttt{gf}}\texttt{-ONNX}
HorNetgf-ONNX模型过程中遇到的问题以及解决办法。
第二部分介绍了通过OpenMMLab发布的MMdeploy工具,实现将
HorNet
gf
\texttt{HorNet}_{\texttt{gf}}
HorNetgf模型转化为
HorNet
gf
-ONNX
\texttt{HorNet}_{\texttt{gf}}\texttt{-ONNX}
HorNetgf-ONNX模型的过程。
注意:
1.只是针对 HorNet gf \texttt{HorNet}_{\texttt{gf}} HorNetgf模型, HorNet 7 × 7 \texttt{HorNet}_{7\times7} HorNet7×7可以通过mmcv自带的torch2onnx.py文件直接进行转化。当然MMdeploy也是可以的。
2.MMdeploy只针对MMCV框架下训练的模型进行部署。
参考资料:
1.MMdeploy官方GitHub
2.我对于HorNet的总结博客:Segmentation:HorNet 学习总结
1. 转换过程中的问题
在 HorNet gf \texttt{HorNet}_{\texttt{gf}} HorNetgf转换的过程中主要是三个问题:
- HorNet gf \texttt{HorNet}_{\texttt{gf}} HorNetgf中Global Filter模块中 torch.fft.rfft2和 torch.fft.irfft2这两个函数在ONNX中没有支持的算子。
- MMCV函数包中无法有效支持,除GlobalAveragePool(1)以外,其他尺度的GlobalAveragePool(n) n=2,3,4…。
- ONNX不支持使用Python算子CheckpointFunction。
1.1 operator fft_rfft2 to ONNX opset version 15 is not supported
RuntimeError: Exporting the operator fft_rfft2 to ONNX opset version 15 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub.
原因分析:更新到ONNX最新版本都发现无法支持 fft_rfft2和fft_irfft2的算子。因此,采用numpy库来替换 fft_rfft2和fft_irfft2的算子。经过测试,输出结果和torch的fft_rfft2和fft_irfft2的算子基本相同(极小的小数位差异。),并且可以转化成功。
解决方法:
# x2 = torch.fft.rfft2(x2, dim=(2, 3), norm='ortho')
x2 = x2.detach().cpu().numpy()
x2 = np.fft.rfft2(x2, axes=(-2, -1), norm='ortho')
x2 = torch.tensor(x2).to(device).to(torch.complex64)
# =====================================================================
# x2 = torch.fft.irfft2(x2, s=(a, b), dim=(2, 3), norm='ortho')
x2 = x2.detach().cpu().numpy()
x2 = np.fft.irfft2(x2, s=(a, b), axes=(-2, -1), norm='ortho')
x2 = torch.tensor(x2).to(device).to(torch.float32)
1.2 NotImplementedError [Adaptive pool] input size not accessible
问题:NotImplementedError [Adaptive pool] input size not accessible
原因分析:在C:\Users\Lee\AppData\Local\JetBrains\PyCharm2020.1\remote_sources-1671096312-1331535106\mmcv\onnx\symbolic.py中:
只有尺度为1,即output_size=[1]的情况才能有效运行,当尺度为其他情况时,总是会卡在第二个条件语句(if not input.isCompleteTensor())。因为input.isCompleteTensor()总是显示为Fasle,使得无法向下运行,导致运算结果失败。
解决方法:我尝试直接注释该条件语句,但是在dim = input.type().sizes()[2:]中,dim的结果为None,导致运行错误。我个人对于代码中对象input所属的Value类不是很熟悉,导致无法继续进行了,因此放弃该方式。
经过网上查询后,发现用MMdeploy可以解决该问题。经过测试后,确实转化成功了。本文后续就是总结MMdeploy的实现流程。
1.3 RuntimeError: ONNX export failed: Couldn’t export Python operator CheckpointFunction
问题:RuntimeError: ONNX export failed: Couldn’t export Python operator CheckpointFunction
原因分析:ONNX不支持使用Python算子CheckpointFunction。
解决方法:将模型配置文件中的use_checkpoint参数从True修改为False。经过网上查询,有说法是改这个参数不会影响网络(未证实,仅供参考)。修改完就可以转化成功了。
2. MMdeploy的部署过程
2.1 MMdeploy的环境配置
MMdeploy的环境配置过程分为如下步骤:
1.从MMdeploy官方GitHub中下载MMdeploy的代码。
2. 下载MMdeploy包。
我是通过清华园镜像下载的,速度较快。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mmdeploy==0.11.0
下载结果如下图所示:
3. 运行setup.py
在下载好的MMdeploy代码中,分别运行python setup.py install和python setup.py build。
python setup.py install
这个代码是可以修改环境中包的版本,以适配MMdeploy的运行环境。
运行结果:
python setup.py build
运行结果:
4. 值得注意的是,版本为0.11.0的MMdeploy只支持最高到mmcv==1.6.0。
我原本是1.7.0,所以,我还需要降下版本:
5.最后,我的整体环境如下:
2.2 模型的配置
从PyTorch转化为ONNX,我们需要配置三个脚本。分辨是ONNX的配置脚本,模型的配置脚本以及torch2onnx.py。
2.2.1 ONNX配置脚本
1.ONNX的配置脚本位于/configs/mmseg文件夹中。该文件夹中有很多转换脚本。如下图所示:
在该文件夹中,只需要根据需求找到对应的脚本。
由于我的HorNet模型的输入是512x512,并且是转化为onnxruntime。因此我选用
“segmentation_onnxruntime_static-512x512.py”。内容如下图,可以修改图像输入尺寸:
在segmentation_onnxruntime_static-512x512.py中还也会涉及三个脚本,分别如下图:
- config/mmseg/segmentation_static.py
这个不用管。直接用。
- config/_base_/onnx_config.py
可以修改opet_version和最终输出ONNX模型的名字。
- config/_base_/backends/onnxruntime.py
这个不用管。直接用。
2.2.2 模型配置脚本
该脚本其实就是MMCV框架下的模型脚本。
具体位置在模型训练后输出文件夹下,如下图所示。
脚本中内容如下图:
2.2.3 torch2onnx.py配置
终于到最后一步了,此处我们需要配置torch2onnx.py。torch2onnx.py位于tools/文件夹下:
需要配置的内容如下:
其中:
- deploy_cfg指的是ONNX配置脚本的路径。
- model_cfg指的是模型配置脚本的路径。
- checkpoint指的是模型权重的路径
- img指的是输入的图像。(和训练同尺度的图就行)
- work-dir指的是输出文件的路径
- device指的是转化时使用的显卡。【注意:转化所选的device不影响测试时的device】
3. 后续问题
最后重点说下,由于ONNX的具体转化过程我没有深入研究,但是经过转化后模型的大小明显变小,推测是对模型进行了量化。因此,精度明显降低。我转了两个模型,分别是建筑物和道路。建筑转化后,预测结果尚可接受。但是道路模型转化后,预测结果很差。因此,如果和我一样对于ONNX机制不是很了解的读者朋友,转化需慎重。
转化前大小:
转化后大小:
建筑物结果展示【红色为转化前,黄色为转化后】:
道路结果展示【红色为转化前,黄色为转化后】:
可以明显看到,道路的转化后的结果很差。所以,后续打算对ONNX进行进一步的学习。如果读者朋友可以解决该问题的也可以在评论区指导我。感谢!