从caffe中新增layer(cpp版本)

在caffe 中增加一个什么都不做的layer(不考虑forward&backward算法,只考虑打通流程)

英文教程 https://github.com/BVLC/caffe/wiki/Development#developing-new-layers

一 修改 /src/caffe/proto/caffe.proto

1 在 LayerParameter 增加

optional MyLayerParameter my_layer_param = 147; (这个ID :147。是因为最近的layerid是146 增加新的layer的话,id数字递增就好了)

2 添加 自己的 MyLayerParameter

message MyLayerParameter {
  // add MyLayerParameter
  optional float pam = 1 [default = 1.0];// 增加一个变量,调研一下怎么获取。
  enum Engine {
    DEFAULT = 0;
    CAFFE = 1;
    CUDNN = 2;
  }
  optional Engine engine = 2 [default = DEFAULT];
}

二 在include/layers/ 增加 MyLayer .hpp文件。样例

#ifndef CAFFE_MY_LAYER_HPP_
#define CAFFE_MY_LAYER_HPP_

#include 

#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"

namespace caffe {

template <typename Dtype>
class MyLayer : public Layer {
 public:
  explicit MyLayer(const LayerParameter& param)
      : Layer(param) {}
  //virtual void Reshape(const vector*>& bottom,
  //    const vector*>& top);

  virtual inline const char* type() const { return "My"; }
  virtual inline int ExactNumBottomBlobs() const { return 1; }
  virtual inline int MinTopBlobs() const { return 1; }
  virtual void Reshape(const vector*>& bottom,
      const vector*>& top);
 protected:
        virtual void Forward_cpu(const vector*>& bottom,
      const vector*>& top);
        virtual void Backward_cpu(const vector*>& top,
      const vector<bool>& propagate_down, const vector*>& bottom);
        virtual void Forward_gpu(const vector*>& bottom,
      const vector*>& top);
        virtual void Backward_gpu(const vector*>& top,
      const vector<bool>& propagate_down, const vector*>& bottom);

  float myParm;
};

}  // namespace caffe

#endif  // CAFFE_MY_LAYER_HPP_

注意:
1 {*}Blobs()之类的方法 约定了输入和输出的blob的个数。例如在neuron_layer.hpp 中ExactNumBottomBlobs(确切数字),MinTopBlobs 返回值为1.而ConcatLayer 中约定了MinBottomBlobs为1。

2 virtual inline const char* type() const { return “My”; }
这一句话实现是为了在train.prototxt 中加入 my_layer 的的参数。

3 reshape && Forward_cpu && Backward_cpu && Forward_gpu && Backward_gpu 我在hpp中都写了一遍,其中reshape && Forward_cpu && Backward_cpu 在cpp文件中时需要实现的。gpu我没有实现。

三 在 /src/caffe/layers 加入 my_layer.cpp .样例

#include 
#include 
#include 
#include "caffe/layers/my_layer.hpp"

namespace caffe {

template <typename Dtype>
void MyLayer::Reshape(const vector*>& bottom,
      const vector*>& top) {
  top[0]->ReshapeLike(*bottom[0]);
}

template <typename Dtype>
void MyLayer::Forward_cpu(const vector*>& bottom,
    const vector*>& top) {
  const Dtype* bottom_data = bottom[0]->cpu_data();
  Dtype* top_data = top[0]->mutable_cpu_data();
  const int count = bottom[0]->count();
  myParm = this->layer_param_.my_layer_param().pam();
  //std::cout<<"my parm : "<
  for (int i = 0; i < count; ++i) {
    top_data[i] = bottom_data[i];
  }
}

template <typename Dtype>
void MyLayer::Backward_cpu(const vector*>& top,
    const vector<bool>& propagate_down,
    const vector*>& bottom) {
  if (propagate_down[0]) {
    //const Dtype* bottom_data = bottom[0]->cpu_data();
    const Dtype* top_diff = top[0]->cpu_diff();
    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    const int count = bottom[0]->count();
    myParm = this->layer_param_.my_layer_param().pam();
    //std::cout<<"my parm : "<
    for (int i = 0; i < count; ++i) {
      bottom_diff[i] = top_diff[i];
    }
  }
}


#ifdef CPU_ONLY
STUB_GPU(MyLayer);
#endif
INSTANTIATE_CLASS(MyLayer);
REGISTER_LAYER_CLASS(My);
// namespace caffe
}
~                                                                                                                                                                                  
~        

注意:
1 在forward和backward中,data 有cpu_data()和mutable_cpu_data() 之分。
在 http://caffe.berkeleyvision.org/tutorial/net_layer_blob.html 中有所描述。
如果使用mutable或者是_data()时候的疑惑,在这里也许有答案。
http://stackoverflow.com/questions/28710350/when-does-caffe-make-copies-of-the-data
另外cpu_data() 为const Dtype*类型。而mutable_cpu_data() 是 Dtype*类型。关于c++ const的tips可以参考下面的链接: http://blog.csdn.net/melody_fhm/article/details/6683504

2 关于我们在MyLayerParameter的proto定义的 optional float pam = 1 [default = 1.0];我们可以直接以下语句获得。

myParm = this->layer_param_.my_layer_param().pam();

3 最后注册一下这个 layer ,在末尾语句是 REGISTER_LAYER_CLASS(My);另外还有别的注册方式,在/include/layer_factory.hpp中有说明。

四 编译验证。

编译之后,在比较简单的网络mnist中加入我们想要的自定义layer参数(我放在了covn1的后面)验证一下。把这个layer名字叫做debug。prototxt上下文.

layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "debug"
  type: "My" //virtual inline const char* type() const { return "My"; } 作用
  bottom: "conv1"
  top: "conv1_new"
  my_layer_param{
  pam: 1.5
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1_new"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}

在caffe日志中会出现之前写的debug_layer。

I1116 10:57:36.935508  7338 layer_factory.hpp:77] Creating layer debug
I1116 10:57:36.935542  7338 net.cpp:104] Creating Layer debug
I1116 10:57:36.935552  7338 net.cpp:505] debug <- conv1
I1116 10:57:36.935623  7338 net.cpp:478] debug -> conv1_new
I1116 10:57:36.935653  7338 net.cpp:155] Setting up debug
I1116 10:57:36.935680  7338 net.cpp:162] Top shape: 100 20 24 24 (1152000)
I1116 10:57:36.935712  7338 net.cpp:170] Memory required for data: 9530800

这样就应该可以了 :)

你可能感兴趣的:(算法)