Caffe | 自定义字段和层

1.自定义字段

最近在老版本的caffe上跑resnext网络的时候出现如下所示的bug,正如我们上一篇文章Caffe | 核心积木Layer层类详解中说到的,在caffe.proto文件的PoolingParameter中没有ceil_mode这个field字段。因此只有在源码中添加这个参数以及相关实现代码,并重新编译caffe。

Message type “caffe.PoolingParameter” has no field named “ceil_mode”.

(1)修改pooling_layer.hpp文件
首先在头文件中添加参数的定义,因为参数在使用之前需要先定义(C/C++语言的特性)。

int height_, width_;
    int pooled_height_, pooled_width_;
    bool global_pooling_;
    bool ceil_mode_;   //添加bug中指出的缺少的属性
    Blob<Dtype> rand_idx_;
    Blob<int> max_idx_;

(2)修改pooling_layer.cpp文件中对应参数
也是在上一篇文章Caffe | 核心积木Layer层类详解中说到的,每一个层(包括当前存在问题的PoolingLayer)都继承自基类LayerParameter。而基类参数中有两个重要的函数如下:

  • Layersetup:读取指定层类的layer param(层参数),为后续reshape做准备。
  • reshape:根据输入该层的bottom blob的形状,和改成定制化的计算策略(也就是当前层的逻辑)计算得到对应的top blob的形状,并预先分配好内存空间。

所以在这里这两个函数跟参数紧密相关,因此我们主要修改的就是pooling_layer.cpp中的这两个函数。
Layersetup函数:

|| (!pool_param.has_stride_h() && !pool_param.has_stride_w()))
        << "Stride is stride OR stride_h and stride_w are required.";
    global_pooling_ = pool_param.global_pooling();

 // 添加的代码-----------------------------------
         ceil_mode_ = pool_param.ceil_mode();      //添加的代码,
                             //主要作用是从参数文件中获取ceil_mode_的参数数值。
// ------------------------------------------------------

    if (global_pooling_) {
      kernel_h_ = bottom[0]->height();
      kernel_w_ = bottom[0]->width();
   if (pad_h_ != 0 || pad_w_ != 0) {
     CHECK(this->layer_param_.pooling_param().pool()
         == PoolingParameter_PoolMethod_AVE
         || this->layer_param_.pooling_param().pool()
         == PoolingParameter_PoolMethod_MAX)
         << "Padding implemented only for average and max pooling.";
     CHECK_LT(pad_h_, kernel_h_);
     CHECK_LT(pad_w_, kernel_w_);

Reshape函数:

 void PoolingLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
       const vector<Blob<Dtype>*>& top) {
   CHECK_EQ(4, bottom[0]->num_axes()) << "Input must have 4 axes, "
       << "corresponding to (num, channels, height, width)";
   channels_ = bottom[0]->channels();
   height_ = bottom[0]->height();
   width_ = bottom[0]->width();
   if (global_pooling_) {
      kernel_h_ = bottom[0]->height();
      kernel_w_ = bottom[0]->width();
    }
 -  pooled_height_ = static_cast<int>(ceil(static_cast<float>(
 -      height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1;
 -  pooled_width_ = static_cast<int>(ceil(static_cast<float>(
 -      width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1;
 +  // Specify the structure by ceil or floor mode
 + 
 + // 添加的代码-----------------------------------
 +  if (ceil_mode_) {
 +    pooled_height_ = static_cast<int>(ceil(static_cast<float>(
 +        height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1;
 +    pooled_width_ = static_cast<int>(ceil(static_cast<float>(
 +        width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1;
 +  } else {
 +    pooled_height_ = static_cast<int>(floor(static_cast<float>(
 +        height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1;
 +    pooled_width_ = static_cast<int>(floor(static_cast<float>(
 +        width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1;
 +  }
 + // ------------------------------------------------------
 + 
    if (pad_h_ || pad_w_) {
      // If we have padding, ensure that the last pooling starts strictly
      // inside the image (instead of at the padding); otherwise clip the last.

(3)修改caffe.proto文件中PoolingParameter
因为所有层的参数定义都存放在caffe.proto文件中,因此修改参数后需要将新的参数添加到该文件对应的层参数中,本例中就将参数添加到PoolingParameter中。

/ If global_pooling then it will pool over the size of the bottom by doing
    // kernel_h = bottom->height and kernel_w = bottom->width
    optional bool global_pooling = 12 [default = false];


 // 添加的代码-----------------------------------
 +  // Specify floor/ceil mode
// 为pooling层添加参数,这样可以在net.prototxt文件中为pooling层设置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yuanCruise

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

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

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

打赏作者

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

抵扣说明:

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

余额充值