| 278 | } |
| 279 | |
| 280 | void Pooling::BackwardAvgPooling(const float* top, const int num, |
| 281 | const int channels, |
| 282 | const int height, const int width, |
| 283 | const int pooled_h, const int pooled_w, |
| 284 | const int kernel_h, const int kernel_w, |
| 285 | const int pad_h, const int pad_w, |
| 286 | const int stride_h, const int stride_w, |
| 287 | float* bottom) { |
| 288 | const int top_offset = pooled_h * pooled_w; |
| 289 | const int bottom_offset = height * width; |
| 290 | memset(bottom, 0, sizeof(float) * num * channels * bottom_offset); |
| 291 | for (int n = 0; n < num; ++n) { |
| 292 | for (int c = 0; c < channels; ++c) { |
| 293 | for (int ph = 0; ph < pooled_h; ++ph) { |
| 294 | for (int pw = 0; pw < pooled_w; ++pw) { |
| 295 | int hstart = ph * stride_h - pad_h; |
| 296 | int wstart = pw * stride_w - pad_w; |
| 297 | int hend = std::min(hstart + kernel_h, height + pad_h); |
| 298 | int wend = std::min(wstart + kernel_w, width + pad_w); |
| 299 | int pool_size = (hend - hstart) * (wend - wstart); |
| 300 | hstart = std::max(hstart, 0); |
| 301 | wstart = std::max(wstart, 0); |
| 302 | hend = std::min(hend, height); |
| 303 | wend = std::min(wend, width); |
| 304 | const int top_index = ph * pooled_w + pw; |
| 305 | for (int h = hstart; h < hend; ++h) { |
| 306 | for (int w = wstart; w < wend; ++w) { |
| 307 | const int index = h * width + w; |
| 308 | bottom[index] += top[top_index] / pool_size; |
| 309 | } |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | top += top_offset; |
| 314 | bottom += bottom_offset; |
| 315 | } |
| 316 | } |
| 317 | } |
| 318 | } // namespace singa |