您的位置:首页 > Web前端

Caffe源码解读(三):Layer类的源码解读

2017-04-16 23:42 501 查看
Layer是Caffe模型的本质内容和执行计算基单元。

作用

Layer可以进行很多运算,如convolve(卷积)、pooling(池化)、inner product(内积),rectified-linear和sigmoid等非线性运算,元素级的数据转换,normalize(归一化)、softmax和hinge等losses(损失计算)。

Layer工作原理



一个 layer 通过 bottom(底部)连接层接收数据,通过 top(顶部)连接层输出数据。

每一个 layer 都定义了 3 种重要的运算:setup(初始化设置),forward(前向传播),backward(反向传播)。

Setup: 在模型初始化时重置 layers 及其相互之间的连接 ;

Forward: 从 bottom 层中接收数据,进行计算后将输出送入到 top 层中;

Backward: 给定相对于 top 层输出的梯度,计算其相对于输入的梯度,并传递到 bottom层。一个有参数的 layer 需要计算相对于各个参数的梯度值并存储在内部。

由于 Caffe 网络的组合性和其代码的模块化,自定义 layer 是很容易的。只要定义好 layer的 setup(初始化设置)、forward(前向通道)和backward(反向通道),就可将 layer 纳入到网络中。

Layer成员变量

/** The protobuf that stores the layer parameters */
LayerParameter layer_param_;//caffe.proto中定义了LayerParameter类,定义了它所包含的基本参数
/** The phase: TRAIN or TEST */
Phase phase_;//caffe.proto中定义了枚举型的Phase,值:TRAIN or TEST。
/** The vector that stores the learnable parameters as a set of blobs. */
vector<shared_ptr<Blob<Dtype> > > blobs_;
/** Vector indicating whether to compute the diff of each param blob. */
vector<bool> param_propagate_down_;

/** The vector that indicates whether each top blob has a non-zero weight in
*  the objective function. */
vector<Dtype> loss_;


/** Whether this layer is actually shared by other nets*/
bool is_shared_;

/** The mutex for sequential forward if this layer is shared */
shared_ptr<boost::mutex> forward_mutex_;


Layer类的成员函数

Layer类常用的成员函数,那些简单易懂的就不列出了。

SetUp()

void SetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
InitMutex();
CheckBlobCounts(bottom, top);
LayerSetUp(bottom, top);
Reshape(bottom, top);
SetLossWeights(top);
}


功能:实现一般layer的setup功能。参数bottom用来preshape输入的blobs。参数top用来分配blobs,这些blobs不用shape,shape由Reshape来执行。

LayerSetUp()

virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {}


功能:虚函数,由自定义的Layer继承并实现,功能类似于SetUp。

Forward()

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


功能:根据bottom,计算出top和loss。

bottom:是输入的blobs,它的数据域存储该层的输入数据。

top:经过preshaped的输出的blobs,用来存储该层的输出。

返回值:该层整体loss。

Backward()

inline void Backward(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom);


功能:给定相对于 top 层输出的误差梯度,计算其相对于输入的梯度,并传递到 bottom层。一个有参数的 layer 需要计算相对于各个参数的梯度值并存储在内部。

- propagate_down:一个与bottom长度相等的向量,对应的每一个值表示是否把误差梯度向下传递给bottom。

type()

/**
* @brief Returns the layer type.
*/
virtual inline const char* type() const { return ""; }


param_propagate_down()

/**
* @brief Specifies whether the layer should compute gradients w.r.t. a
*        parameter at a particular index given by param_id.
*
* You can safely ignore false values and always compute gradients
* for all parameters, but possibly with wasteful computation.
*/
inline bool param_propagate_down(const int param_id) {
return (param_propagate_down_.size() > param_id) ?
param_propagate_down_[param_id] : false;
}


Forward_cpu()

/** @brief Using the CPU device, compute the layer output. */
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) = 0;


Forward_gpu()

/**
* @brief Using the GPU device, compute the layer output.
*        Fall back to Forward_cpu() if unavailable.
*/
virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,

4000
const vector<Blob<Dtype>*>& top) {
// LOG(WARNING) << "Using CPU code as backup.";
return Forward_cpu(bottom, top);
}


Backward_cpu()

/**
* @brief Using the CPU device, compute the gradients for any parameters and
*        for the bottom blobs if propagate_down is true.
*/
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) = 0;


Backward_gpu()

/**
1. @brief Using the GPU device, compute the gradients for any parameters and
2.        for the bottom blobs if propagate_down is true.
3.        Fall back to Backward_cpu() if unavailable.
*/
virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
// LOG(WARNING) << "Using CPU code as backup.";
Backward_cpu(top, propagate_down, bottom);
}


5种主要的衍生类

data_layer

neuron_layer

loss_layer

common_layer

vision_layer

data_layer

data_layer主要包含与数据有关的文件。在官方文档中指出data是caffe数据的入口是网络的最低层,并且支持多种格式,在这之中又有5种LayerType:

1. DATA 用于LevelDB或LMDB数据格式的输入的类型,输入参数有source, batch_size, (rand_skip), (backend)。后两个是可选。

2. MEMORY_DATA 这种类型可以直接从内存读取数据使用时需要调用MemoryDataLayer::Reset,输入参数有batch_size, channels, height, width。

3. HDF5_DATA HDF5数据格式输入的类型,输入参数有source, batch_size。

4. HDF5_OUTPUT HDF5数据格式输出的类型,输入参数有file_name。

5. IMAGE_DATA 图像格式数据输入的类型,输入参数有source, batch_size, (rand_skip), (shuffle), (new_height), (new_width)。

其实还有两种WINDOW_DATA, DUMMY_DATA用于测试和预留的接口,不重要。

neuron_layer

同样是数据的操作层,neuron_layer实现里大量激活函数,主要是元素级别的操作,具有相同的bottom,top size。

Caffe中实现了大量激活函数GPU和CPU的都有很多。它们的父类都是NeuronLayer

template <typename Dtype>
class NeuronLayer : public Layer<Dtype>


一般的参数设置格式如下(以ReLU修正线性单元为例):

layers {
name: "relu1"
type: RELU
bottom: "conv1"
top: "conv1"
}


RELU目前使用广泛的激活函数。

loss_layer

loss层计算网络误差,loss_layer.hpp头文件中调用了neuron_layers.hpp。估计是需要调用里面的函数计算Loss,一般来说Loss放在最后一层。caffe实现了大量loss function,它们的父类都是LossLayer。

template <typename Dtype>
class LossLayer : public Layer<Dtype>


common_layer

这一层主要进行的是vision_layer的连接。

声明了9个类型的common_layer,部分有GPU实现:

InnerProductLayer 常常用来作为全连接层

SplitLayer 用于一输入对多输出的场合(对blob)

FlattenLayer 将n * c * h * w变成向量的格式n * ( c * h * w ) * 1 * 1

ConcatLayer 用于多输入一输出的场合

SilenceLayer 用于一输入对多输出的场合(对layer)

(Elementwise Operations) 这里面是我们常说的激活函数层Activation Layers。

EltwiseLayer

SoftmaxLayer

ArgMaxLayer

MVNLayer

vision_layer

主要是实现Convolution和Pooling操作, 主要有以下几个类:

ConvolutionLayer 最常用的卷积操作

Im2colLayer 与MATLAB里面的im2col类似,即image-to-column transformation,转换后方便卷积计算

LRNLayer 全称local response normalization layer,在Hinton论文中有详细介绍ImageNet Classification with Deep Convolutional Neural Networks 。

PoolingLayer Pooling操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  caffe学习