caffe 添加自定义层(custom layer)

《剖析Caffe源码之Layer》可以知道layer是所有层的基类,由此类派生出各种不同的不同的层,其如下图所示:

由此扩展出了各种不同的层,基本能满足要求,但是有时候在搭建拓扑网络时,所需要的层并没有实现,这时就需要用户自己新添加一个layer。添加layer过程相对较为简单,下面将举一个例子进行说明。

用例

下面将以双曲线余弦函数为例子,说明添加一个custom layer过程:

将该层命名为cosh

添加头文件

首先添加cosh 层头文件,头文件名为:cosh_layer.hpp,存放路径为\include\caffe\layers\文件夹下面,

其内容如下:

#ifndef CAFFE_COSH_LAYER_HPP_
#define CAFFE_COSH_LAYER_HPP_

#include <vector>

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



namespace caffe {

/**
 * @brief cosh layer.
 */
template <typename Dtype>
class CoshLayer : public Layer<Dtype> {
 public:
  /**
   * @param param provides.
   */
  explicit CoshLayer(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 "Cosh"; }
  virtual inline int ExactNumBottomBlobs() const { return 1; }

  virtual inline int MinTopBlobs() const { return 1; }
  virtual inline int MaxTopBlobs() 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);


  /// @brief Not implemented -- AccuracyLayer cannot be used as a loss.
  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  // CAFFE_COSH_LAYER_HPP_

其中有几个需要特别说明的是:

1:inline const char* type()返回的是Layer 类型,要改成个该层名字一样,标明该层的类型,对查找到该层比较关键。

2:ExactNumBottomBlobs():表明该层作为输入Blob的个数,cosh层输入为1个

3:MinTopBlobs和MaxTopBlobs:该层输出Blob的最小和最大输出数目

4:由于该层没有参数,不需要添加参数

添加CPP文件,主要为该层实现部分,命名为Cosh_layer.cpp,文件位于:src\caffe\layers目录下,主要实现以下几个函数功能:

LayerSetUp

setup函数,主要对该层允许前一个变量进行设置,比如该层参数等等,由于该层没有参数,所以为空

Reshape

reshape()函数定义该层输出的shape,记住caffe中的处理原则就是在该层的输出top定义shape,不能在输入bottom定义shape,由于cosh函数输出的shape和输入的shape一样,故实现如下:

template <typename Dtype>
void CoshLayer<Dtype>::Reshape(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {

  top[0]->shape(bottom[0]->num(), bottom[0]->count(), bottom[0]->height(),   bottom[0]->width());
 
}

前向传播

前向传播实现,实现上述公式:

template <typename Dtype>
void CoshLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  Dtype accuracy = 0;
  const Dtype* bottom_data = bottom[0]->cpu_data();
  const Dtype* top_data = top[0]->cpu_data();

    for (int i = 0; i < bottom[0]->count(); ++i) {
      top_data[i] = (exp(bottom_data[i]) + exp(-bottom_data[i]))/2;
    }
}
template <typename Dtype>
void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top)
{
  Forward_cpu(bottom, top)
}

如果有英伟达GPU可以使用CUDA实现,没有GPU可以直接调用CPU的实现

反向传播

由于该层不需要反向传播,直接为空。

template <typename Dtype>
void CoshLayer<Dtype>:: Backward_cpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom)
{
}
template <typename Dtype>
void CoshLayer<Dtype>:: Backward_gpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom)
{
}

注册Layer

注册该layer

#ifdef CPU_ONLY
STUB_GPU(CoshLayer);
#endif

INSTANTIATE_CLASS(CoshLayer);
REGISTER_LAYER_CLASS(Cosh);

整体实现如下:

#include <functional>
#include <utility>
#include <vector>

#include "caffe/layers/cosh_layer.hpp"
#include "caffe/util/math_functions.hpp"

namespace caffe {

template <typename Dtype>
void CoshLayer<Dtype>::LayerSetUp(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
}

template <typename Dtype>
void CoshLayer<Dtype>::Reshape(
  const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {

  top[0]->shape(bottom[0]->num(), bottom[0]->count(), bottom[0]->height(),   bottom[0]->width());
 
}

template <typename Dtype>
void CoshLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  Dtype accuracy = 0;
  const Dtype* bottom_data = bottom[0]->cpu_data();
  const Dtype* top_data = top[0]->cpu_data();

    for (int i = 0; i < bottom[0]->count(); ++i) {
      top_data[i] = (exp(bottom_data[i]) + exp(-bottom_data[i]))/2;
    }
}
template <typename Dtype>
void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top)
{
  Forward_cpu(bottom, top)
}

template <typename Dtype>
void CoshLayer<Dtype>:: Backward_cpu(const vector<Blob<Dtype>*>& top,
      const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom)
{
}
template <typename Dtype>
void CoshLayer<Dtype>:: Backward_gpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom)
{
}


#ifdef CPU_ONLY
STUB_GPU(CoshLayer);
#endif

INSTANTIATE_CLASS(CoshLayer);
REGISTER_LAYER_CLASS(Cosh);

}  // namespace caffe

由于该层不需要添加参数,所以没有必要修改caffe.proto添加layer自定义结构,如果用户需要添加新的自定义层的参数,则需要在LayerParameter添加自定义结构,对LayerParameter不了解的,可以查看《剖析Caffe源码之Net---NetParameter参数》

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huo的藏经阁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值