欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

caffe跑densenet的错误:Message type "caffe.PoolingParameter" has no field named "ceil_mode".

程序员文章站 2022-05-30 12:15:38
...

最近看了densenet这篇论文,论文作者给了基于caffe的源码,自己在电脑上跑了下,但是出现了Message type “caffe.PoolingParameter” has no field named “ceil_mode”.的错误,现将解决办法记载如下。主要是参考
https://github.com/BVLC/caffe/pull/3057/files)。错误原因:由于caffe的版本的原因,现用的caffe的源码中的pooling层没有ceil_mode
这个函数,因此解决办法也是在现在的源码中网pooling层中添加这个参数以及相关的代码,并重新编译caffe即可。

1、修改pooling_layer.hpp文件PoolingLayer类

在pooling_layer.hpp中往PoolingLayer类中添加ceil_mode_这个参数,修改如下:

    int height_, width_;
    int pooled_height_, pooled_width_;
    bool global_pooling_;
    bool ceil_mode_;   //添加的类成员变量
    Blob<Dtype> rand_idx_;
    Blob<int> max_idx_;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、修改pooling_layer.cpp文件中相关参数

主要涉及到LayerSetUp函数和Reshape函数。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_);
     .......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

3、修改caffe.proto文件中PoolingParameter的定义

因为添加了pooling层的参数,因此需要修改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
         +  optional bool ceil_mode = 13 [default = true];// 为pooling层添加参数,这样可以在net.prototxt文件中为pooling层设置该参数,注意后面需要给其设置一个ID,同时设置一个默认值。
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4、重新编译caffe

返回到caffe的根目录,使用make指令,即可。

 make -j32    // 这里j后面的数字与电脑配置有关系,可以加速编译
  • 1
  • 2

注意:这个流程也是一般修改caffe的层的一般流程:1、主要修改相应层的hpp文件和cpp文件;2、如果有参数的添加或者减少,还需要修改caffe.proto文件对应层的参数即可(注意设置正确的ID以及默认值default);3、重新编译caffe