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

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,
      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种主要的衍生类

  1. data_layer
  2. neuron_layer
  3. loss_layer
  4. common_layer
  5. 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操作
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值