Ncnn框架在c++的推理及其认识
认识:
ncnn是腾讯优图推出的在手机端极致优化的高性能神经网络前向计架框架,适用于手机端的CPU计算且无需依赖第三方计算库,ncnn只用作推理而非边训练边推理。
同时由于NCNN模型是全部用c++来写的,所以它可以跨平台,比如常见的嵌入式设备上可以通用,另外我了解到它的负责人是nihui大佬,nihui群里更是大佬云集。
关于NCNN的模型转换:
先附上脚本转换网站(daquexian前辈):
这是一个在线的模型转换网站
对于Pytorch模型:
一种是可以通过PNNX直接转ncnn,pnnx是一个工具,支持动态尺寸输入,目前只支持torchscript转ncnn,且只支持torch.trace的torchscript。这种网上资料较少。
另一种则是通过中间模型onnx转ncnn,这种网上资料比起pnnx转ncnn更多。
关于NCNN模型文件的认识:
param和bin
param是网络结构文件,而bin则是参数文件
查看网络结构是不是同一个可用netron.app在线网站查看
以打开mobiefacenet的param
第一行的7767517为magic num
第二行的的160为网络层数,从第三行开始数,172为blob数量,相当于一个数据节点,带输入和输出。
从第三行开始为网络层,第一列为网络层类型,第二列为网络层名,第三列为bottom_count,第四列为top_count,bottom_count为该层在多少个网络层之下(相当于输入的blob数),top_count为该层在多少个网络层之上(理解为输出的blob数),后面的列依次为bottom_name,blob_name 以及该层的所带的参数,如果bottom_count为0则可以省略正如input那一层。
在c++下的推理:
前提,在电脑上装好环境,比如已经编译好了的ncnn库,protobuf,opencv库
ncnn环境配置参照:
以经典的分类网络为例
// 网络加载 ncnn::Net squeezenet; squeezenet.load_param("squeezenet_v1.1.param"); squeezenet.load_model("squeezenet_v1.1.bin"); // 数据预处理 ncnn::Mat in = ncnn::Mat::from_pixels_resize(image.data, ncnn::Mat::PIXEL_BGR, image.cols, image.rows, 227, 227); const float mean_vals[3] = { 104.f, 117.f, 123.f }; in.substract_mean_normalize(mean_vals, 0); // 网络推理 ncnn::Extractor ex = squeezenet.create_extractor(); ex.input("data", in); ncnn::Mat out; ex.extract("prob", out);
具体步骤
- 网络加载 load_param load_model
- 数据预处理 from_pixels_resize substract_mean_normalize
- 网络推理 create_extractor input extract
- 每一层的推理(隐含在模型内的)
注意的地方:
在netron的可视化下
最后输出名为518,输出通道数量为512
最后,整体看来确实简单,推理实际上是forward的一个递归的过程。