| 228 | |
| 229 | template <typename Dtype> |
| 230 | void PoolingLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, |
| 231 | const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { |
| 232 | if (!propagate_down[0]) { |
| 233 | return; |
| 234 | } |
| 235 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 236 | Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); |
| 237 | // Different pooling methods. We explicitly do the switch outside the for |
| 238 | // loop to save time, although this results in more codes. |
| 239 | caffe_set(bottom[0]->count(), Dtype(0), bottom_diff); |
| 240 | // We'll output the mask to top[1] if it's of size >1. |
| 241 | const bool use_top_mask = top.size() > 1; |
| 242 | const int* mask = NULL; // suppress warnings about uninitialized variables |
| 243 | const Dtype* top_mask = NULL; |
| 244 | switch (this->layer_param_.pooling_param().pool()) { |
| 245 | case PoolingParameter_PoolMethod_MAX: |
| 246 | // The main loop |
| 247 | if (use_top_mask) { |
| 248 | top_mask = top[1]->cpu_data(); |
| 249 | } else { |
| 250 | mask = max_idx_.cpu_data(); |
| 251 | } |
| 252 | for (int n = 0; n < top[0]->num(); ++n) { |
| 253 | for (int c = 0; c < channels_; ++c) { |
| 254 | for (int ph = 0; ph < pooled_height_; ++ph) { |
| 255 | for (int pw = 0; pw < pooled_width_; ++pw) { |
| 256 | const int index = ph * pooled_width_ + pw; |
| 257 | const int bottom_index = |
| 258 | use_top_mask ? top_mask[index] : mask[index]; |
| 259 | bottom_diff[bottom_index] += top_diff[index]; |
| 260 | } |
| 261 | } |
| 262 | bottom_diff += bottom[0]->offset(0, 1); |
| 263 | top_diff += top[0]->offset(0, 1); |
| 264 | if (use_top_mask) { |
| 265 | top_mask += top[0]->offset(0, 1); |
| 266 | } else { |
| 267 | mask += top[0]->offset(0, 1); |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | break; |
| 272 | case PoolingParameter_PoolMethod_AVE: |
| 273 | // The main loop |
| 274 | for (int n = 0; n < top[0]->num(); ++n) { |
| 275 | for (int c = 0; c < channels_; ++c) { |
| 276 | for (int ph = 0; ph < pooled_height_; ++ph) { |
| 277 | for (int pw = 0; pw < pooled_width_; ++pw) { |
| 278 | int hstart = ph * stride_h_ - pad_h_; |
| 279 | int wstart = pw * stride_w_ - pad_w_; |
| 280 | int hend = min(hstart + kernel_h_, height_ + pad_h_); |
| 281 | int wend = min(wstart + kernel_w_, width_ + pad_w_); |
| 282 | int pool_size = (hend - hstart) * (wend - wstart); |
| 283 | hstart = max(hstart, 0); |
| 284 | wstart = max(wstart, 0); |
| 285 | hend = min(hend, height_); |
| 286 | wend = min(wend, width_); |
| 287 | for (int h = hstart; h < hend; ++h) { |