5 #include "caffe/layers/pooling_layer.hpp"
6 #include "caffe/util/math_functions.hpp"
13 template <typename Dtype>
14 void PoolingLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
15 const vector<Blob<Dtype>*>& top) {
16 PoolingParameter pool_param = this->layer_param_.pooling_param();
17 if (pool_param.global_pooling()) {
18 CHECK(!(pool_param.has_kernel_size() ||
19 pool_param.has_kernel_h() || pool_param.has_kernel_w()))
20 << "With Global_pooling: true Filter size cannot specified";
22 CHECK(!pool_param.has_kernel_size() !=
23 !(pool_param.has_kernel_h() && pool_param.has_kernel_w()))
24 << "Filter size is kernel_size OR kernel_h and kernel_w; not both";
25 CHECK(pool_param.has_kernel_size() ||
26 (pool_param.has_kernel_h() && pool_param.has_kernel_w()))
27 << "For non-square filters both kernel_h and kernel_w are required.";
29 CHECK((!pool_param.has_pad() && pool_param.has_pad_h()
30 && pool_param.has_pad_w())
31 || (!pool_param.has_pad_h() && !pool_param.has_pad_w()))
32 << "pad is pad OR pad_h and pad_w are required.";
33 CHECK((!pool_param.has_stride() && pool_param.has_stride_h()
34 && pool_param.has_stride_w())
35 || (!pool_param.has_stride_h() && !pool_param.has_stride_w()))
36 << "Stride is stride OR stride_h and stride_w are required.";
37 global_pooling_ = pool_param.global_pooling();
38 round_mode_ = pool_param.round_mode();
39 if (global_pooling_) {
40 kernel_h_ = bottom[0]->height();
41 kernel_w_ = bottom[0]->width();
43 if (pool_param.has_kernel_size()) {
44 kernel_h_ = kernel_w_ = pool_param.kernel_size();
46 kernel_h_ = pool_param.kernel_h();
47 kernel_w_ = pool_param.kernel_w();
50 CHECK_GT(kernel_h_, 0) << "Filter dimensions cannot be zero.";
51 CHECK_GT(kernel_w_, 0) << "Filter dimensions cannot be zero.";
52 if (!pool_param.has_pad_h()) {
53 pad_h_ = pad_w_ = pool_param.pad();
55 pad_h_ = pool_param.pad_h();
56 pad_w_ = pool_param.pad_w();
58 if (!pool_param.has_stride_h()) {
59 stride_h_ = stride_w_ = pool_param.stride();
61 stride_h_ = pool_param.stride_h();
62 stride_w_ = pool_param.stride_w();
64 if (global_pooling_) {
65 CHECK(pad_h_ == 0 && pad_w_ == 0 && stride_h_ == 1 && stride_w_ == 1)
66 << "With Global_pooling: true; only pad = 0 and stride = 1";
68 if (pad_h_ != 0 || pad_w_ != 0) {
69 CHECK(this->layer_param_.pooling_param().pool()
70 == PoolingParameter_PoolMethod_AVE
71 || this->layer_param_.pooling_param().pool()
72 == PoolingParameter_PoolMethod_MAX)
73 << "Padding implemented only for average and max pooling.";
74 CHECK_LT(pad_h_, kernel_h_);
75 CHECK_LT(pad_w_, kernel_w_);
79 template <typename Dtype>
80 void PoolingLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
81 const vector<Blob<Dtype>*>& top) {
82 CHECK_EQ(4, bottom[0]->num_axes()) << "Input must have 4 axes, "
83 << "corresponding to (num, channels, height, width)";
84 channels_ = bottom[0]->channels();
85 height_ = bottom[0]->height();
86 width_ = bottom[0]->width();
87 if (global_pooling_) {
88 kernel_h_ = bottom[0]->height();
89 kernel_w_ = bottom[0]->width();
91 switch (round_mode_) {
92 case PoolingParameter_RoundMode_CEIL:
93 pooled_height_ = static_cast<int>(ceil(static_cast<float>(
94 height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1;
95 pooled_width_ = static_cast<int>(ceil(static_cast<float>(
96 width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1;
98 case PoolingParameter_RoundMode_FLOOR:
99 pooled_height_ = static_cast<int>(floor(static_cast<float>(
100 height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1;
101 pooled_width_ = static_cast<int>(floor(static_cast<float>(
102 width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1;
105 LOG(FATAL) << "Unknown rounding mode.";
107 if (pad_h_ || pad_w_) {
108 // If we have padding, ensure that the last pooling starts strictly
109 // inside the image (instead of at the padding); otherwise clip the last.
110 if ((pooled_height_ - 1) * stride_h_ >= height_ + pad_h_) {
113 if ((pooled_width_ - 1) * stride_w_ >= width_ + pad_w_) {
116 CHECK_LT((pooled_height_ - 1) * stride_h_, height_ + pad_h_);
117 CHECK_LT((pooled_width_ - 1) * stride_w_, width_ + pad_w_);
119 top[0]->Reshape(bottom[0]->num(), channels_, pooled_height_,
121 if (top.size() > 1) {
122 top[1]->ReshapeLike(*top[0]);
124 // If max pooling, we will initialize the vector index part.
125 if (this->layer_param_.pooling_param().pool() ==
126 PoolingParameter_PoolMethod_MAX && top.size() == 1) {
127 max_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_,
130 // If stochastic pooling, we will initialize the random index part.
131 if (this->layer_param_.pooling_param().pool() ==
132 PoolingParameter_PoolMethod_STOCHASTIC) {
133 rand_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_,
138 // TODO(Yangqing): Is there a faster way to do pooling in the channel-first
140 template <typename Dtype>
141 void PoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
142 const vector<Blob<Dtype>*>& top) {
143 const Dtype* bottom_data = bottom[0]->cpu_data();
144 Dtype* top_data = top[0]->mutable_cpu_data();
145 const int top_count = top[0]->count();
146 // We'll output the mask to top[1] if it's of size >1.
147 const bool use_top_mask = top.size() > 1;
148 int* mask = NULL; // suppress warnings about uninitalized variables
149 Dtype* top_mask = NULL;
150 // Different pooling methods. We explicitly do the switch outside the for
151 // loop to save time, although this results in more code.
152 switch (this->layer_param_.pooling_param().pool()) {
153 case PoolingParameter_PoolMethod_MAX:
156 top_mask = top[1]->mutable_cpu_data();
157 caffe_set(top_count, Dtype(-1), top_mask);
159 mask = max_idx_.mutable_cpu_data();
160 caffe_set(top_count, -1, mask);
162 caffe_set(top_count, Dtype(-FLT_MAX), top_data);
164 for (int n = 0; n < bottom[0]->num(); ++n) {
165 for (int c = 0; c < channels_; ++c) {
166 for (int ph = 0; ph < pooled_height_; ++ph) {
167 for (int pw = 0; pw < pooled_width_; ++pw) {
168 int hstart = ph * stride_h_ - pad_h_;
169 int wstart = pw * stride_w_ - pad_w_;
170 int hend = min(hstart + kernel_h_, height_);
171 int wend = min(wstart + kernel_w_, width_);
172 hstart = max(hstart, 0);
173 wstart = max(wstart, 0);
174 const int pool_index = ph * pooled_width_ + pw;
175 for (int h = hstart; h < hend; ++h) {
176 for (int w = wstart; w < wend; ++w) {
177 const int index = h * width_ + w;
178 if (bottom_data[index] > top_data[pool_index]) {
179 top_data[pool_index] = bottom_data[index];
181 top_mask[pool_index] = static_cast<Dtype>(index);
183 mask[pool_index] = index;
191 bottom_data += bottom[0]->offset(0, 1);
192 top_data += top[0]->offset(0, 1);
194 top_mask += top[0]->offset(0, 1);
196 mask += top[0]->offset(0, 1);
201 case PoolingParameter_PoolMethod_AVE:
202 for (int i = 0; i < top_count; ++i) {
206 for (int n = 0; n < bottom[0]->num(); ++n) {
207 for (int c = 0; c < channels_; ++c) {
208 for (int ph = 0; ph < pooled_height_; ++ph) {
209 for (int pw = 0; pw < pooled_width_; ++pw) {
210 int hstart = ph * stride_h_ - pad_h_;
211 int wstart = pw * stride_w_ - pad_w_;
212 int hend = min(hstart + kernel_h_, height_ + pad_h_);
213 int wend = min(wstart + kernel_w_, width_ + pad_w_);
214 int pool_size = (hend - hstart) * (wend - wstart);
215 hstart = max(hstart, 0);
216 wstart = max(wstart, 0);
217 hend = min(hend, height_);
218 wend = min(wend, width_);
219 for (int h = hstart; h < hend; ++h) {
220 for (int w = wstart; w < wend; ++w) {
221 top_data[ph * pooled_width_ + pw] +=
222 bottom_data[h * width_ + w];
225 top_data[ph * pooled_width_ + pw] /= pool_size;
229 bottom_data += bottom[0]->offset(0, 1);
230 top_data += top[0]->offset(0, 1);
234 case PoolingParameter_PoolMethod_STOCHASTIC:
238 LOG(FATAL) << "Unknown pooling method.";
242 template <typename Dtype>
243 void PoolingLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
244 const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
245 if (!propagate_down[0]) {
248 const Dtype* top_diff = top[0]->cpu_diff();
249 Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
250 // Different pooling methods. We explicitly do the switch outside the for
251 // loop to save time, although this results in more codes.
252 caffe_set(bottom[0]->count(), Dtype(0), bottom_diff);
253 // We'll output the mask to top[1] if it's of size >1.
254 const bool use_top_mask = top.size() > 1;
255 const int* mask = NULL; // suppress warnings about uninitialized variables
256 const Dtype* top_mask = NULL;
257 switch (this->layer_param_.pooling_param().pool()) {
258 case PoolingParameter_PoolMethod_MAX:
261 top_mask = top[1]->cpu_data();
263 mask = max_idx_.cpu_data();
265 for (int n = 0; n < top[0]->num(); ++n) {
266 for (int c = 0; c < channels_; ++c) {
267 for (int ph = 0; ph < pooled_height_; ++ph) {
268 for (int pw = 0; pw < pooled_width_; ++pw) {
269 const int index = ph * pooled_width_ + pw;
270 const int bottom_index =
271 use_top_mask ? top_mask[index] : mask[index];
272 bottom_diff[bottom_index] += top_diff[index];
275 bottom_diff += bottom[0]->offset(0, 1);
276 top_diff += top[0]->offset(0, 1);
278 top_mask += top[0]->offset(0, 1);
280 mask += top[0]->offset(0, 1);
285 case PoolingParameter_PoolMethod_AVE:
287 for (int n = 0; n < top[0]->num(); ++n) {
288 for (int c = 0; c < channels_; ++c) {
289 for (int ph = 0; ph < pooled_height_; ++ph) {
290 for (int pw = 0; pw < pooled_width_; ++pw) {
291 int hstart = ph * stride_h_ - pad_h_;
292 int wstart = pw * stride_w_ - pad_w_;
293 int hend = min(hstart + kernel_h_, height_ + pad_h_);
294 int wend = min(wstart + kernel_w_, width_ + pad_w_);
295 int pool_size = (hend - hstart) * (wend - wstart);
296 hstart = max(hstart, 0);
297 wstart = max(wstart, 0);
298 hend = min(hend, height_);
299 wend = min(wend, width_);
300 for (int h = hstart; h < hend; ++h) {
301 for (int w = wstart; w < wend; ++w) {
302 bottom_diff[h * width_ + w] +=
303 top_diff[ph * pooled_width_ + pw] / pool_size;
309 bottom_diff += bottom[0]->offset(0, 1);
310 top_diff += top[0]->offset(0, 1);
314 case PoolingParameter_PoolMethod_STOCHASTIC:
318 LOG(FATAL) << "Unknown pooling method.";
324 STUB_GPU(PoolingLayer);
327 INSTANTIATE_CLASS(PoolingLayer);