• Ncnn框架在c++的推理及其认识


    目录

    认识:

    关于NCNN的模型转换:

    关于NCNN模型文件的认识:

    在c++下的推理:

    认识:

            ncnn是腾讯优图推出的在手机端极致优化的高性能神经网络前向计架框架,适用于手机端的CPU计算且无需依赖第三方计算库,ncnn只用作推理而非边训练边推理。

    ncnn (GitHub地址:GitHub - Tencent/ncnn: ncnn is a high-performance neural network inference framework optimized for the mobile platform ncnn 从设计之初深刻考虑手机端的部署和使用。无第三方依赖,跨平台,手机端 CPU 的速度快于目前所有已知的开源框架。基于 ncnn,开发者能够将深度学习算法轻松移植到手机端高效执行,开发出人工智能 APP,将 AI 带到你的指尖。ncnn 目前已在腾讯多款应用中使用,如 QQ,Qzone,微信,天天P图等。

    同时由于NCNN模型是全部用c++来写的,所以它可以跨平台,比如常见的嵌入式设备上可以通用,另外我了解到它的负责人是nihui大佬,nihui群里更是大佬云集。

    关于NCNN的模型转换:

    先附上脚本转换网站(daquexian前辈):

    一键转换 Caffe, ONNX, TensorFlow 到 NCNN, MNN, Tengine (convertmodel.com)

    这是一个在线的模型转换网站

    对于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环境配置参照:

    Windows下ncnn环境配置(VS2019)_逮仔的博客-CSDN博客_ncnn vs2019

    以经典的分类网络为例

    1. // 网络加载
    2. ncnn::Net squeezenet;
    3. squeezenet.load_param("squeezenet_v1.1.param");
    4. squeezenet.load_model("squeezenet_v1.1.bin");
    5. // 数据预处理
    6. ncnn::Mat in = ncnn::Mat::from_pixels_resize(image.data, ncnn::Mat::PIXEL_BGR, image.cols, image.rows, 227, 227);
    7. const float mean_vals[3] = { 104.f, 117.f, 123.f };
    8. in.substract_mean_normalize(mean_vals, 0);
    9. // 网络推理
    10. ncnn::Extractor ex = squeezenet.create_extractor();
    11. ex.input("data", in);
    12. ncnn::Mat out;
    13. ex.extract("prob", out);

    具体步骤

    1. 网络加载
      1. load_param
      2. load_model
    2. 数据预处理
      1. from_pixels_resize
      2. substract_mean_normalize
    3. 网络推理
      1. create_extractor
      2. input
      3. extract
    4. 每一层的推理(隐含在模型内的)

    注意的地方:

    作为初学者可以把ncnn的推理看做是一个黑盒子,只关注网络的输入和输出,本例子网络中的data则是输入层的名字,prob则是输出层的名字,关于怎么知道不同训练过程的输入和输出网络层的名字?用netron可视化观察,同时还能看到它输出的通道数知道自己该用什么样的数据结构去接受输出内容。

    在netron的可视化下

     最后输出名为518,输出通道数量为512

    最后,整体看来确实简单,推理实际上是forward的一个递归的过程。

     

  • 相关阅读:
    springboot 使用 microsoft SQL server 报错
    Codeforces Round #827 (Div. 4) A-G
    【华为机试真题 JAVA】第k个排列-100
    shell脚本详解
    python技术面试题(其三)
    VOLTE:MIUI14无5G信号、通话质量差、短信收不到的原因之一
    改造delon库的reuse-tab标签使其关联隐藏动态菜单Menu及tab切换时参数不丢失方案
    使用Cmake编译项目从入门到精通
    论文阅读笔记 | 三维目标检测——PointNet
    论文阅读——DiffusionDet
  • 原文地址:https://blog.csdn.net/PHILICS7/article/details/125430079