ncnn笔记_cnn代码

ncnn笔记_cnn代码最近看了ncnn的源码,代码风格清爽,遂想先抛开VULKAN记录一下它的推理流程。1. 先看个yolov2democsdn上的帖子https://blog.csdn.net/sina

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

最近看了ncnn的源码,代码风格清爽, 遂想先抛开VULKAN记录一下它的推理流程。

1. 先看个yolov2 demo

csdn上的帖子https://blog.csdn.net/sinat_31425585/article/details/83243961, 其文末还附了福利直接可用的模型https://download.csdn.net/download/sinat_31425585/10737783,超赞的良心博主。

yolov2.cpp

 //construct net
   ncnn::Net yolov3;
    yolov3.load_param("mobilenetv2_yolov3.param");
    yolov3.load_model("mobilenetv2_yolov3.bin");
  //read in img
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows, target_size, target_size);
  //substract mean
    const float mean_vals[3] = {127.5f, 127.5f, 127.5f};
    const float norm_vals[3] = {0.007843f, 0.007843f, 0.007843f};
    in.substract_mean_normalize(mean_vals, norm_vals);
  //construct create_extractor
    ncnn::Extractor ex = yolov3.create_extractor(); 
    ex.set_num_threads(4); 
  //provide input
    ex.input("data", in); 
  //get output
    ncnn::Mat out; ex.extract("detection_out", out);

     清晰的识图流程:构建网络, 读入模型描述文件/权重文件, 读入图片做减均值, 构造提取器, 计算出预测数据。 

2. 网络模型描述文件

/benchmark下有很多网络的param, 以alexnet为例子

7767517 15 15 Input data 0 1 data 0=227 1=227 2=3 Convolution conv1 1 1 data conv1_relu1 0=96 1=11 3=4 5=1 6=34848 9=1 LRN norm1 1 1 conv1_relu1 norm1 2=0.000100 Pooling pool1 1 1 norm1 pool1 1=3 2=2 ConvolutionDepthWise conv2 1 1 pool1 conv2_relu2 0=256 1=5 4=2 5=1 6=307200 7=2 9=1 LRN norm2 1 1 conv2_relu2 norm2 2=0.000100 Pooling pool2 1 1 norm2 pool2 1=3 2=2 Convolution conv3 1 1 pool2 conv3_relu3 0=384 1=3 4=1 5=1 6=884736 9=1 ConvolutionDepthWise conv4 1 1 conv3_relu3 conv4_relu4 0=384 1=3 4=1 5=1 6=663552 7=2 9=1 ConvolutionDepthWise conv5 1 1 conv4_relu4 conv5_relu5 0=256 1=3 4=1 5=1 6=442368 7=2 9=1 Pooling pool5 1 1 conv5_relu5 pool5 1=3 2=2 InnerProduct fc6 1 1 pool5 fc6_drop6 0=4096 1=1 2=37748736 9=1 InnerProduct fc7 1 1 fc6_drop6 fc7_drop7 0=4096 1=1 2=16777216 9=1 InnerProduct fc8 1 1 fc7_drop7 fc8 0=1000 1=1 2=4096000 Softmax prob 1 1 fc8 output

line 1:magic number, 有点校验码的味道

line 2:   layer_count   blob_count

rest line:  【layer_type】  【layer_name】 【bottom_blob_num】【top_blob_num】【bottom/top_blob_names 】【calculate_parameters】(key_id = value 的形式, 不太常见的是有个比较大的数,如conv中的 6=34848, weight_size, 从文件读取weights有用)

calculate_parameters: 会被ParamDict解析成字典, 每个layer用ParamDict读出计算参数。

blob 的管理: blob只是描述tensor的数据结构(存储name,producer 和consumers的索引),实际数据存储在extraor中。

3. Net

Extractor是个很好的推理抽象,数据成员就三个:网络net, 计算的blobs_mats(vector<Mat>) 和 option(配置信息)

调用extract(const char* blob_name, Mat&feat)函数的时候, extractor会去判断blob_name 指向的Mat是否有值, 有的话直接返回给feat, 没有就去调用net 的forward_layer函数来计算出这个Mat 再返回。

net->forward_layer(layer_index,  blob_mats, opt)是一个递归函数, 下面只截取了部分源码来表达逻辑

int Net::forward_layer(int layer_index, std::vector<Mat>& blob_mats, Option& opt) const { const Layer* layer = layers[layer_index]; if (layer->one_blob_only) { // load bottom blob int bottom_blob_index = layer->bottoms[0]; int top_blob_index = layer->tops[0]; if (blob_mats[bottom_blob_index].dims == 0) { int ret = forward_layer(blobs[bottom_blob_index].producer, blob_mats, opt); if (ret != 0) return ret; } Mat bottom_blob = blob_mats[bottom_blob_index]; // forward if (opt.lightmode && layer->support_inplace) { Mat& bottom_top_blob = bottom_blob; int ret = layer->forward_inplace(bottom_top_blob, opt); if (ret != 0) return ret; // store top blob blob_mats[top_blob_index] = bottom_top_blob; }
   }

该函数检查该layer的bottom_blob_num是否有效,没有的话就调用上一层的forward_layer。bottom_blob凑齐后调用layer->forward()计算出本层的top_blob(cosumers的bottom_blob)。

再看一眼Net这个类的几个成员函数和变量:

public:// register custom layer by layer type name // return 0 if success int register_custom_layer(const char* type, layer_creator_func creator); // register custom layer by layer type // return 0 if success int register_custom_layer(int index, layer_creator_func creator); // load network structure from plain param file // return 0 if success int load_param(FILE* fp);protected:

int forward_layer(int layer_index, std::vector<Mat>& blob_mats, Option& opt) const; protected: std::vector<Blob> blobs; std::vector<Layer*> layers; std::vector<layer_registry_entry> custom_layer_registry;

load_param() 用来初始化填充blobs和layers, forward_layer() 用来调用layer->forward()推数据流动。

下面是load_param()中create_layer的方式,先调用内建layer类中的create_layer()函数, 如果不识别再调用create_custom_layer(),这也不识别那就只有abort()了。create_layer()和 create_custom_layer() 分别去查找layer中定义的layer_registry和net中定义的custom_layer_registry。

 Layer* layer = create_layer(layer_type); if (!layer) { layer = create_custom_layer(layer_type); } 

layer_registry_entry结构中装了layer的name的creator函数, 内建的layer_registry 通过#include “layer_registry.h”来初始化, 而layer_registry.h文件用cmake在编译时生成, 即相应的layer在CMakeLists中添加。 而custom_layer_registry的话需调用register_custom_layer() 来注册, 即往custom_layer_registry里push_back一个entry。examples/mobilenetv2ssdlite.cpp 下有一个注册Noop的例子。

//layer.h struct layer_registry_entry { // layer type name const char* name; // layer factory entry  layer_creator_func creator; }; //layer.cpp static const layer_registry_entry layer_registry[] = { #include "layer_registry.h" };

内建的layer_creator_func 也是cmake生成,定义在layer_declaration.h中, 下面是生成文件中的第一个算子。

class AbsVal_final : virtual public AbsVal { public: virtual int create_pipeline(const Option& opt) { { int ret = AbsVal::create_pipeline(opt); if (ret) return ret; } return 0; } virtual int destroy_pipeline(const Option& opt) { { int ret = AbsVal::destroy_pipeline(opt); if (ret) return ret; } return 0; } }; DEFINE_LAYER_CREATOR(AbsVal_final) //layer.h #define DEFINE_LAYER_CREATOR(name) \ ::ncnn::Layer* name##_layer_creator() { return new name; }

 

4. Layer

下面是layer 类的主要成员和函数

public: // load layer specific parameter from parsed dict // return 0 if success virtual int load_param(const ParamDict& pd); // load layer specific weight data from model binary // return 0 if success virtual int load_model(const ModelBin& mb); public: // implement inference // return 0 if success virtual int forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt = Option()) const; virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt = Option()) const; // implement inplace inference // return 0 if success virtual int forward_inplace(std::vector<Mat>& bottom_top_blobs, const Option& opt = Option()) const; virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt = Option()) const; public: // layer type index int typeindex; // layer type name std::string type; // layer name std::string name; // blob index which this layer needs as input std::vector<int> bottoms; // blob index which this layer produces as output std::vector<int> tops;

layer_type的enum也是cmake生成的。在src/layer文件下是实现了很多的算子类, 大部分都只需要继承Layer函数, 实现

不同的load_param(), load_model() 和forward() 函数就行。

 

先写这么多入个门, ncnn的重点应该是针对各类算子在移动设备端的优化。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/166554.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 如何彻底删除kvm虚拟机_虚拟机命令怎么删除

    如何彻底删除kvm虚拟机_虚拟机命令怎么删除(转)virsh命令速查表VirshVirshconnectVirshdisplaynodeinformation:VirshlistalldomainsListonlyactivedomainsVirshstartvmVirshautostartvmVirshautostartdisableVirshstopvm,virshshutd…

  • 傻妞机器人新版安装教程「建议收藏」

    傻妞机器人新版安装教程「建议收藏」本文由以下部分组成傻妞基础功能简介。傻妞机器人安装(只对接QQ)傻妞常规设置傻妞对接微信/公众号/TG机器人傻妞重启以及更换机器人QQ傻妞青龙扩展使用。其他一、傻妞功能简介1.傻妞青龙扩展可以发送命令控制青龙任务,添加青龙变量,提交COOKIE,查询资产,查看任务日志等等!可对接其他项目。2.配置扩展在sillyGirl/conf/config.yaml文件配置各种API,让傻妞功能丰富多彩。目前支持返回图片和文本(包括链接)。样例文件见文末。3.自定义文件功能扩展在sill

  • JavaScript 判断元素是否在数组中

    JavaScript 判断元素是否在数组中

    2021年11月22日
  • PyCharm安装及使用

    PyCharm安装及使用

    2021年10月16日
  • Ubuntu下安装VSCODE「建议收藏」

    Ubuntu下安装VSCODE「建议收藏」方式一:应用中心安装首先在ubuntu桌面找到应用中心打开在软件中心中,搜索VisualStudioCode当然上面是理想情况,这种图是我在网上搜的。。。我自己的应用中心并不能搜索到VSCODE能找到就在页面中直接选择安装方式二:安装包安装1.从vscode官网下载最新版本,deb包下载地址:https://code.visualstudio.com/docs?dv=linux64当然由于是外网,可能下载速度极慢,这是我下载后上传到百度云的链接,官网下载..

  • Web 3D机房,智能数字机房HTML5 WebGL(ThreeJS)匠心打造「建议收藏」

    Web 3D机房,智能数字机房HTML5 WebGL(ThreeJS)匠心打造「建议收藏」在H5使用3D技术门槛比较低了,它的基础是WebGL(ThreeJS),一个OpenGL的浏览器子集,支持大部分主要3D功能接口。目前主流的浏览器都有较好的支持,IE需要11。最近web3D机房研发告一段落,有时间整理这段时间的一些成果。主要涉及使用H5、js、WebGL技术。机房3D效果图机房线缆和走线架线缆的连接走向和连接关系是管理员关注的焦点。机架中…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号