赞
踩
概述:本文主要讲述把MobileNet转成华为Altas服务器离线推理om模型的过程,本人在转换过程中也遇到过比较多的坑,这里把我的经验记录下来,希望大家可以少走点弯路,如果大家觉得此教程有用,记得订阅点赞加分享哦.
ATC MobileNet在ascend的ModelZoo已经有相关的样例,我们先通过下面的地址去下载样例,在下面地址点击立即下载即可.
https://www.hiascend.com/zh/software/modelzoo/detail/1/a2951ef07c40424a9b0e39237466e383
下载并解压,里面有官方提供的通过ImageNet训练出来的模型,如下,
我们需要为环境安装相对应的依赖,我们这里是使用ARM架构的Altas服务器,我解决完依赖问题时候,对应的Python环境包如下所示:
asttokens==2.0.4 astunparse==1.6.3 attrs==20.3.0 auto-tune @ file:///root/selfgz270731700/fwkacllib/lib64/auto_tune-0.1.0-py3-none-any.whl certifi==2020.12.5 cffi==1.14.4 chardet==4.0.0 click==7.1.2 Cython==0.29.21 decorator==4.4.2 easydict==1.9 Flask==1.1.2 flatbuffers==1.12 geffnet @ file:///home/jxl/guochan/dxaisix/geffnet-1.0.2-py3-none-any.whl grpcio==1.35.0 grpcio-tools==1.35.0 gunicorn @ file:///home/jxl/guochan/dxaisix/gunicorn-20.0.4-py2.py3-none-any.whl hccl @ file:///root/selfgz270731700/fwkacllib/lib64/hccl-0.1.0-py3-none-any.whl idna==2.10 itsdangerous==1.1.0 Jinja2==2.11.2 joblib==0.17.0 MarkupSafe==1.1.1 mindspore-ascend @ file:///tmp/mindspore_ascend-1.1.1-cp37-cp37m-linux_aarch64.whl mpmath==1.1.0 numpy @ file:///home/jxl/guochan/whl/numpy-1.21.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl onnx @ file:///home/jxl/guochan/dxaisix/onnx-1.10.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl onnxconverter-common==1.7.0 onnxruntime @ file:///home/jxl/guochan/dxaisix/onnxruntime-1.10.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl packaging==20.9 pathlib2==2.3.5 Pillow==8.1.0 protobuf==3.14.0 psutil==5.8.0 pycparser==2.20 pyparsing==2.4.7 PyYAML==5.4.1 requests==2.25.1 schedule-search @ file:///root/selfgz270731700/fwkacllib/lib64/schedule_search-0.1.0-py3-none-any.whl scikit-learn==0.23.2 scipy==1.6.0 six==1.15.0 skl2onnx @ file:///home/jxl/guochan/dxaisix/skl2onnx-1.10.3-py2.py3-none-any.whl sympy==1.4 te @ file:///root/selfgz270731700/fwkacllib/lib64/te-0.4.0-py3-none-any.whl tensorflow-aarch64==1.2 threadpoolctl==2.1.0 topi @ file:///root/selfgz270731700/fwkacllib/lib64/topi-0.4.0-py3-none-any.whl torch @ file:///home/jxl/guochan/dxaisix/torch-1.10.0-cp37-cp37m-manylinux2014_aarch64.whl torchvision @ file:///home/jxl/guochan/whl/torchvision-0.10.0-cp37-cp37m-manylinux2014_aarch64.whl typing-extensions==3.7.4.3 urllib3==1.26.3 Werkzeug==1.0.1
我们把官方无用的pth模型(Pytorch输出),和om模型删除,并换上自己训练好准备转换的模型,这里我把模型统一放在models目录下面,如下所示:
对于上图中,其他的文件解释如下:
atlas_utils(现在改名为acllite):
Pyacl调用组件包,可以通过下面地址下载:
https://gitee.com/ascend/samples/tree/master/python/common
nc
存放我们这个实例中的测试图片
tools
存放我们这个实例中的自定义预处理文件
mobilenetv3.py文件
存放我们定义的mobilenetv3文件
至此,前期文件准备已经完成
更改MobileNetV3_pth2onnx.py,使其模型导入为自定义的模型,其中需要修改的部分如下,下图蓝色部分,这里需要传入正确的class_num,另外如果inputsize不是224*224的话,需要改32行的input,这里是默认input所以暂时不用修改.
通过下面的命令调用MobileNetV3_pth2onnx.py把pth模型转换成onnx模型,转换完成以后,models文件夹下面就会多一个mobilenetv3-81-best.onnx模型
python3 MobileNetV3_pth2onnx.py ./models/mobilenetv3-81-best.pth ./models/mobilenetv3-81-best.onnx
新建predict_onnx.py文件,使用转换前一样的预处理函数,用onnxrutime去调用onnx模型进行前向运算,查看输出结果和原来的是否一致
import os import cv2 from torchvision import transforms from tools import my_transforms from tools.utils import BaseTransform import onnxruntime # to inference ONNX models, we use the ONNX Runtime train_size = (256, 256) net_size = (224, 224) rgb_means = (0.42819217, 0.4287907, 0.42214316) rgb_std = (0.26126036, 0.24752016, 0.24400638) def predict_onnx(img_path): img_src = cv2.imread(img_path) transformer = transforms.Compose([ my_transforms.Resize(train_size), my_transforms.CenterCrop(net_size), BaseTransform(net_size, rgb_means, rgb_std)]) img_src = transformer(img_src) img_src = img_src.unsqueeze(0) input_data = img_src.numpy() print("input_data shape {}".format(input_data.shape)) session = onnxruntime.InferenceSession('./models/mobilenetv3-81-best.onnx', None) raw_result = session.run([], {'image': input_data}) return raw_result if __name__ == '__main__': img_list = os.listdir("./nc") for img_name in img_list: print("predict: {}".format(img_name)) result = predict_onnx("./nc/{}".format(img_name)) print(result)
这里的输出结果,如下所示,与转换之前的结果是一致的
下面需要用到模型转换工具ATC,以及PYACL离线推理包,需要先配置环境变量,过程如下,其中ascendtools的安装环境需要自己更改,本实例是安装在/usr/local/Ascend/ascend-toolkit/latest
配置ATC环境变量
export PATH=/usr/local/Ascend/ascend-toolkit/latest/atc/ccec_compiler/bin:/usr/local/Ascend/ascend-toolkit/latest/atc/bin:$PATH
export ASCEND_OPP_PATH=/usr/local/Ascend/ascend-toolkit/latest/arm64-linux/opp
export ASCEND_AICPU_PATH=/usr/local/Ascend/ascend-toolkit/latest/
配置PYACL环境变量
export PYTHONPATH=/usr/local/Ascend/ascend-toolkit/latest/arm64-linux/pyACL/python/site-packages/acl:$PYTHONPATH
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/arm64-linux/acllib/lib64:$LD_LIBRARY_PATH
接下来把onnx模型转换成om模型,运行下面的命令即可,运行成功后,模型
atc --framework=5 \
--model=./models/mobilenetv3-81-best.onnx \
--input_format=NCHW \
--input_shape="image:1,3,224,224" \
--output=./models/mobilenetv3-81-best \
--log=debug \
--soc_version=Ascend910
运行结果:
新建predict_pyacl.py文件,与onnx一样,参照原模型去写预处理代码,并使用pyacl的api调用离线模型
from atlas_utils.acl_model import Model from atlas_utils.acl_resource import AclResource from torchvision import transforms import os import acl import cv2 from tools import my_transforms from tools.utils import BaseTransform acl_resource = AclResource() acl_resource.init() model = Model("models/mobilenetv3-81-best.om") dims, ret = acl.mdl.get_input_dims(model._model_desc, 0) _, _, height, width = tuple(dims["dims"]) print("model input: {}".format(tuple(dims["dims"]))) train_size = (256, 256) net_size = (224, 224) rgb_means = (0.42819217, 0.4287907, 0.42214316) rgb_std = (0.26126036, 0.24752016, 0.24400638) def predict_acl(img_path): """ Program execution with picture directory parameters """ """ 模仿img_preprocess.py编写 """ img_src = cv2.imread(img_path) transformer = transforms.Compose([ my_transforms.Resize(train_size), my_transforms.CenterCrop(net_size), BaseTransform(net_size, rgb_means, rgb_std)]) img_src = transformer(img_src) img_src = img_src.unsqueeze(0) input_data = img_src.numpy() ptr, input_data = acl.util.numpy_contiguous_to_ptr(input_data) print("input_data shape {}".format(input_data.shape)) result = model.execute([input_data, ]) return result if __name__ == '__main__': img_list = os.listdir("./nc") for img_name in img_list: print("predict: {}".format(img_name)) result = predict_acl("./nc/{}".format(img_name)) print(result)
运行并测试代码,输出如下结果:
可见输出的结果和onnx模型是一致的,证明转换成功了,
这里有一个天坑,本人花了很长时间才确认的,如果自定义预处理中,输出的numpy数组在内存不是连续存储的,会出现下面的warning
/home/jxl/guochan/guochan_src_code/mobilenetv3/atlas_utils/acl_model.py:142: Warning: The input ndarray is discontiguous. Please use acl.util.numpy_contiguous_to_ptr instead.
ptr = acl.util.numpy_to_ptr(input_data)
这个warning是不能忽略的,否则,输出的不肯能是我们想要的结果.我们先通过下面语句去看是否连续
input_data.flags
输出:
发现和上面的warning一致,储存是不连续的,所以我们需要用到下面语句,把他转成连续存储的numpy数组:
ptr, input_data = acl.util.numpy_contiguous_to_ptr(input_data)
ALL DONE!
本期的教程就到这里啦,谢谢大家的关注哦,如果大家觉得有用,记得点赞和分享哦.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。