学习笔记: 源码 pooling_layer.cpp 略懂
来源:互联网 发布:淘宝游戏账号出售 编辑:程序博客网 时间:2024/05/22 11:30
PoolingLayer 相比于 ConvolutionLayer 简单多了……
Layer 三步走:SetUp,Forward 和 Backward.
1. LayerSetUp()
存储相应的layer param,例如 kernel_h, kernel_w,stride 等等。
2. Reshape()
根据 bottom 的形状大小对 top 进行形状大小的计算,并对top进行Reshape(),内存分配。
此外,如果 pooling 层是 max pooling,在 pooling_layer 还会有一个 数据成员 max_idx_ 来进行记录 pooling 过程中局部的 max 的 index。max_idx_ 的 blob 形状大小和 top一样。
3. Forward_cpu()
在 forward 的函数中,利用 switch case 选择 pooling 的类型(e.g. max, ave)。
这里只分析 max pooling。
case PoolingParameter_PoolMethod_MAX:... mask = max_idx_.mutable_cpu_data(); caffe_set(top_count, -1, mask);... caffe_set(top_count, Dtype(-FLT_MAX), top_data); //FLT_MAX 正浮点数最大值 // The main loop for (int n = 0; n < bottom[0]->num(); ++n) { for (int c = 0; c < channels_; ++c) { for (int ph = 0; ph < pooled_height_; ++ph) { for (int pw = 0; pw < pooled_width_; ++pw) { int hstart = ph * stride_h_ - pad_h_; int wstart = pw * stride_w_ - pad_w_; int hend = min(hstart + kernel_h_, height_); int wend = min(wstart + kernel_w_, width_); hstart = max(hstart, 0); wstart = max(wstart, 0); const int pool_index = ph * pooled_width_ + pw; //pool_index 对应 top的位置 for (int h = hstart; h < hend; ++h) { // 在小块中求最大值赋予top_data for (int w = wstart; w < wend; ++w) { //相应的mask[pool_index] 记录最大值的index const int index = h * width_ + w; // index 对应 bottom 的位置 if (bottom_data[index] > top_data[pool_index]) { top_data[pool_index] = bottom_data[index]; if (use_top_mask) { top_mask[pool_index] = static_cast<Dtype>(index); } else { mask[pool_index] = index; } } } } } } // compute offset bottom_data += bottom[0]->offset(0, 1); top_data += top[0]->offset(0, 1); //top_data 指针偏移一个channel_dim( = height * width) if (use_top_mask) { top_mask += top[0]->offset(0, 1); } else { mask += top[0]->offset(0, 1); } } } break; inline int offset(const int n, const int c = 0, const int h = 0, //计算blob在(n, c, h, w)坐标下相应 const int w = 0) const { //内存的index... return ((n * channels() + c) * height() + h) * width() + w; }
4. Backward_cpu()
case PoolingParameter_PoolMethod_MAX: // The main loop if (use_top_mask) { top_mask = top[1]->cpu_data(); } else { mask = max_idx_.cpu_data(); } for (int n = 0; n < top[0]->num(); ++n) { for (int c = 0; c < channels_; ++c) { for (int ph = 0; ph < pooled_height_; ++ph) { for (int pw = 0; pw < pooled_width_; ++pw) { const int index = ph * pooled_width_ + pw; //这里的index是对应top 的index const int bottom_index = use_top_mask ? top_mask[index] : mask[index]; bottom_diff[bottom_index] += top_diff[index]; } } bottom_diff += bottom[0]->offset(0, 1); top_diff += top[0]->offset(0, 1); if (use_top_mask) { top_mask += top[0]->offset(0, 1); } else { mask += top[0]->offset(0, 1); } } } break;
在 max pooling 的后向传播中,只将梯度传播给起作用的 bottom_data,我们在 max_idx_ 中有记录。即只将 top_diff 直接赋给起作用的 bottom_diff,而其他没有起作用的bottom_diff = 0。
0 0
- 学习笔记: 源码 pooling_layer.cpp 略懂
- Caffe源码:pooling_layer.cpp
- 学习笔记: 源码 relu_layer.cpp 略见
- 学习笔记: 源码 inner_product_layer.cpp 略识
- 学习笔记: 源码 accuracy_layer.cpp 略明
- 学习笔记: 源码 softmax_layer.cpp 略通
- 学习笔记: 源码 multinomial_logistic_loss_layer.cpp 略晓
- 学习笔记: 源码 softmax_loss_layer.cpp 略析
- CAFFE源码学习笔记之池化层pooling_layer
- caffe源码c++学习笔记Classifier.cpp
- 学习笔记: 源码 caffe.cpp 初探
- 学习笔记: 源码 solver.cpp 初访
- 学习笔记: 源码 net.cpp 浅析
- 学习笔记: 源码 blob.cpp 初见
- 学习笔记: 源码 conv_layer.cpp 略知
- Caffe源码解析7:Pooling_Layer
- Caffe源码解析7:Pooling_Layer
- Caffe源码解析7:Pooling_Layer
- AJAX之二级联动下拉列表
- 《Unbroken》——Everything is possible
- C++实验6:数组操作
- kali linux2.0安装中文输入法googlepinyin
- Asp.Net面试题
- 学习笔记: 源码 pooling_layer.cpp 略懂
- A Beginner's Guide To Understanding Convolutional Neural Networks
- 小数据集训练深度网络的小技巧
- linux下php-fpm的启动和关闭
- 笔试时常用排序算法时间复杂度和空间复杂度
- A Beginner's Guide To Understanding Convolutional Neural Networks Part 2
- [Leetcode]_26 Remove Duplicates from Sorted Array
- Linux内核 printk知多少
- Oracle 11g通过提高IO吞吐量(修改_db_file_optimizer_read_count)来优化全表扫描