动手学深度学习 5.4 池化层

前言

从零开始学习ai文章系列计划是个人在《动手学深度学习》和《磨菇书》两本书的学习中的个人笔记,文章也会以课本中的章节分开,即每个章节一片笔记。我会尽量的把主要内容以及遇到的难点进行记录与解决,如果哪里有错误的欢迎指正。或者不清晰的可以直接查看原文部分。

《动手学深度学习》原文(课本):https://tangshusen.me/Dive-into-DL-PyTorch/#/

《动手学深度学习》代码:https://github.com/ShusenTang/Dive-into-DL-PyTorch

(由于有时候公式太多,可能会直接贴图片)

池化(Pooling)就是在降低特征图尺寸的同时,保留重要的特征(比如纹理、边缘、轮廓、最大响应)并提升模型的鲁棒性(不敏感于位置、旋转、缩放等)

池化层只能容忍 小幅度的平移,对大幅度的偏移是无能为力的。所以并不用在意这个东西,池化层主要就是减少后续需要处理的参数,防止参数爆炸,从而加快训练,其他都是额外的

1. 二维最大池化层和平均池化层

同卷积层一样,池化层每次对输入数据的一个固定形状窗口(又称池化窗口)中的元素计算输出。

不同于卷积层里计算输入和核的互相关性,池化层直接计算池化窗口内元素的最大值或者平均值。

二维平均池化的工作原理与二维最大池化类似,但将最大运算符替换成平均运算符。

下面把池化层的前向计算实现在pool2d函数里。它跟5.1节(二维卷积层)里corr2d函数非常类似,唯一的区别在计算输出Y上。

我们可以构造图5.6中的输入数组X来验证二维最大池化层的输出。

1
2
3
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
res = pool2d(X, (2, 2))
print(res)

2. 填充和步幅

卷积层一样,池化层也可以在输入的高和宽两侧的填充并调整窗口的移动步幅来改变输出形状。池化层填充和步幅与卷积层填充和步幅的工作机制一样。

我们将通过nn模块里的二维最大池化层MaxPool2d来演示池化层填充和步幅的工作机制。我们先构造一个形状为(1, 1, 4, 4)的输入数据,前两个维度分别是批量(batch)通道(chanel)(池化函数的输入格式)。

1
2
X = torch.arange(16, dtype=torch.float).view((1, 1, 4, 4))
print(X)

默认情况下,MaxPool2d实例里步幅和池化窗口形状相同。下面使用形状为(3, 3)的池化窗口,默认获得形状为(3, 3)的步幅。

1
2
3
pool2d = nn.MaxPool2d(3)
res = pool2d(X)
print(res)

我们可以手动指定步幅和填充。

1
2
3
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
res = pool2d(X)
print(res)

当然,我们也可以指定非正方形的池化窗口,并分别指定高和宽上的填充和步幅。

1
2
3
4
pool2d = nn.MaxPool2d((2, 4), padding=(1, 2), stride=(2, 3))
pool2d(X)
res = pool2d(X)
print(res)

padding=(1, 2) 指的是上下添加1行,左右添加2列

3. 多通道

在处理多通道输入数据时,池化层对每个输入通道分别池化,而不是像卷积层那样将各通道的输入按通道相加

下面将数组X和X+1在通道维上连结来构造通道数为2的输入。

1
2
3
X = torch.cat((X, X + 1), dim=1)
print(X.shape)
print(X)

运行下面的池化代码后,我们发现输出通道数仍然是2。

1
2
3
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
r = pool2d(X)
print(r)

池化层的输出通道数跟输入通道数相同