小数部分来自步幅操作。没有步幅,输出大小应该是output_no_stride = input + 2*pad - filter + 1 = 224. 跨步,使用的常规公式是output_with_stride = floor((input + 2*pad - filter) / stride) + 1 = 112。
在许多编程语言中,整数除法的默认行为是“向零舍入”,因此当分子和分母为正整数时,可以省略下限运算。(参考:Caffe 的卷积实现,Cudnn 文档)
比较有步幅和没有步幅的输出维度
output_with_stride = floor((input + 2*pad - filter) / stride) + 1
= floor((output_no_stride - 1) / stride) + 1
= ceil(output_no_stride / stride)
Caffe 的池化有点复杂,它首先用天花板代替地板,然后如果最后一个池不是严格在图像内部开始,则将大小减小一,如代码所示。
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;
if (pad_h_ || pad_w_) {
// If we have padding, ensure that the last pooling starts strictly
// inside the image (instead of at the padding); otherwise clip the last.
if ((pooled_height_ - 1) * stride_h_ >= height_ + pad_h_) {
--pooled_height_;
}
if ((pooled_width_ - 1) * stride_w_ >= width_ + pad_w_) {
--pooled_width_;
}
CHECK_LT((pooled_height_ - 1) * stride_h_, height_ + pad_h_);
CHECK_LT((pooled_width_ - 1) * stride_w_, width_ + pad_w_);
}
我认为结果大部分与传统公式一致,除非最后一个池完全在原始输入之外。