caffe中添加新层(差分层)

caffe中添加新层(最新版本2017.8)

正向直接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  
(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_.diff_cutoff_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);
} 


(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: 147 (last added: BatchCLuster)
message LayerParameter {

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

optional DiffCutoffParameter diffcutoff_param = 147;

任意位置出定义层的参数

message DiffCutoffParameter 
{ 
optionalfloat  diff_scale = 1 [default = 1];//默认梯度不缩放
}
(4)最后重新编译caffe即可
设置train.prototxt

layer {
name: "diff_1"
type: "DiffCutoff"
bottom: "conv1"
top: "diff_1"
diff_cutoff_param {
diff_scale: 0.0001
}
}
(5)放入到相应的位置,然后运行caffe,就可以了!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值