如何给caffe添加新的层

新版的caffe更新之后,增加一个只要在在include/caffe/layers中添加相应的头文件,
在src/layers中添加相应cpp, cu文件。


举例:本次主要给caffe添加normalize_layer层,源码来自caffe_windows中。
(1) 在caffe/layers中新建normalize_layer.hpp

#ifndef CAFFE_NORMALIZE_LAYER_HPP_
#define CAFFE_NORMALIZE_LAYER_HPP_

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

namespace caffe{

    template<typename Dtype>
    class NormalizeLayer : public Layer<Dtype>
    {
    public:
            explicit NormalizeLayer(const LayerParameter &param):Layer<Dtype>(param){}
            virtual void LayerSetUp(const vector<Blob<Dtype>*> &bottom, const vector<Blob<Dtype>*> &top);
            virtual void Reshape(const vector<Blob<Dtype>*> &bottom, const vector<Blob<Dtype>*> &top);
            virtual inline const char* type() const{return "Normalize";}
            virtual inline int ExactNumBottomBlobs() const{return 1;}
            virtual inline int ExactNumTopBlobs()const{return 1;}
        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);

        Blob<Dtype> sum_multiplier_, norm_, squared_;
        std::string normalize_type_;
        bool rescale_;

    };

}

#endif

(2) 在src/caffe/layers中新建normalize_layer.cpp,内容如下:

#include <algorithm>
#include <vector>
#include <cmath>

#include "caffe/layer.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/layers/normalize_layer.hpp"

namespace caffe {

template <typename Dtype>
void NormalizeLayer<Dtype>::LayerSetUp(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  normalize_type_ =
    this->layer_param_.normalize_param().normalize_type();
  rescale_ =
    this->layer_param_.normalize_param().rescale();
}

template <typename Dtype>
void NormalizeLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  top[0]->Reshape(bottom[0]->num(), bottom[0]->channels(),
      bottom[0]->height(), bottom[0]->width());
  squared_.Reshape(bottom[0]->num(), bottom[0]->channels(),
    bottom[0]->height(), bottom[0]->width());
  norm_.Reshape(bottom[0]->num(), 1,
                  bottom[0]->height(), bottom[0]->width());
}

template <typename Dtype>
void NormalizeLayer<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();
  Dtype* square_data = squared_.mutable_cpu_data();
  Dtype* norm_data = norm_.mutable_cpu_data();
  int num = bottom[0]->num();
  int channels = bottom[0]->channels();
  int spatial_dim = bottom[0]->height() * bottom[0]->width();
  if (normalize_type_ == "L2") {
    caffe_sqr<Dtype>(num*channels*spatial_dim, bottom_data, square_data);
    for (int n = 0; n < num; n++) {
      for (int s = 0; s < spatial_dim; s++) {
        norm_data[n*spatial_dim + s] = Dtype(0);
        for (int c = 0; c < channels; c++) {
          norm_data[n*spatial_dim + s] += square_data[(n * channels + c) * spatial_dim + s];
        }
        norm_data[n*spatial_dim + s] += 1e-6;
        norm_data[n*spatial_dim + s] = Dtype(1) / sqrt(norm_data[n*spatial_dim + s]);
        for (int c = 0; c < channels; c++) {
          top_data[(n * channels + c) * spatial_dim + s] = bottom_data[(n * channels + c) * spatial_dim + s] * norm_data[n*spatial_dim + s];
        }
      }
    }
  }
  else if (normalize_type_ == "L1") {
    caffe_abs<Dtype>(num*channels*spatial_dim, bottom_data, square_data);
    for (int n = 0; n < num; n++) {
      for (int s = 0; s < spatial_dim; s++) {
        norm_data[n*spatial_dim +s] = Dtype(0);
        for (int c = 0; c < channels; c++) {
          norm_data[n*spatial_dim + s] += square_data[(n * channels + c) * spatial_dim + s];
        }
        norm_data[n*spatial_dim + s] += 1e-6;
        norm_data[n*spatial_dim + s] = Dtype(1) / norm_data[n*spatial_dim + s];
        for (int c = 0; c < channels; c++) {
          top_data[(n * channels + c) * spatial_dim + s] = bottom_data[(n * channels + c) * spatial_dim + s] * norm_data[n*spatial_dim + s];
        }
      }
    }
  }
  else {
    NOT_IMPLEMENTED;
  }
}

template <typename Dtype>
void NormalizeLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
  const Dtype* top_diff = top[0]->cpu_diff();
  const Dtype* top_data = top[0]->cpu_data();
  const Dtype* bottom_data = bottom[0]->cpu_data();
  const Dtype* square_data = squared_.cpu_data();
  const Dtype* norm_data = norm_.mutable_cpu_data();
  Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();

  int num = bottom[0]->num();
  int channels = bottom[0]->channels();
  int spatial_dim = bottom[0]->height() * bottom[0]->width();
  if (normalize_type_ == "L2") {
    for (int n = 0; n < num; ++n) {
      for (int s = 0; s < spatial_dim; s++) {
        Dtype a = caffe_cpu_strided_dot(channels, top_data + n*channels*spatial_dim + s, spatial_dim, top_diff + n*channels*spatial_dim + s, spatial_dim);
        for (int c = 0; c < channels; c++) {
          bottom_diff[(n * channels + c) * spatial_dim + s] =
            (top_diff[(n * channels + c) * spatial_dim + s] - top_data[(n * channels + c) * spatial_dim + s] * a) * norm_data[n*spatial_dim + s];
        }
      }
    }
  }
  else if(normalize_type_ == "L1") {
    for (int n = 0; n < num; ++n) {
      for (int s = 0; s < spatial_dim; s++) {
        Dtype a = caffe_cpu_strided_dot(channels, top_data + n*channels*spatial_dim + s, spatial_dim, top_diff + n*channels*spatial_dim + s, spatial_dim);
        for (int c = 0; c < channels; c++) {
          bottom_diff[(n * channels + c) * spatial_dim + s] =
            (top_diff[(n * channels + c) * spatial_dim + s] - square_data[(n * channels + c) * spatial_dim + s] * a) * norm_data[n*spatial_dim + s];
        }
      }
    }
  }
  else {
    NOT_IMPLEMENTED;
  }
}


#ifdef CPU_ONLY
STUB_GPU(NormalizeLayer);
#endif

INSTANTIATE_CLASS(NormalizeLayer);
REGISTER_LAYER_CLASS(Normalize);

}  // namespace caffe

(3) 同理如果有.cu文件的实现,则完成cu文件编写。
(4)修改src\caffe\proto\caffe.proto
首先我们看到LayerParameter中提示我们可以使用ID,于是可以添加下面147。

// NOTE
// Update the next available ID when you add a new LayerParameter field.
//
// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)

添加的ID,这里的normalize_para就是以后在训练文件中的参数名。
如:

  pooling_param{
    pool: AVE
    global_pooling: true
  }
  optional PoolingParameter pooling_param = 121;
  optional NormalizeParameter normalize_param = 147;

我们看到normalize_layer这个层有两个参数

  normalize_type_ =
    this->layer_param_.normalize_param().normalize_type();
  rescale_ =
    this->layer_param_.normalize_param().rescale();

于是我们需要添加下面的参数信息:

// add normalization param
message NormalizeParameter {
  optional string normalize_type = 1 [default = "L2"];
  optional bool rescale = 2 [default = false];
}

然后重先编译就可以使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值