我们来看max pooling 在caffe 中怎么实现的吧
首先 reshap的时候:
// If max pooling, we will initialize the vector index part.
if (this->layer_param_.pooling_param().pool() ==
PoolingParameter_PoolMethod_MAX && top.size() == 1) {
max_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_,
pooled_width_);
}
如是max pooling 则需要reshape max_idx 用来记录每次max pooling是 提取哪个地方的位置。
大小为
再看forward:
case PoolingParameter_PoolMethod_MAX:
// Initialize 如果top有两个分支,就有top_mask 没研究这个。遇到再说,目前是进else分支
if (use_top_mask) {
top_mask = top[1]->mutable_cpu_data();
caffe_set(top_count, Dtype(-1), top_mask);
} else {
//get 到 max_idx_的指针
mask = max_idx_.mutable_cpu_data();
caffe_set(top_count, -1, mask);
}
//top_data 全部变成大浮点数的相反数。方便后面的取max运算
caffe_set(top_count, Dtype(-FLT_MAX), top_data);
// 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;
for (int h = hstart; h < hend; ++h) {
for (int w = wstart; w < wend; ++w) {
const int index = h * width_ + w;
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);
if (use_top_mask) {
top_mask += top[0]->offset(0, 1);
} else {
mask += top[0]->offset(0, 1);
}
}
}
break;
其中offset函数是这样定义的:
inline int offset(const int n, const int c = 0, const int h = 0,
const int w = 0) const {
CHECK_GE(n, 0);
CHECK_LE(n, num());
CHECK_GE(channels(), 0);
CHECK_LE(c, channels());
CHECK_GE(height(), 0);
CHECK_LE(h, height());
CHECK_GE(width(), 0);
CHECK_LE(w, width());
return ((n * channels() + c) * height() + h) * width() + w;
}
带入的都是0,1 也就是 平移
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;
//找到对应位置 把上层的梯度加上去就好了
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; 题目链接 题目大意 给定M×N矩阵,求经过给定size为A×B的最大池化处理后结果 M, N <= 2e3, A <= M, B <= N 直接上二维线段树可能被卡常了。 这里用滑动窗口,先对每行使用滑动窗口,再对得到的数组的每列使用滑动窗口即可。...
题目 输入:从控制台获取n,m,a,b;其中n*m为矩阵大小,a*b为滑动窗口大小 矩阵中的值,通过(i*j)mod 10 得到, 在滑动过程中,需要获得每次滑动窗口中的最大值,并存储下来 输出:所有最大值的和 要求及思路 纯暴力求解法,时间复杂度过高,需要使用滑动窗口方法求解 题目为2维矩阵,所以需要对行和列依次使用滑动窗口方法即可 不了解滑动窗口的可以参考一维滑动窗口这篇文章 源码  ...
输出: The shape of x: (1, 4, 4, 1) [[ 4. 3. 1. 8.] [ 7. 2. 6. 3.] [ 2. 0. 1. 1.] [ 3. 4. 2. 5.]] The shape pf y:...
案例: 输出结果:...
Class_4 Caffe Layers之pooling_layer(池化层) 1. 概述 池化是卷积神经网络中较为常用的一种操作,根本目的是实现降采样,简化计算。 目前池化层从作用面区分,可分为全局池化和局部池化。全局池化是相当于在整张图上做池化,每一张特征图最终得到一个池化值,即H*W*C的特征层,经过全局池化以后得到的是1*1*C的池化输出。局部池化就是指定Feature ma...
最近老师让做一个比较多个池化操作的作业。其中包含了max,min,avg,k-max, dynamic k-max。 前面四种还好说,max和avg在pytorch.nn.functional里面就有,min只需要给输入值加个负号,然后在外面加个负号会正即可。k-max也是网上有很多的实现方式。但是关于dynamic k-max的资料在百度里面实在太少。谷歌里面也都是一些tf,或者别的实现方式的,...
Author: Zongwei Zhou | 周纵苇 Weibo: @MrGiovanni Email: [email protected] Overview System: Ubuntu 16.04 LTS Graphics: GeForce GTX 960M/PCIe/SSE2 OS type: 64-bit Python: 2.7.12 Downloads CUDA Linux x86_64 ...
参考文献: https://blog.csdn.net/mounty_fsc/article/details/53114698 [(Caffe)LSTM层分析] https://stackoverflow.com/questions/32225388/lstm-module-for-caffe# [代码来自于该网址]...
下面进行实验,主要检查三个参数的具体含义,即across_spatial , scale_filler ,channel_shared。 across_spatial: 对于每个样本,其到达norm层的张量形状表示为(1,c,h,w),那么across_spatial用来指示标准化是否要跨空间位置 (即(h,w))。如果across_spatial=False,则表示分别对(h,w)空间中的每个位...
参考官方文档:http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb...