回忆一下图 7.2.1中的卷积示例。输入的高度和宽度均为 3,卷积核的高度和宽度均为 2,从而产生具有维度的输出表示2×2. 假设输入形状是 nh×nw卷积核形状为 kh×kw,输出形状将是 (nh−kh+1)×(nw−kw+1):我们只能将卷积核移动到它用完像素以应用卷积为止。
在下文中,我们将探索许多技术,包括填充和跨步卷积,它们可以更好地控制输出的大小。作为动机,请注意,由于内核的宽度和高度通常大于1,在应用许多连续的卷积之后,我们往往会得到比输入小得多的输出。如果我们从一个240×240像素图像,10层层5×5卷积将图像缩小为200×200像素,切片30%的图像,并用它抹掉原始图像边界上的任何有趣信息。填充是处理此问题的最流行的工具。在其他情况下,我们可能希望大幅降低维数,例如,如果我们发现原始输入分辨率很笨重。跨步卷积是一种流行的技术,可以在这些情况下提供帮助。
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
7.3.1. 填充
如上所述,应用卷积层时的一个棘手问题是我们往往会丢失图像周边的像素。考虑 图 7.3.1,该图将像素利用率描述为卷积核大小和图像内位置的函数。角落里的像素几乎没有被使用。
由于我们通常使用小内核,对于任何给定的卷积,我们可能只会丢失几个像素,但是当我们应用许多连续的卷积层时,这可能会累加起来。这个问题的一个直接解决方案是在输入图像的边界周围添加额外的填充像素,从而增加图像的有效尺寸。通常,我们将额外像素的值设置为零。在 图 7.3.2中,我们填充一个3×3输入,将其大小增加到5×5. 相应的输出然后增加到4×4矩阵。阴影部分是第一个输出元素以及用于输出计算的输入和内核张量元素:0×0+0×1+0×2+0×3=0.
一般来说,如果我们总共添加ph填充行(大约一半在顶部,一半在底部)和总共pw填充列(大约一半在左边,一半在右边),输出形状将是
这意味着输出的高度和宽度将增加 ph和pw, 分别。
在许多情况下,我们会想要设置ph=kh−1和 pw=kw−1给输入和输出相同的高度和宽度。这样在构建网络时更容易预测每一层的输出形状。假如说kh这里很奇怪,我们会垫ph/2高度两侧的行。如果 kh是偶数,一种可能是填充 ⌈ph/2⌉输入顶部的行和 ⌊ph/2⌋底部的行。我们将以相同的方式填充宽度的两侧。
CNN 通常使用具有奇数高度和宽度值的卷积核,例如 1、3、5 或 7。选择奇数核大小的好处是我们可以保留维度,同时在顶部和底部填充相同数量的行,并且左右的列数相同。
此外,这种使用奇数内核和填充来精确保持维度的做法提供了文书上的好处。对于任意一个二维张量X
,当核的大小为奇数,且各边的padding行数和列数相同时,产生与输入等高等宽的输出,我们知道输出是通过cross计算