《TencentNCNN系列》 之工作原理简要解析(以LeNet-5为例)
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=068)
本文发布于 2018-07-19 11:05:52,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=068)
环境说明
时间:2018.07.19
ncnn master commit id:b3e24cafc37483dcc97ee61e6f0f6ff1b094300e
前言
前面两篇文章我们分析了ncnn的加载参数和网络的基本工作流程。其实这一切只是为了给这篇文章做准备。因为我觉得ncnn作为一个前向框架,写的还是比较简单的,方便我们这些小菜鸟对其工作原理进行分析。而分析的方法,还是得从哪里来,从哪里去(读源码)。
前置内容(非常重要的)
本文作为例子的网络
7767517
9 9
Input data 0 1 data 0=28 1=28 2=1
Convolution conv1 1 1 data conv1 0=20 1=5 2=1 3=1 4=0 5=1 6=500
Pooling pool1 1 1 conv1 pool1 0=0 1=2 2=2 3=0 4=0
Convolution conv2 1 1 pool1 conv2 0=50 1=5 2=1 3=1 4=0 5=1 6=25000
Pooling pool2 1 1 conv2 pool2 0=0 1=2 2=2 3=0 4=0
InnerProduct ip1 1 1 pool2 ip1 0=500 1=1 2=400000
ReLU relu1 1 1 ip1 ip1_relu1
InnerProduct ip2 1 1 ip1_relu1 ip2 0=10 1=1 2=5000
Softmax prob 1 1 ip2 prob 0=0
ncnn的基本调用流程
#include "net.h"
ncnn::Net abc_net;
ncnn::Mat in_img;
ncnn::Mat out_img;
abc_net.load_param(param_path);
abc_net.load_model(model_path);
ncnn::Extractor ex = abc_net.create_extractor();
ex.set_num_threads(4);
ex.set_light_mode(true);
ex.input("data", in_img);
ex.extract("prob", out_img);
这里简要说明一下:
前两篇文章分别介绍了load_param load_model的基本工作原理,这里要介绍的就是剩下的所有内容。
相关数据结构准备(此小节内容可作为前两篇文章的内容补充)
在load_param时:
ncnn::Net::blobs存放着每一个blob的相关信息,主要信息为name、producer、consumers,含义分别为:名字、产生这个blob数据的层、消费这个blob数据的层。
ncnn::Net::layers存放的是:
- ncnn::Net::layers::type
- ncnn::Net::layers::name
- ncnn::Net::layers::bottoms 存的是此层需要的输入blob的idx
- ncnn::Net::layers::tops 存的是此层输出的blob的idx
在load_param中会根据我们读入的type来create_layer,这里建立这个layer也挺有意思的。
//这里的layer_to_index会去layer_registry去查找对应的层类型的idx,这里的layer_registry数组是我们在编译ncnn的时候初始化的,里面存放的是如下的东西。
#if NCNN_STRING
{"Convolution",Convolution_x86_layer_creator},
#else
{Convolution_x86_layer_creator},
//这个数组的作用就是用来查询具体层的idx和其提供的构造接口creator。每个层都会实现这个creator,比如Convolution层在x86架构下,其构造接口名字叫做Convolution_x86_layer_creator。其原理如下:
DEFINE_LAYER_CREATOR(Convolution_x86)//通过宏定义Convolution_x86_layer_creator这个全局函数
#define DEFINE_LAYER_CREATOR(name) \
::ncnn::Layer* name##_layer_creator() { return new name; }
以前文网络为例分析
这里的分析入口为:
ncnn::Extractor::input()
//图中blob_mats 就是整个框架工作时的数据存放向量。
std::vector<Mat> blob_mats;//blob_mats 定义
//blob_mats的大小初始化在ncnn::Net::create_extractor()中完成,这里唯一需要注意的是,此函数是类Extractor的友元类成员函数,这样写的原因是为了访问其protect的构造函数。
Extractor Net::create_extractor() const
{
return Extractor(this, blobs.size());
}
Extractor::Extractor(const Net* _net, int blob_count) : net(_net)
{
blob_mats.resize(blob_count);
lightmode = true;
num_threads = 0;
}
//find_blob_index_by_name 就是在ncnn::Net::blobs中去循环遍历,得到其idx。
//然后把输入的mat数据,放入到blob_mats中相应的位置去。到这里,输入数据就填充完了。
ncnn::Extractor::extract()
//此调用的开始时,根据名字通过find_blob_index_by_name 查找我们需要的输出层的idx,然后把blob_mats(携带输入数据)、lightmode、我们需要的输出层的idx一起传入给ncnn::Net::forward_layer()。然后将上述调用处理好的数据放入feature返回。一个网络的前向计算就完成了。
ncnn::Net::forward_layer()
上图这个if语句是这层网络只有一个输入和输出
此图的else是这层网络非一个输入和输出
//这里我只分析只有一个输入和输出的情况,另外一种和它非常相近。
//图中line 637-line 642,这里通过递归调用一层层倒推回去,直到我们的网络输入层。因为这一层在input的时候给blob_mats赋值,其dims不为零。
//图中line646-line 655是set_light_mode的作用,其作用为是否释放计算过程中,存入blob_mats中,在前面层计算的得到的数据
//图中line 658-line 691是开始前向计算。这里的计算分为两类,一类是在输入数据上计算,并把输出数据放入到输入数据的变量中。另外一种就是分别传入两个变量,一个存输入,一个存输出。至于为啥这样写,不知道,节约内存?
//后续只会分析一种情况,分别传入两个变量,一个存输入,一个存输入。这里以前文网络中的第二层Convolution层为例。在line 677-line 690中,layer->forward()就是执行具体层的计算。
ncnn::Convolution::forward()
//这里只分析kernel为1*1*1的这种卷积
//这里构造了一个InnerProduct层操作,这里简短的几句话,其实就是我前面几篇文章中的部分内容,load_param做了什么,load_model做了什么
ncnn::InnerProduct::forward()
这里核心是计算两个向量的内积。
到这里为止,一个卷积操作就完成了。然后forward_layer会从递归中一级级返回,最后得到我们需要的那一层的值。
后记
无
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
《TencentNCNN系列》 之工作原理简要解析(以LeNet-5为例)的更多相关文章
- android多线程-AsyncTask之工作原理深入解析(下)
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- android多线程-AsyncTask之工作原理深入解析(上)
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- 路由及路由器工作原理深入解析3:路由与port
日志"路由及路由器工作原理深入解析1"http://user.qzone.qq.com/2756567163/blog/1438322342介绍了"为什么要使用路 ...
- NS域名工作原理及解析
DNS域名工作原理及解析 0x00 定义 DNS( Domain Name System)是“域名系统”的英文缩写,它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.D ...
- JavaScript的工作原理:解析、抽象语法树(AST)+ 提升编译速度5个技巧
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
- Java web每天学之Servlet工作原理详情解析
上篇文章中我们介绍了Servlet的实现方式以及Servlet的生命周期,我们这篇文章就来介绍一下常用对象. 点击回顾:<Java Web每天学之Servlet的工作原理解析>:<J ...
- Android ListView工作原理完全解析,带你从源码的角度彻底理解
版权声明:本文出自郭霖的博客,转载必须注明出处. 目录(?)[+] Adapter的作用 RecycleBin机制 第一次Layout 第二次Layout 滑动加载更多数据 转载请注明出处:h ...
- Android ListView工作原理完全解析(转自 郭霖老师博客)
原文地址:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android所有常用的原生控件当中,用法最复杂的应该就是ListVie ...
- Android ListView工作原理全然解析,带你从源代码的角度彻底理解
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android全部经常使用的原生控件其中.使用方法最复杂的应该就是 ...
- DNS的工作原理及解析
DNS协议是互联网核心协议之一.不管是上网浏览,还是编程开发,都需要了解一点它的知识. 一.什么是DNS? DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次 ...
随机推荐
- CF1089K King Kog's Reception 题解
题目传送门 前置知识 线段树 解法 第一眼感觉和 luogu P1083 [NOIP2012 提高组] 借教室 很像.本题同样采用线段树维护,\(sum_{l,r}(1 \le l \le r \le ...
- BZOJ3364 Distance Queries 距离咨询 题解
原题 简化题意:有一棵 \(n\) 个点的树, \(q\) 组询问,每次询问回答两点间的距离. 令 \(dis[i][j]\) 表示 \(i\) 到 \(j\) 的距离,根节点为 \(rt\) ,则有 ...
- 同一份代码怎能在不同环境表现不同?记一个可选链因为代码压缩造成的bug
壹 ❀ 引 某一天,CSM日常找我反馈客户紧急工单,说有一个私有部署客户升级版本后,发现一个功能使用不太正常.因为我们公司客户分为两种,一种是SaaS客户,客户侧使用的版本被动跟随主版本变动,而私有部 ...
- JVM详解
1 JVM运行机制概述 JVM运行机制 类加载机制: 类加载过程由类加载器来完成,即由ClassLoader及其子类实现,有隐式加载和显式加载两种方式.隐式加载是指在使用new等方式创建对象时会隐式调 ...
- Dota2参议院
Dota2参议院 Dota2的世界里有两个阵营:Radiant天辉和Dire夜魇 Dota2参议院由来自两派的参议员组成.现在参议院希望对一个Dota2游戏里的改变作出决定.他们以一个基于轮转过程的投 ...
- SpringBoot使用git-commit-id-maven-plugin打包
简介 git-commit-id-maven-plugin 是一个maven 插件,用来在打包的时候将git-commit 信息打进jar中. 这样做的好处是可以将发布的某版本和对应的代码关联起来,方 ...
- haproxy ssl证书配置
通常情况下,web应用程序的ssl证书放置于nginx的服务器,但很多时候前面会加一次负载均衡,使用HAProxy可以实现https的证书安全,从客户浏览器到HAProxy代理服务器之间为ssl加密传 ...
- Uniapp+Nodejs实现外卖App项目1-项目介绍
项目介绍 本项目采用uniapp和nodejs(数据接口).mongodb等技术实现了一个类似美团外卖的简易APP.项目主要目的是为了快速上手,如何快速使用uniapp开发一个app项目,同时掌握一些 ...
- ERROR 1820 (HY000): You must reset your password using ALTER USER statement
新安装好的mysql5.7数据库,用root登录以后执行操作报这个错. 解决方法: mysql> alter user 'root'@'localhost' identified by 'roo ...
- Mac技巧之苹果电脑上将一个软件进程的 CPU 占用率限制在指定范围内:cputhrottle
苹果电脑 Mac OS X 系统上,我们可以用 cputhrottle 这个免费工具,配合活动监视器和终端,把一个软件进程的 CPU 占用率限制在指定值(比如 20%)以内,以防止应为它 " ...