import torch
'''
池化层
在5.1节里面介绍的图像物体边缘检测应用中,我们构造卷积核从而精确的找到了像素变化位置。设任意二维数组
x的i行j列的元素为x[i,j]。如果我们构造的卷积核输出Y[i,j]=1,呢么说明输入中x[i,j]和x[i,j+1]数值不一样
这可能意味着物体边缘通过这两个元素之间。但实际图像里,我们感兴趣的物体不会总出现在固定位置:即使我们连续
拍摄同一个物体也可能会出现像素位置上的偏移。这会导致同一个边缘对应的输出可能出现在卷积输出Y上的不同位置
,进而对后面的模式识别造成不便
池化层的提出是为了缓解卷积层对位置的过度敏感性
二维最大池化层和平均池化层
同卷积层一样,池化层每次对输入数据的一个固定形状窗口(池化窗口)中的元素计算输出。不同于卷积里面计算输入跟
卷积核的互相关性,池化层直接计算池化窗口内的最大值或者平均值。该运算也称为最大池化或者平均池化。
二维最大池化
在二维最大池化中,池化窗口从左到右,从上到下依次在输入数组中滑动,当池化窗口移动到某一个位置时,窗口中
输入子数组最大值即为输出数组中相应位置的元素
'''
from torch import nn
def pool2d(x, pool_size, mode='max'):
x = x.float()
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 = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
result = pool2d(X, (2, 2))
print(result)
result_avg = pool2d(X, (2, 2), 'avg')
print(result_avg)
'''
步幅和填充
跟卷积层一样 池化层也可以在输入的高和宽两侧的填充或者调整窗口移动的步幅来改变输出形状。池化层的步幅和填充跟
卷积层的工作原理一样。
'''
x = torch.arange(16, dtype=torch.float).view((1, 1, 4, 4))
'''构建一个形状为(1, 1, 4, 4)的输入数据'''
print(x)
pool2d_nn = nn.MaxPool2d(3)
result_nn = pool2d_nn(x)
print(result_nn)
result_ps = nn.MaxPool2d(3, padding=1, stride=2)
'''填充为1 步幅为2'''
print(result_ps(x))
result_ps2 = nn.MaxPool2d((2, 4), padding=(1, 2), stride=(2, 3))
'''填充为1 步幅为2'''
print(result_ps2(x))
'''
多通道
在处理多通道输入数据的时候,池化层对每个输入通道分别池化,而不是像卷积那样将各个通道的输入按
通道想加,这意味着池化层的输出通道跟输入通道数相等
'''
print('**'*100)
x = torch.cat((x, x + 1), dim=1)
print(x)
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
print(pool2d(x))
'''
小结
eg
最大池化层和平均池化层分别取池化窗口中输入元素最大值或者平均值
池化层的目标是缓解卷积层对位置的过度敏感
可以指定池化层的填充和步幅
池化层的输出通道数跟输入通道数相同
'''