在实际场景中,深度学习模型通常通过 PyTorch、TensorFlow 等框架来完成,直接通过这些模型来进行推理效率并不高,特别是对延时要求严格的线上场景。由此,经过工业界和学术界数年的探索,模型部署有了一条流行的流水线:
这一条流水线解决了模型部署中的两大难点:使用对接深度学习框架和推理引擎的中间表示,开发者不必担心如何在新环境中运行各个复杂的框架;通过中间表示的网络结构优化和推理引擎对运算的底层优化,模型的运算效率大幅提升。
在本文中,我们尝试以 ONNX 模型作为中介将 PyTorch 模型转换为 NCNN 模型。
一、将 PyTorch 模型转换为 ONNX 模型
1.1 配置环境
配置 PyTorch 环境的过程可以参考官方网站。
安装 ONNX Runtime 和 ONNX Smiplifier:
pip install onnxruntime
pip install onnx-simplifier
1.2 转换模型
在准备好相关环境后,使用以下 Python 代码即可将 PyTorch 模型转换为 ONNX 模型:
import torch.onnx
import torch
import timm
dummy_input = torch.randn(1, 3, 299, 299)
model = timm.create_model('inception_v3', num_classes=1000, pretrained=True)
model.eval()
torch.onnx.export(model, # model being run
dummy_input, # model input (or a tuple for multiple inputs)
"./out/inception_v3.onnx", # where to save the model (can be a file or file-like object)
export_params=True, # store the trained parameter weights inside the model file
do_constant_folding=True, # whether to execute constant folding for optimization
input_names = ['input'], # the model's input names
output_names = ['output'], # the model's output names
)
为了避免出现运行失败的情况,在将 ONNX 模型转换为 NCNN 模型前,我们需要简化ONNX 模型:
onnxsim ./out/inception_v3.onnx ./out/inception_v3-sim.onnx
1.3 验证模型
在转换后,需要对比 PyTorch 模型和转换后得到的 ONNX 模型的推理结果是否一致,以验证转换是否成功,可以使用以下代码:
import torch
import onnxruntime
import numpy as np
import cv2
import timm
#test image
img_path = "59204d6bb0c234eb.png"
img = cv2.imread(img_path)
img = cv2.resize(img, (299, 299))
img = np.transpose(img, (2, 0, 1)).astype(np.float32)
img = torch.from_numpy(img)
img = img.unsqueeze(0)
# pytorch test
model = timm.create_model('inception_v3', num_classes=1000, pretrained=True)
model.eval()
# pytorch test
output = model(img)
val, cls = torch.max(output.data, 1)
print("[PyTorch]--->predicted class:", cls.item())
print("[PyTorch]--->predicted value:", val.item())
# onnx test
sess = onnxruntime.InferenceSession("./out/inception_v3-sim.onnx")
x = "input"
y = ["output"]
output = sess.run(y, {x : img.numpy()})
cls = np.argmax(output[0][0], axis=0)
val = output[0][0][cls]
print("[ONNX]--->predicted class:", cls)
print("[ONNX]--->predicted value:", val)
可见,PyTorch 模型和 ONNX 模型的推理结果一致,说明转换成功:
二、将 ONNX 模型转换为 NCNN 模型
拉取 NCNN 代码:
git clone https://github.com/Tencent/ncnn.git
安装相关依赖:
sudo apt update
sudo apt install build-essential git cmake libprotobuf-dev protobuf-compiler libvulkan-dev vulkan-utils libopencv-dev
编译 Vulkan 后端:
wget https://sdk.lunarg.com/sdk/download/1.2.182.0/linux/vulkansdk-linux-x86_64-1.2.182.0.tar.gz
tar xvf vulkansdk-linux-x86_64-1.2.182.0.tar.gz
export VULKAN_SDK=$(pwd)/1.2.182.0/x86_64
拉取 NCNN 子模块:
cd ncnn
git submodule update --init
编译 NCNN:
mkdir -p build-x86
cd build-x86
cmake -DCMAKE_BUILD_TYPE=Release -DNCNN_VULKAN=ON -DNCNN_SYSTEM_GLSLANG=ON -DNCNN_BUILD_EXAMPLES=ON ..
make -j$(nproc)
如果使用cmake
命令时提示:CMake 3.14.0 or higher is required. You are running version 3.10.2
,则需要升级cmake
,可以执行以下命令:
sudo apt remove cmake # 删除旧版本的cmake
sudo apt-get install build-essential libssl-dev
wget https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0.tar.gz
tar -zxvf cmake-3.20.0.tar.gz
cd cmake-3.20.0
./bootstrap
make
sudo make install
cmake --version
编译结束之后会在 ./build-x86/tools/onnx/
下得到 onnx2ncnn
可执行文件,即将 ONNX 模型转换为 NCNN 模型的转换工具。将上面得到的 inception_v3-sim.onnx
拷贝至该目录,执行命令:
cd tools/onnx/
./onnx2ncnn inception_v3-sim.onnx inception_v3.param inception_v3.bin
即可转换得到 NCNN 模型。
参考资料
[2] pytorch转ncnn及其测试
另外,本文只是最基本的部署教程,如果涉及到复杂操作(例如自定义 ONNX 中没有的算子),建议阅读由 MMDeploy 提供的文档:操作概述、第一章:模型部署简介等。
版权属于:Angus
本文链接:https://blog.angustar.com/archives/deploying-DNNs-on-embedded-development-boards-1.html
所有原创文章采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。 您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。