在嵌入式开发板上部署深度神经网络（一）：将 PyTorch 模型转换为 NCNN 模型
在实际场景中，深度学习模型通常通过 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) [scode type="yellow"] 如果使用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 [/scode] 编译结束之后会在 ./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 模型。 参考资料 [1] pytorch-＞onnx-＞ncnn模型移植 [2] pytorch转ncnn及其测试 [3] V831上部署resnet18分类网络 [4] onnx2ncnn并在pc端调用ncnn模型 另外，本文只是最基本的部署教程，如果涉及到复杂操作（例如自定义 ONNX 中没有的算子），建议阅读由 MMDeploy 提供的文档：操作概述、第一章：模型部署简介等。