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

Densely connected convolutional networks(DenseNet)论文解读以及运行(Caffe)

程序员文章站 2024-03-15 15:41:11
...

DenseNet网络是应用由于分类任务中,在目前较好的分类网络ResNets,他们之前存在着很多的不同。下面先来说一说。
先来看一看网络模型结构:
Densely connected convolutional networks(DenseNet)论文解读以及运行(Caffe)
DenseNet主要解决的问题是缓解了消失梯度的问题,增强了特征的传播,促进了特征再利用,大大减少了参数的数量,使网络模型模型进行缩减。
这篇文章中作者主要用了DenseNet-121(k=32),DenseNet-169(k=32),DenseNet-201(k=32),DenseNet-161(k=48),在三个数据集中进行测试。下图是测试结果。
Densely connected convolutional networks(DenseNet)论文解读以及运行(Caffe)
DenseNet是一种密集的连接模式的直观效果,它需要的参数比传统的娟娟网络少,无需重新学习冗余的特征图,改善看网络中的信息流和梯度。对于ResNet是采用合并之前所有层的特征到一层的方法。
下面是图片输入后进行操作,值得注意的是Dense里面每一张特征图谱的连接的前提条件必须是特征图谱的大小一致,不然的话也是不可能连接的在文章中作者说的并不是很清楚,我们可以从提供的代码中进行解读,以及对于图像是如何进行降维的在文中我们可以知道两个Dense之间是有一个卷积层和一个pooling层,降维的操作主要是在pooling层中进行,卷积层并没有。
Densely connected convolutional networks(DenseNet)论文解读以及运行(Caffe)
下面是文章的链接以及代码的链接:
https://arxiv.org/pdf/1608.06993.pdf
https://github.com/liuzhuang13/DenseNet
一个博客对文章的翻译:
https://blog.csdn.net/tumi678/article/details/78667966?locationNum=7&fps=1

代码实现(Caffe)

后续pytorch以及keras等代码实现之后补充
在利用本文提供的代码对自己的数据进行训练:网络结构的prototxt文件地址:https://github.com/shicai/DenseNet-Caffe
在利用的时候出现的问题:
Question:https://github.com/shicai/DenseNet-Caffe/issues/10
fine-tuning:https://github.com/shicai/DenseNet-Caffe/issues/8
[libprotobuf ERROR google/protobuf/text_format.cc:245] Error parsing text-format caffe.NetParameter: 54:14: Message type “caffe.PoolingParameter” has no field named “ceil_mode”.
解决办法:https://github.com/BVLC/caffe/pull/3057/files
其中,include/caffe/vision_layers.hpp,由于caffe结构已经修改,没有这个文件了,经过查看之后,发现该文件是:/home/ccf/caffe/include/caffe/layers/pooling_layer.hpp
第一步:/home/ccf/caffe/include/caffe/layers/pooling_layer.hpp

   int height_, width_;
   int pooled_height_, pooled_width_;
   bool global_pooling_;
+  bool ceil_mode_;
   Blob<Dtype> rand_idx_;
   Blob<int> max_idx_;
 };

第二步: src/caffe/layers/pooling_layer.cpp

       || (!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();
   if (global_pooling_) {
     kernel_h_ = bottom[0]->height();
     kernel_w_ = bottom[0]->width();
@@ -90,10 +91,18 @@ void PoolingLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
     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.

第三步:src/caffe/proto/caffe.proto

   // 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];
 }

 message PowerParameter {

之后对caffe重新编译make -j128