池化层(Pooling layers)

池化层(Pooling layers)

1.理论部分

在进行卷积层计算时候,有一个问题就是边缘的地方容易忽略,并且对位置是非常敏感的。池化层的做法是为了降低卷积层对位置的敏感性,同时降低对空间降采样表示的敏感性。 因此,除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性。与卷积层不同的是,池化层运算是确定性的,我们通常计算池化窗口中所有元素的最大值或平均值。这些操作分别称为最大池化层 (maximum pooling)和平均池化层(average pooling)。先举一个池化层的例子

假如输入是一个4×4矩阵,用到的池化类型是最大池化(max pooling)。执行最大池化是一个2×2矩阵。执行过程非常简单,把4×4的输入拆分成不同的区域,我把这个区域用不同颜色来标记。对于2×2的输出,输出的每个元素都是其对应颜色区域中的最大元素值。

左上区域的最大值是9,右上区域的最大元素值是2,左下区域的最大值是6,右下区域的最大值是3。为了计算出右侧这4个元素值,我们需要对输入矩阵的2×2区域做最大值运算。

这里相当于是一个2×2的kernel,步幅为2。因为我们使用的过滤器为2×2,最后输出是9。然后向右移动2个步幅,计算出最大值2。然后是第二行,向下移动得到最大值6。最后向右移动,得到最大值3。这是一个2×2矩阵,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> f = 2 f=2 </math>f=2,步幅是2,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> s = 2 s=2 </math>s=2。

这是对最大池化功能的直观理解,你可以把这个4×4区域看作是某些特征的集合,也就是神经网络中某一层的非激活值集合。数字大意味着可能探测到了某些特定的特征,左上象限具有的特征可能是一个垂直边缘,最大化操作的功能就是只要在任何一个象限内提取到某个特征,它都会保留在最大化的池化输出里。所以最大化运算的实际作用就是,如果在过滤器中提取到某个特征,那么保留其最大值。如果没有提取到这个特征,可能在右上象限中不存在这个特征,那么其中的最大值也还是很小。

其中一个有意思的特点就是,它有一组超参数,但并没有参数需要学习 。实际上,梯度下降没有什么可学的,一旦确定了 <math xmlns="http://www.w3.org/1998/Math/MathML"> f f </math>f和 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s,它就是一个固定运算,梯度下降无需改变任何值。

我们来看一个有若干个超级参数的示例,输入是一个5×5的矩阵。我们采用最大池化法,它的过滤器参数为3×3,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> f = 3 f=3 </math>f=3,步幅为1, <math xmlns="http://www.w3.org/1998/Math/MathML"> s = 1 s=1 </math>s=1,输出矩阵是3×3。之前讲的计算卷积层输出大小的公式同样适用于最大池化, <math xmlns="http://www.w3.org/1998/Math/MathML"> n + 2 p − f s + 1 \frac{n + 2p - f}{s} + 1 </math>sn+2p−f+1,这个公式也可以计算最大池化的输出大小。

目前来说,最大池化比平均池化更常用。但也有例外,就是深度很深的神经网络,你可以用平均池化来分解规模为7×7×1000的网络的表示层,在整个空间内求平均值,得到1×1×1000。但在神经网络中,最大池化要比平均池化用得更多。

2.代码实现

池化层代码非常简单,因为这里没有卷积核,输出为输入中每个区域的最大值或平均值,我们可以很简单的自定义一个池化层函数

python 复制代码
import torch
from torch import nn
def pool2d(X, pool_size, mode='max'):
    p_h, p_w = pool_size #池化层大小
    Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            if mode == 'max':
                Y[i, j] = X[i: i + p_h, j: j + p_w].max()
            elif mode == 'avg':
                Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
    return Y

现在我们测试一下,先生成一个张量X

python 复制代码
X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
X
python 复制代码
# 测试我们刚刚的函数,默认最大池化层
pool2d(X, (2, 2))
lua 复制代码
tensor([[4., 5.],
        [7., 8.]])

3.填充与步幅

与卷积层一样,池化层也可以改变输出形状。和以前一样,我们可以通过填充(padding)和步幅(stride)以获得所需的输出形状。 这里我们直接使用pytorch内置的方法来演示,首先生成输入张量X,它是一个四维张量,其中样本数和通道数都是1。

python 复制代码
X = torch.arange(16, dtype=torch.float32).reshape((1, 1, 4, 4))
X
lua 复制代码
tensor([[[[ 0.,  1.,  2.,  3.],
          [ 4.,  5.,  6.,  7.],
          [ 8.,  9., 10., 11.],
          [12., 13., 14., 15.]]]])

默认条件下,步幅和池化层的窗口大小一致。例如,我们使用 <math xmlns="http://www.w3.org/1998/Math/MathML"> 3 × 3 3×3 </math>3×3的池化层,那么步幅 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s默认是3

python 复制代码
pool2d = nn.MaxPool2d(3)
pool2d(X)
lua 复制代码
tensor([[[[10.]]]])

我们可以根据需要指定相应的步幅和填充,这里我们设置padding=1,stride=2通常情况下,我们不会使用填充(padding),因为这一部分可以在卷积层进行。

python 复制代码
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
pool2d(X)

4.多通道

在处理多通道输入数据时,池化层在每个输入通道上单独运算,而不是像卷积层一样在通道上对输入进行汇总。 这意味着汇聚层的输出通道数与输入通道数相同。和我们之前创建多通道数据一样,我们使用cat函数

ini 复制代码
X = torch.cat((X, X + 1), 1)
X

此时X的纬度是1×2×4×4,1个样本,两个通道

接下来我们使用一个2×2的池化层,步幅 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s为2

python 复制代码
pool2d = nn.MaxPool2d(2, stride=2)
pool2d(X)
lua 复制代码
tensor([[[[ 5.,  7.],
          [13., 15.]],

         [[ 6.,  8.],
          [14., 16.]]]])

可以看到结果仍然是一个两通道张量,这一点和卷积层完全不同。

总结

总结一下,池化层的超参数包括过滤器大小 <math xmlns="http://www.w3.org/1998/Math/MathML"> f f </math>f和步幅 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s,常用的参数值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> f = 2 f=2 </math>f=2, <math xmlns="http://www.w3.org/1998/Math/MathML"> s = 2 s=2 </math>s=2,应用频率非常高,其效果相当于高度和宽度缩减一半。也有使用 <math xmlns="http://www.w3.org/1998/Math/MathML"> f = 3 f=3 </math>f=3, <math xmlns="http://www.w3.org/1998/Math/MathML"> s = 2 s=2 </math>s=2的情况。至于其它超参数就要看你用的是最大池化还是平均池化了。大部分情况下,最大池化很少用padding 。目前 <math xmlns="http://www.w3.org/1998/Math/MathML"> p p </math>p最常用的值是0,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> p a d d i n g = 0 padding=0 </math>padding=0。最大池化的输入就是 <math xmlns="http://www.w3.org/1998/Math/MathML"> n H × n W × n c n_{H} \times n_{W} \times n_{c} </math>nH×nW×nc,假设没有padding ,则输出 <math xmlns="http://www.w3.org/1998/Math/MathML"> ⌊ n H − f s + 1 ⌋ × ⌊ n w − f s + 1 ⌋ × n c \lfloor\frac{n_{H} - f}{s} +1\rfloor \times \lfloor\frac{n_{w} - f}{s} + 1\rfloor \times n_{c} </math>⌊snH−f+1⌋×⌊snw−f+1⌋×nc。输入通道与输出通道个数相同,因为我们对每个通道都做了池化。需要注意的一点是,池化过程中没有需要学习的参数。执行反向传播时,反向传播没有参数适用于池化层。这些超参数都是设置的,可能是手动设置的,也可能是通过交叉验证设置的。

特点:

  • 输入通道数等于输出通道数
  • 没有可以学习的参数
  • 池化层的主要优点之一是减轻卷积层对位置的过度敏感
  • 最大池化层:返回窗口内的最大值,提取的是每个窗口中最强的信号,更常用
  • 平均池化层:平均汇聚层会输出该窗口内的平均值。
相关推荐
通信仿真实验室30 分钟前
(15)衰落信道模型作用于信号是相乘还是卷积
开发语言·人工智能·算法·matlab
如果能为勤奋颁奖1 小时前
YOLO11改进|注意力机制篇|引入上下文锚注意力机制CAA
人工智能·深度学习·yolo
黄焖鸡能干四碗1 小时前
【需求分析】软件系统需求设计报告,需求分析报告,需求总结报告(原件PPT)
大数据·人工智能·安全·测试用例·需求分析
FL16238631291 小时前
[C++]使用C++部署yolov11目标检测的tensorrt模型支持图片视频推理windows测试通过
人工智能·yolo·目标检测
人生不如初见2 小时前
平台数据分类与聚类实验报告
人工智能·分类·数据挖掘·聚类
iiimZoey2 小时前
Dit架构 diffusion范式分类+应用
人工智能·python
唐小旭2 小时前
RL_足球教练
人工智能
winfredzhang2 小时前
如何使用Flair.ai实现模特换装效果
人工智能·换装·flair
程序员非鱼2 小时前
深度学习中的损失函数详解
人工智能·深度学习·计算机视觉·损失函数
SCBAiotAigc2 小时前
VSCode debug模式无法跳转进入内置模块
人工智能·vscode·python