目录

Layer介绍

Layer分析

LayerParameter

Class Layer

Layer派生类

Layer源码

Layer构造函数

SetUp函数

Forward函数

Backward函数

总结

参考资料


Layer介绍

如果将caffe比作成一个大楼,那么Blob就是盖成大楼的每块砖瓦,而Layer就是用Blob组成的一层层楼房,layer是神经网络中模型中比较关键的部分,是构成整个计算过程的基础。在上节中,通过对Blob源码进行剖析,对Blob进行了一定了解,而Layer是以Blob作为输入和输出,Layer其本质就是根据输入计算输出,每个layer只完成一类特定的计算,例如convolution操作、pooling、非线性变换、内积运算,以及数据加载、归一化和损失计算等。

上图是一个经典的卷积Layer,是以bottom blob为输入,输出为top blob。

官方文档:http://caffe.berkeleyvision.org/tutorial/net_layer_blob.html

Layer分析

在看Layer源码之前首先需要对整个Layer参数进行了解,Layer的入参除了Blob之外还有很多其他参数,用于配置

LayerParameter

LayerParameter参数的定义在src\caffe\proto\caffe.proto,是采用的ProtoBuf格式,上节已经对ProtoBuf 基本语法进行了解析:

注意在LayerParameter结构之前有一段说明,记录了该message中的number ID使用到了哪里,以及最近新添加的参数,ProtoBuf规定ID不能重复。原代码中对每个参数都进行了详细描述

message LayerParameter {optional string name = 1; // the layer name: Layer 名称optional string type = 2; // the layer type: Layer typerepeated string bottom = 3; // the name of each bottom blob: bottom blob入参名称repeated string top = 4; // the name of each top blob:top blob出参名称// The train / test phase for computation.optional Phase phase = 10; //是用于模型训练还是测试,TRAIN值为0:用于训练,TEST值为1:用于测试// The amount of weight to assign each top blob in the objective.// Each layer assigns a default value, usually of either 0 or 1,// to each top blob.repeated float loss_weight = 5;// 每个输出top blob的loss权重// Specifies training parameters (multipliers on global learning constants,// and the name and other settings used for weight sharing).repeated ParamSpec param = 6; //特定训练参数,可以查看ParamSpec结构// The blobs containing the numeric parameters of the layer.repeated BlobProto blobs = 7; // 每层的参数 blob// Specifies whether to backpropagate to each bottom. If unspecified,// Caffe will automatically infer whether each input needs backpropagation// to compute parameter gradients. If set to true for some inputs,// backpropagation to those inputs is forced; if set false for some inputs,// backpropagation to those inputs is skipped.//// The size must be either 0 or equal to the number of bottoms.repeated bool propagate_down = 11;// Rules controlling whether and when a layer is included in the network,// based on the current NetState.  You may specify a non-zero number of rules// to include OR exclude, but not both.  If no include or exclude rules are// specified, the layer is always included.  If the current NetState meets// ANY (i.e., one or more) of the specified rules, the layer is// included/excluded.repeated NetStateRule include = 8;repeated NetStateRule exclude = 9;// Parameters for data pre-processing.optional TransformationParameter transform_param = 100;// Parameters shared by loss layers.optional LossParameter loss_param = 101;// Layer type-specific parameters.//// Note: certain layers may have more than one computational engine// for their implementation. These layers include an Engine type and// engine parameter for selecting the implementation.// The default for the engine is set by the ENGINE switch at compile-time.optional AccuracyParameter accuracy_param = 102;optional ArgMaxParameter argmax_param = 103;optional BatchNormParameter batch_norm_param = 139;optional BiasParameter bias_param = 141;optional ClipParameter clip_param = 148;optional ConcatParameter concat_param = 104;optional ContrastiveLossParameter contrastive_loss_param = 105;optional ConvolutionParameter convolution_param = 106;optional CropParameter crop_param = 144;optional DataParameter data_param = 107;optional DropoutParameter dropout_param = 108;optional DummyDataParameter dummy_data_param = 109;optional EltwiseParameter eltwise_param = 110;optional ELUParameter elu_param = 140;optional EmbedParameter embed_param = 137;optional ExpParameter exp_param = 111;optional FlattenParameter flatten_param = 135;optional HDF5DataParameter hdf5_data_param = 112;optional HDF5OutputParameter hdf5_output_param = 113;optional HingeLossParameter hinge_loss_param = 114;optional ImageDataParameter image_data_param = 115;optional InfogainLossParameter infogain_loss_param = 116;optional InnerProductParameter inner_product_param = 117;optional InputParameter input_param = 143;optional LogParameter log_param = 134;optional LRNParameter lrn_param = 118;optional MemoryDataParameter memory_data_param = 119;optional MVNParameter mvn_param = 120;optional ParameterParameter parameter_param = 145;optional PoolingParameter pooling_param = 121;optional PowerParameter power_param = 122;optional PReLUParameter prelu_param = 131;optional PythonParameter python_param = 130;optional RecurrentParameter recurrent_param = 146;optional ReductionParameter reduction_param = 136;optional ReLUParameter relu_param = 123;optional ReshapeParameter reshape_param = 133;optional ScaleParameter scale_param = 142;optional SigmoidParameter sigmoid_param = 124;optional SoftmaxParameter softmax_param = 125;optional SPPParameter spp_param = 132;optional SliceParameter slice_param = 126;optional SwishParameter swish_param = 147;optional TanHParameter tanh_param = 127;optional ThresholdParameter threshold_param = 128;optional TileParameter tile_param = 138;optional WindowDataParameter window_data_param = 129;
}

Class Layer

Layer是caffe较为复杂模块,其中layer是所有layer基类,定义所有layer的基本接口,其头文件为caffe\include\caffe\layer.hpp,C++文件在\src\caffe\layer.cpp中

在layer.hpp文件中其大部分接口都是虚函数,具体实现是由各个派生类来实现,class layer中的接口成员主要由以下列表:

Layer方法类别 Layer方法 描述
构造与析构函数 explicit Layer(const LayerParameter& param) 带参数显示构造函数
virtual ~Layer()  析构函数,由具体派生类来实现
Setup以及LayerParameter相关函数

void SetUp

(const vector<Blob<Dtype>*>& bottom,  const vector<Blob<Dtype>*>& top)

bottom Blob为Layer输入参数

top  Blob为其输出参数

为Layer的环境安装函数,主要是参数设置

virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,

const vector<Blob<Dtype>*>& top

虚函数,Layer安装函数,由具体的派生类来实现

virtual void Reshape

(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top)

虚函数,根据bottom的输入shape,设置其输出Blob shape,由具体的派生类来实现
const LayerParameter& layer_param() 获取Layer的入参LayerParameter,将其存储在class layer中的私有变量layer_param_中
virtual void ToProto(LayerParameter* param, bool write_diff = false); 获取Layer的入参LayerParameter,将其存储在class layer中的私有变量layer_param_中
virtual inline const char* type()  虚函数,返回Layer type,具体实现由派生类来实现
前向传播和后向传播 inline Dtype Forward(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top)
前向传播实现函数,bottom为输入,top为输出
inline void Backward(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down,
      const vector<Blob<Dtype>*>& bottom)

后向传播实现函数,bottom为输入,top为输出

propagate_down为与bottom 大小相对的标志位vector,主要用来标记是否做误差梯度

virtual inline bool AllowForceBackward

(const int bottom_index)

虚函数,是否允许强制反向传播,如果 AllowForceBackward(i) == false,则会忽略force_backward设定,具体实现由派生类来实现
 inline bool param_propagate_down(const int param_id) 指定该Layer是否计算相对权值和偏置项的梯度,具体相对谁由param_id指定
inline void set_param_propagate_down(const int param_id, const bool value) 设置该Layer是否计算相对权值或偏置项的梯度,具体相对谁由param_id指定

virtual void Forward_cpu

(const vector<Blob<Dtype>*>& bottom,  const vector<Blob<Dtype>*>& top)

虚函数,CPU版本的前向传播函数,具体实现是由派生类来实现

virtual void Forward_gpu

(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top)

虚函数,GPU版本的前向传播函数,具体实现由派生类来实现
Loss相关 inline Dtype loss(const int top_index)  返回某个top blob标量loss值
inline void set_loss(const int top_index, const Dtype value) 根据给定的index,设置某个top blob标量loss值
virtual inline const char* type()  虚函数,返回Layer type,具体实现由派生类来实现
Blob相关 virtual inline int ExactNumBottomBlobs() 虚函数,返回Bottom Blob的数量,具体实现由派生类来实现
 virtual inline int MinBottomBlobs() 虚函数,返回layer所需要的最小Bottom Blob数量,具体实现由派生类来实现
virtual inline int MaxBottomBlobs() 虚函数,返回layer期望的最多Bottom Blob数量,具体实现由派生类来实现
virtual inline int ExactNumTopBlobs()  虚函数,返回layer的输出Top Bottom Blob数量,具体实现由派生类来实现
virtual inline int MinTopBlobs()  虚函数,返回期望最小的Tob Blob数量,具体实现由派生类来实现
virtual inline int MaxTopBlobs() 虚函数,返回期望最大的Tob Blob数量,具体实现由派生类来实现
virtual inline bool EqualNumBottomTopBlobs() 虚函数,输入bottom与输出top数量是否相同,如果相对返回true,否则返回false,具体实现由派生类来实现
virtual inline bool AutoTopBlobs()  虚函数,是否允许匿名Top Blob,即由该layer自动创建,如为真,在Net:Init()函数会创建足够多的匿名Top Blob来满足该Layer ExactNumTopBlobs()、MinTopBlobs()需求
Layer相关参数 LayerParameter layer_param_ 用于存储LayerParameter参数
Phase phase_ 用于训练train还是test参数
vector<shared_ptr<Blob<Dtype> > > blobs_ Layer内部权值或偏置项,以Blob方式组织
vector<bool> param_propagate_down_ 标志位,是否计算对应参数的误差梯度
vector<Dtype> loss_ 标志位,在目标函数中,是否每个Top Blob都有非零权重

最新的caffe版本中Layer类中去掉了一个Layer是否被多个Net共享相关函数,例如IsShare(),ShareInParallel()等相关函数。

Layer派生类

从上面列表中在Layer大部分关键函数实现都是用的虚函数,并没有实现,而是需要相关的派生类自己实现,由此可知Layer只是个基类,定义了大部分功能的接口。

Caffe最新代码中由此Layer派生出:Data Layer、Vision Layer、Recurrent Layers、Common Layers、Normalization Layers、Activation/Neuron Layers、Utility Layers等几大功能模块。

每次Caffe的更新,都会将添加大量的Layer,下面是最新版本的Layer的分布图,与之前版本已经有了很大不同,但是其基本架构没用多大变化

Layer源码

通过官网资料:http://caffe.berkeleyvision.org/tutorial/net_layer_blob.html,看到每个layer的主要是三个关键函数实现:

setup:初始化layer,在网络链接时要首先调用setup初始化

Forward:前向传播,根据输入bottom计算输出,并发送到top

Backword:反向传播,根据输出的tio 计算出梯度误差,并发送给输出bottom。

官方文档说明如下:

最新版本的caffe Layer CPP文件\src\caffe\layer.cpp如下:

基本上为一个空文件,这个主要是

  • Layer是个基类 大部分接口都是虚函数形式,需要派生类来实现
  • 需要Layer实现的接口较少,直接在 caffe\include\caffe\layer.hpp函数中实现,代码会更简洁

Layer构造函数

Layer显式带参数构造函数源码如下:

通过函数注释说明可知道,构造函数是不需要派生类来实现的,由基类来实现,如果由其他一些特殊参数可以通过Setup函数来实现

  • 首先将将传递的LayerParameter参数保存到layer_param_中,以便供后面进行从处理。
  • 其次将LayerParameter中的phase单独保存到phase中 是用于Train还是Test
  • 最后将LayerParameter中的blobs参数保存到blobs_中,为该层的数值参数的Blob

SetUp函数

SetUp()函数是Net调Layer首先需要做的第一步,对该Layer 一些变量环境进行安装:

该函数入参bottom是Layer的入参,top为Layer出参,Layer的shape在LayerSetup中进行设置。

首先调用CheckBlobCounts()对入参bottom和出参top进行检查,如果该检查不满足要求,可以在派生类中重新写该函数进行覆盖。

LayerSetup()函数由各个派生类来实现,主要是每个派生Layer类可能都有特殊的安装需求,需要在具体的Layer中实现。

Reshape()同样也是由派生类来实现,主要是具体实现的layer,其输出格式每个都不一样。

为每个输出top分配loss权重,从 LayerParameter参数中读取每个出身top的loss_weight,并调用set_loss,将其保存到loss_中,其中0是不参与目标计算,1是参与目标计算:

最后是将找到Blob 中diff_数据指针,调用caffe_set()将其保存到diff_中:

SetUp函数主要完成几件事情

  • 调用派生类的LayerSetup,安装派生类的特殊要求
  • 设置输出top的shape
  • 设置Loss权重

Forward函数

Forward计算前向传播,其代码如下:

其处理首先要区分是在CPU上计算还是在GPU上进行计算,如果是在CPU上则调用Forward_cpu()函数,如果是在GPU上则调用Forward_gpu()函数,

上述两个函数为虚函数,需要在具体的Layer自己来实现。计算完成之后,根据所设置的权重是否计算输出权重,并输出最后的结果到top中。

Backward函数

Bakcward计算其后向传播,其函数源码为:

其处理流程同样区分CPU或者GPU,最后分别调用Backward_cpu或者Backward_gpu:

两个函数同样需要派生的Layer来实现

总结

通过对Layer源码可以看到其layer只是个框架基类,实现功能较少,需要每个相应的派生类来自己实现,后面将会对派生出来的几个大类分别进行分析

参考资料

《21天实战caffe》

http://caffe.berkeleyvision.org/tutorial/net_layer_blob.html

剖析Caffe源码之Layer相关推荐

  1. 剖析Caffe源码之Layer_factory

    在<剖析Caffe源码之Layer>,对Layer代码进行了基本分析,可以知道Layer是所有的其他Layer的基本类,由此来扩展出各个神经网络中所需要的Layer,体现了caffe的可扩 ...

  2. 剖析Caffe源码之Net---Net构造函数

    目录 Net构造函数 读取Prototxt ReadProtoFromTextFile UpgradeNetAsNeeded 设置网络状态 Init函数 FilterNet InsertSplits ...

  3. caffe源码分析-layer

    本文主要分析caffe layer层,主要内容如下: 从整体上说明下caffe的layer层的类别,以及作用 通过proto定义与类Layer简要说明下Layer的核心成员变量; Layer类的核心成 ...

  4. Caffe源码中layer文件分析

    Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/layer.hpp文件的内 ...

  5. 剖析Caffe源码之Net类变量

    在<解析Net的构造函数源码>过程中,可以看到Net类有很多变量,用于存储网络中的各种信息,caffe中类的变量命名规则统一在变量名中加上'_',查看net.hpp代码可以看到使用了很多变 ...

  6. 剖析Caffe源码之Net(上)---NetParameter参数

    前面几篇文章主要分析了Caffe中的Blob和Layer源码,了解到了Caffe中的参数数据结构文件caffe.proto,掌握了各个Layer是如何注册到Caffe中,下面将分析Net层. 在分析N ...

  7. 剖析Caffe源码之InputLayer

    ImageDataLayer可以完成caffe自动读取图片进行模型训练和推断,但是在实际的应用中一般图像都是通过sensor采集而来,将采集得到的图片送到训练好的模型中进行识别.推断,此时就需要用到I ...

  8. 剖析Caffe源码之ImageDataLayer

    目录 ImageDataLayer参数 Source root_folder new_height.new_width is_color crop_size Prototxt配置 Class Imag ...

  9. 剖析Caffe源码之Net---NetParameter参数

    前面几篇文章主要分析了Caffe中的Blob和Layer源码,了解到了Caffe中的参数数据结构文件caffe.proto,掌握了各个Layer是如何注册到Caffe中,下面将分析Net层. 在分析N ...

最新文章

  1. 谷歌知名前 AI 研究员无辜被裁,CEO:调查!
  2. OpenStack 虚拟机启动流程 UML 分析(内含 UML 源码)
  3. git:config命令
  4. POJ - 1922 Ride to School(思维+贪心)
  5. python万年历源代码_python万年历实现代码 含运行结果
  6. 2017-2018-1 20155308 《信息安全系统设计基础》课堂第六章测试(补做)
  7. 一文快速探索视频用户网络画像与应用
  8. 最长等差数列_(Trivial) LeetCode 1027—最长等差子序列
  9. GD32 MCU USB开发学习记录
  10. c# 打印 html,c# – 使用模板打印
  11. WineQQ2012 最新下载
  12. ps初始化html面表时停止工作打不开,PS打不开提示不能初始化因为首选项是无效的该怎么处理?...
  13. 【Books系列】2022年:《拼职场》读书笔记
  14. Swift 5.1 温故而知新笔记系列之第七天
  15. 微信小程序后台销毁时间 演变和总结(热启动时间限制)
  16. 快捷键大全(实用版)
  17. burpsuit 靶场(Directory traversal)
  18. java eclipse 查看版本_怎么查看eclipse的版本号
  19. 欢迎使小程序 mpvue vantweapp
  20. 洛谷3165 CQOI2014 排序机械臂 splay

热门文章

  1. Linux下几种文件传输命令 sz rz sftp scp
  2. MySQL进阶篇(01):基于多个维度,分析服务器性能
  3. 项目开发优化技巧总结
  4. Mask R-CNN
  5. Javascript 正则表达式对象
  6. RedHat系列软件管理(第二版) --源码包安装
  7. MySQL学习笔记_5_SQL语言的设计与编写(上)
  8. Python3之对象垃圾收集机制浅析
  9. ceph Dispatcher模块分析
  10. 【云周刊】第128期:支撑千亿营收背后秘密——首届阿里巴巴研发效能嘉年华...