in src/model/layer/pooling.cc [26:84]
void Pooling::Setup(const Shape& in_sample, const LayerConf& conf) {
Layer::Setup(in_sample, conf);
PoolingConf pool_conf = conf.pooling_conf();
if (pool_conf.has_kernel_size()) {
kernel_w_ = kernel_h_ = pool_conf.kernel_size();
} else {
kernel_w_ = pool_conf.kernel_w();
kernel_h_ = pool_conf.kernel_h();
}
CHECK_GT(kernel_w_, 0u);
CHECK_GT(kernel_h_, 0u);
if (pool_conf.has_pad()) {
pad_w_ = pad_h_ = pool_conf.pad();
} else {
pad_w_ = pool_conf.pad_w();
pad_h_ = pool_conf.pad_h();
}
CHECK_GE(pad_w_, 0u);
CHECK_GE(pad_h_, 0u);
if (pool_conf.has_stride()) {
stride_w_ = stride_h_ = pool_conf.stride();
} else {
stride_w_ = pool_conf.stride_w();
stride_h_ = pool_conf.stride_h();
}
CHECK_GT(stride_w_, 0u);
CHECK_GE(stride_h_, 0u); // 0 for 1D pooling
pool_ = pool_conf.pool();
CHECK(pool_ == PoolingConf_PoolMethod_AVE ||
pool_ == PoolingConf_PoolMethod_MAX ||
pool_ == PoolingConf_PoolMethod_STOCHASTIC)
<< "Padding implemented only for average and max pooling.";
CHECK_EQ(in_sample.size(), 3u);
channels_ = in_sample.at(0);
height_ = in_sample.at(1);
width_ = in_sample.at(2);
pooled_height_ = 1;
if (pool_conf.ceil()) {
// TODO(wangwei): caffe also ensures the last pooling window starts strictly
// within the original area
if (stride_h_ > 0)
pooled_height_ = static_cast<int>(ceil(static_cast<float>(
height_ + 2 * pad_h_ - kernel_h_) / stride_h_)) + 1;
pooled_width_ = static_cast<int>(ceil(static_cast<float>(
width_ + 2 * pad_w_ - kernel_w_) / stride_w_)) + 1;
}
else {
if (stride_h_ > 0)
pooled_height_ =
static_cast<size_t>((height_ + 2 * pad_h_ - kernel_h_) / stride_h_) + 1;
pooled_width_ =
static_cast<size_t>((width_ + 2 * pad_w_ - kernel_w_) / stride_w_) + 1;
}
out_sample_shape_ = vector<size_t>{channels_, pooled_height_, pooled_width_};
}