TensorFlow 卷积 padding 策略详解

技术

picture.image


卷积计算是 CNN 最核心的部分,而随着网络结构不断推陈出新(LeNet-5、AlexNet、GoogLeNet、VGG、ResNet、DenseNet、SENet、Xception、ResNeXt、MobileNet、ShuffleNet、NASNet……),卷积类型越来越丰富(二维卷积、三维卷积、空洞卷积、空间可分离卷积、深度可分离卷积、反卷积、变形卷积……)。设计网络时需要特别留意 padding 策略。

在 TensorFlow 中,padding 参数可选项有两种:'SAME' 和 'VALID'。在 TF 1.7 API 中 conv2d 是长这样的:

picture.image

我们先看一个例子:假设输入图片尺寸为 5x5,卷积核尺寸为 3x3,做二维卷积时动图如下:

picture.image

其中虚线格子就表示 padding 的像素(值为 0)。经过 padding,实际输入图片尺寸变成了 7x7,卷积核在 7x7 范围内滑动,分别每个位置产生一个输出像素,最终输出结果尺寸为 5x5。我们发现,输出尺寸与原输入尺寸相同,也就是所谓 'SAME' 方式 padding 名称的由来。为了保证输出与输入尺寸一致,我们可以推出 'SAME' padding 计算公式:

SAME PADDING 计算公式

output_h = input_h

output_w = input_w

pad_h = (kernel_h - 1)/2

pad_w = (kernel_w - 1)/2

前面例子中 kernel_h = kernel_w = 3,所以 pad_h = pad_w = (3 - 1)/2 = 1。

如前所述,使用 'SAME' padding 会在输入图片边界处“无中生有”地加入了一些像素,这很可能破坏原始图片的内容。而 'VALID' padding 则非常守规矩, 卷积核只在“有效的”输入像素点范围内滑动 。用公式表达就是:

VALID PADDING 计算公式

pad_h = 0

pad_w = 0

output_h = input_h - kernel_h + 1

output_w = input_w - kernel_w + 1

下图为一个 'VALID' padding 例子,输入图片尺寸为 4x4,卷积核尺寸为 3x3,输出尺寸为 2x2。

picture.image

以上讨论都是在 stride == 1 和 dilation == 1 时的情况。

当 dilation > 1 时,先计算扩张卷积核尺寸:

dilation_kernel_h = (kernel_h - 1) * dilation_h + 1

dilation_kernel_w = (kernel_w - 1) * dilation_w + 1

之后再将 dilation_kernel_h、dilation_kernel_w 代入前面不同 padding 公式即可得到对应的 padding 尺寸和输出尺寸。一个例子如下:

picture.image

输入图片尺寸为 7x7,卷积核尺寸为 3x3,扩张率为 2x2,使用 'VALID' padding 方法。首先得到扩张后卷积核尺寸为 (3 - 1) * 2 + 1 = 5,即等效为 5x5 卷积核。将该值代入 'VALID' padding 公式,得到输出尺寸为:7 - 5 + 1 = 3,即 3x3,与图中显示一致。

当 stride > 1 时,即使使用 'SAME' padding 方式,输出尺寸依然小于输入尺寸,只是沿用了 stride == 1 的称谓。

SAME PADDING 计算公式(stride > 1)

output_h = ceil(input_h / stride_h)

output_w = ceil(input_w / stride_w)

pad_h = ((output_h - 1) * stride_h + kernel_h - input_h) / 2

pad_w = ((output_w - 1) * stride_w + kernel_w - input_w) / 2

picture.image

如上图为 stride = 2 的情况,输入尺寸为 5x5,卷积核尺寸 3x3。首先通过公式计算得到输出尺寸:output_h = output_w = ceil(5/2) = ceil(2.5) = 3,即 3x3;然后利用公式计算 pad_h = pad_w = ((3 - 1) * 2 + 3 - 5)/2 = 1,与图中一致。

当 stride > 1 时,使用 'VALID' padding 方式,计算过程仍满足卷积核只在“有效的”输入像素点范围内滑动 的约束。

VALID PADDING 计算公式(stride > 1)

pad_h = 0

pad_w = 0

output_h = ceil((input_h - kernel_h + 1) / stride_h)

output_w = ceil((input_w - kernel_w + 1) / stride_w)

picture.image

上图中 input : 5x5,kernel : 3x3,stride : 2x2,output : 2x2,请读者自行核算。

另外,MaxPool 和 AvePool 的输出尺寸计算公式也可从上面公式推导得到。

参考:

【1】 https://github.com/vdumoulin/conv\_arithmetic

【2】 TensorFlow 源码 v1.7


picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动云原生降本增效实践
本次分享主要介绍字节跳动如何利用云原生技术不断提升资源利用效率,降低基础设施成本;并重点分享字节跳动云原生团队在构建超大规模云原生系统过程中遇到的问题和相关解决方案,以及过程中回馈社区和客户的一系列开源项目和产品。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论