caffe添加新层教程

来源:互联网 发布:棕色牛津鞋搭配 知乎 编辑:程序博客网 时间:2024/05/18 03:35

时间节点2016.04,即caffe重大更新后(每一种层都对应一个同名cpp和hpp文件)。

描述一下本次要实现层的功能:

正向直接copy传播,反向时将梯度放缩指定倍。

这个层对一些特定的网络结构有很重要的辅助作用,比如有时我们的网络存在分支,但我们不希望某一分支影响之前层的更新,那么我们就将梯度放缩0倍。

(1)创建HPP头文件diff_cutoff_layer.hpp

不同功能类型的层所引的头文件也不同,具体大家可以到“caffe/include/caffe/layers”目录下找相似的现成的文件参考 。我们这次写的hpp文件最后也要放在这个目录下。

注意:下面注释包起来的部分为需要注意的部分。

特别注意:命名的时候应严格一致和注意大小写,这一点是导致很多人加层失败的主要原因。

//*****************************************#ifndef CAFFE_DIFFCUTOFF_LAYER_HPP_#define CAFFE_DIFFCUTOFF_LAYER_HPP_//*****************************************#include <vector>#include "caffe/blob.hpp"#include "caffe/layer.hpp"#include "caffe/proto/caffe.pb.h"//*****************************************#include "caffe/layers/neuron_layer.hpp"//*****************************************namespace caffe {template <typename Dtype>//******以后我们层的type: "DiffCutoff" *******  class DiffCutoffLayer : public NeuronLayer<Dtype> {//*****************************************  public:    explicit DiffCutoffLayer(const LayerParameter& param) : NeuronLayer<Dtype>(param) {}    virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>&top);//****我们只需要一个bottom和一个top*****    virtual inline int ExactNumBottomBlobs() const { return 1; }//******以后我们层的type: "DiffCutoff" *******    virtual inline const char* type() const { return "DiffCutoff"; }  protected://******这里只写了CPU功能,故删掉了原本的GPU函数 *******    virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top);    virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);//  *****定义一个Dtype型的标量,用来存储梯度放缩倍数***     Dtype diff_scale;    };} #endif  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

(2)创建diff_cutoff_layer.cpp文件

CPP文件应当位于src/caffe/layers下

#include <algorithm>#include <vector>//*****************************************#include "caffe/layers/diff_cutoff_layer.hpp"//*****************************************#include "caffe/util/math_functions.hpp"namespace caffe {  template <typename Dtype>  void DiffCutoffLayer<Dtype>::LayerSetUp(    const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {    NeuronLayer<Dtype>::LayerSetUp(bottom, top); // 因为对前向传播不修改,因此top的shape应和bottom的shape相同    top[0]->Reshape(bottom[0]->shape());   }  template <typename Dtype>  void DiffCutoffLayer<Dtype>::Forward_cpu(    const vector<Blob<Dtype>*>& bottom,    const vector<Blob<Dtype>*>& top) { // 前向传播直接将bottom的数据copy到top    const int count = top[0]->count();    caffe_copy(        count,        bottom[0]->cpu_data(),        top[0]->mutable_cpu_data());  }  template <typename Dtype>  void DiffCutoffLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {    const int count = top[0]->count();    const Dtype* top_diff = top[0]->cpu_diff();  //读取我们实际指定的梯度放缩倍数,注意我们的参数名为diff_scale    diff_scale= this->layer_param_.diffcutoff_param().diff_scale();// 如果bottom前向传播完成,我们就把top的diff放缩后赋给bottom的diff    if (propagate_down[0]) {      Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();      caffe_cpu_axpby(      count,      diff_scale,      top_diff,      Dtype(0),      bottom_diff);    }    }#ifdef CPU_ONLY  STUB_GPU(DiffCutoffLayer);#endif  INSTANTIATE_CLASS(DiffCutoffLayer);  REGISTER_LAYER_CLASS(DiffCutoff);} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

(3)修改src\caffe\proto\caffe.proto文件

这里我们要为我们新写的层添加参数和消息函数

【1】由于我们的层有一个diff_scale参数,因此我们首先应该在message LayerParameter {}中添加新参数信息。添加信息时,首先要制定一个唯一ID,这个ID的可选值可以由这句话看出:

// NOTE// Update the next available ID when you add a new LayerParameter field.//// LayerParameter next available layer-specific ID: 143 (last added: BatchCLuster)message LayerParameter {
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

由上图可以看出,可选的ID为143。 
于是我们就可以添加这样一行:

  optional DiffCutoffParameter diffcutoff_param = 143;
  • 1
  • 1

【2】在任意位置添加消息函数

message DiffCutoffParameter {  optional float diff_scale = 1 [default = 1]; //默认梯度不缩放}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

【3】 在message V1LayerParameter {}中添加以下内容

在enum LayerType {}中添加唯一ID,只要在这里不重复即可。

   DIFF_CUTOFF=45;
  • 1
  • 1

外面接着添加,同样ID也是只要不重复即可

  optional DiffCutoffParameter diffcutoff_param = 46;
  • 1
  • 1

【4】 在message V0LayerParameter {}添加参数定义

  optional float diff_scale = 47 [default = 1]; 
  • 1
  • 1

(4)最后重新编译caffe即可

使用方法举例如下:

layer {  name: "diff_1"  type: "DiffCutoff"  bottom: "conv1"  top: "diff_1"  diff_cutoff_param {    diff_scale: 0.0001  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

(5)忠告与建议

(1)一定要注意大小写、一定要注意大小写、一定要注意大小写

(2)不会写、不确定,就去找caffe现有的层来参考模仿

(3)caffe数据操作的函数定义在src/caffe/util/math_functions.cpp, 
大家也可以参考这位同学的博客 
http://blog.csdn.net/seven_first/article/details/47378697

原创粉丝点击