从caffe中新增layer(cpp版本)

来源:互联网 发布:phpstorm mac 激活 编辑:程序博客网 时间:2024/06/05 13:39

在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 <vector>#include "caffe/blob.hpp"#include "caffe/layer.hpp"#include "caffe/proto/caffe.pb.h"namespace caffe {template <typename Dtype>class MyLayer : public Layer<Dtype> { public:  explicit MyLayer(const LayerParameter& param)      : Layer<Dtype>(param) {}  //virtual void Reshape(const vector<Blob<Dtype>*>& bottom,  //    const vector<Blob<Dtype>*>& 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<Blob<Dtype>*>& bottom,      const vector<Blob<Dtype>*>& top); protected:        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);        virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,      const vector<Blob<Dtype>*>& top);        virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& 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 <algorithm>#include <vector>#include <iostream>#include "caffe/layers/my_layer.hpp"namespace caffe {template <typename Dtype>void MyLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,      const vector<Blob<Dtype>*>& top) {  top[0]->ReshapeLike(*bottom[0]);}template <typename Dtype>void MyLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,    const vector<Blob<Dtype>*>& 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 : "<<myParm<<std::endl;  for (int i = 0; i < count; ++i) {    top_data[i] = bottom_data[i];  }}template <typename Dtype>void MyLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,    const vector<bool>& propagate_down,    const vector<Blob<Dtype>*>& 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 : "<<myParm<<std::endl;    for (int i = 0; i < count; ++i) {      bottom_diff[i] = top_diff[i];    }  }}#ifdef CPU_ONLYSTUB_GPU(MyLayer);#endifINSTANTIATE_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 debugI1116 10:57:36.935542  7338 net.cpp:104] Creating Layer debugI1116 10:57:36.935552  7338 net.cpp:505] debug <- conv1I1116 10:57:36.935623  7338 net.cpp:478] debug -> conv1_newI1116 10:57:36.935653  7338 net.cpp:155] Setting up debugI1116 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

这样就应该可以了 :)

2 0
原创粉丝点击