深度学习之Caffe完全掌握:用C++开发(自定义)网络层

深度学习之Caffe完全掌握:用C++开发(自定义)网络层(纯cpu实现)


这里写图片描述


意义

当你想实现论文中某个前卫的方法时,caffe中纷繁的网络层模型也不再够用,需要自行定义。同理,你也可以写自己的损失层、数据层和视觉层来加入到网络模型。


我们要做什么

我们要实现一个叫NewLayer的新层,这是一个全通层,它并不做任何事情,只是为了方便展示如何加入自定义的网络层。
我们要添加一个新层,要做以下四件事:

  1. 在include/caffe/layers中创建头文件:new_layer.hpp
  2. 在src/caffe/layers中创建实现文件:new_layer.cpp
  3. 在src/caffe/layers中创建cuda实现文件:new_layer.cu
  4. 在src/caffe/caffe.proto中添加一些定义内容
    注意:之前的要在layer_factory中在 Layer 工厂注册新 Layer 加工函数这一步不再必要了!!

顺便提一句

使用python接口,需要先编译:

[root@master ]# cd /download/caffe
[root@master ]# make pycaffe

开始完成那四件事

我们不实现GPU功能,所以省略第三步。
在include/caffe/layers中创建头文件:new_layer.hpp

#ifndef CAFFE_HANSS_LAYER_HPP_  
#define CAFFE_HANSS_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>  
class NewLayer : public NeuronLayer<Dtype> {  
 public:  
  explicit NewLayer(const LayerParameter& param)  
      : NeuronLayer<Dtype>(param) {}  

  virtual inline const char* type() const { return "AllPass"; }  

 protected:  

  virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,  
      const vector<Blob<Dtype>*>& top);  
  virtual void Forward_gpu(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 Backward_gpu(const vector<Blob<Dtype>*>& top,  
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);  
};  

}  // namespace caffe  

#endif  

在src/caffe/layers中创建实现文件:new_layer.cpp

#include <algorithm>  
#include <vector>  

#include "caffe/layers/new_layer.hpp"  

#include <iostream>  
using namespace std;  
#define DEBUG_AP(str) cout<<str<<endl  
namespace caffe {  

template <typename Dtype>  
void NewLayer<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();  
  for (int i = 0; i < count; ++i) {  
    top_data[i] = bottom_data[i];  
  }  
  DEBUG_AP("Here is New Layer's forwarding.");  
  DEBUG_AP(this->layer_param_.new_param().key());  
}  

template <typename Dtype>  
void NewLayer<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();  
    for (int i = 0; i < count; ++i) {  
      bottom_diff[i] = top_diff[i];  
    }  
  }  
  DEBUG_AP("Here is New Layer's backwarding.");  
  DEBUG_AP(this->layer_param_.new_param().key());  
}  


#ifdef CPU_ONLY  
STUB_GPU(NewLayer);  
#endif  

INSTANTIATE_CLASS(NewLayer);  
REGISTER_LAYER_CLASS(New);  
}  // namespace caffe  

在src/caffe/caffe.proto中添加一些定义内容
注意对照前后代码,添加我写的下面代码里的关于new_layer的代码:

  ... ...
  optional TileParameter tile_param = 138;
  optional WindowDataParameter window_data_param = 129;
  //mymodel
  optional HanssParameter new_param = 155;
}

//mymodel
message NewParameter {  
  optional float key = 1 [default = 0];  
}  

// Message that stores parameters used to apply transformation
// to the data layer's data
message TransformationParameter {
... ...

然后记得重新编译caffe与pycaffe!
最后,写一个网络测试,我只写这个网络层及其它前后两个:

layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "data"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 50
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "drop1"
  type: "Dropout"
  bottom: "ip1"
  top: "ip1"
  dropout_param {
    dropout_ratio: 0.5
  }
}


layer {
  name: "newLayer"
  type: "Hanss"
  bottom: "ip1"
  top: "newLayer"
  hanss_param {
    key: 12.88  
  }
}


layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "newLayer"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 50
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "drop2"
  type: "Dropout"
  bottom: "ip2"
  top: "ip2"
  dropout_param {
    dropout_ratio: 0.4
  }
}

完成,运行即可。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/hanss2/article/details/78838075