在神经网络中 池化层是比较重要的,是提取重要信息的操作,可以去掉不重要的信息,减少计算开销。下面我们来介绍
MaxPool2d的使用方法。

API官网文档

在这里插入图片描述
在这里插入图片描述

MaxPool2d 参数介绍

  • kernel_size :表示做最大池化的窗口大小,可以是单个值,也可以是tuple元组
  • stride :步长,可以是单个值,也可以是tuple元组
  • padding :填充,可以是单个值,也可以是tuple元组
  • dilation :控制窗口中元素步幅
  • return_indices :布尔类型,返回最大值位置索引
  • ceil_mode :布尔类型,为True,用向上取整的方法,计算输出形状;默认是向下取整。

kernel_size 的详解

注意这里的 kernel_size 跟卷积核不是一个东西。 kernel_size 可以看做是一个滑动窗口,这个窗口的大小由自己指定,如果输入是单个值,例如 3 ,那么窗口的大小就是 3 × 3 3 ,还可以输入元组,例如 (3, 2) ,那么窗口大小就是 3 × 2。
最大池化的方法就是取这个窗口覆盖元素中的最大值

stride 的详解

上一个参数我们确定了滑动窗口的大小,现在我们来确定这个窗口如何进行滑动。如果不指定这个参数,那么默认步长跟最大池化窗口大小一致。如果指定了参数,那么将按照我们指定的参数进行滑动。例如 stride=(2,3) , 那么窗口将每次向右滑动三个元素位置,或者向下滑动两个元素位置

padding 的详解

这参数控制如何进行填充,填充值默认为0。如果是单个值,例如 1,那么将在周围填充一圈0。还可以用元组指定如何填充,例如 padding = ( 2 , 1 ) padding=(2, 1)padding=(2,1) ,表示在上下两个方向个填充两行0,在左右两个方向各填充一列0。

dilation 的详解

空洞卷积,默认 dilation=1,如果kernel_size =3,那么卷积核就是33的框。如果dilation = 2,kernel_size =3,那么每列数据与每列数据中间再加一列空洞,那么卷积核就变成55的框。

return_indices 的详解

这是个布尔类型值,表示返回值中是否包含最大值位置的索引。注意这个最大值指的是在所有窗口中产生的最大值,如果窗口产生的最大值总共有5个,就会有5个返回值。

ceil_mode 的详解

这个也是布尔类型值,它决定的是在计算输出结果形状的时候,是使用向上取整还是向下取整。怎么计算输出形状,下面会讲到。一看就知道了。

最大池化层输出形状计算

在这里插入图片描述
看到向下取整的符号了吗?这个就是由 ceil_mode 控制的。

参数示例介绍

验证 kernel_size 参数

import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3))

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print(output)

在这里插入图片描述
第一个tensor是我们的输入数据 1 × 1 × 6 × 6 ,我们画红线的区域就是我们设置的窗口大小 3 × 3 ,背景色为红色的值,为该区域的最大值。

第二个tensor就是我们最大池化后的结果,跟我们标注的一模一样。

验证一下 stride 参数

import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3), stride=(2, 2))

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print(output)

在这里插入图片描述
红色的还是我们的窗口,但是我们的步长变为了2,可以看到第一个窗口和向右滑动后的窗口,他们的最大值刚好是重叠的部分都是2.688,向下滑动之后,最大值是0.8030,再次向右滑动,最大值是2.4859。

可以看到我们在滑动的时候省略了部分数值,因为剩下的数据不够一次滑动了,于是我们将他们丢弃了。

其实最后图片的宽度和高度还可以通过上面两个公式来计算,我们公式中用的是向下取整,因此我们丢弃了不足的数据。现在我们试试向上取整。

利用 ceil_mode 参数向上取整

import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3), stride=(2, 2), ceil_mode=True)

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print('\n\n\n\n\n')

print(output)

在这里插入图片描述
从结果可以看出,输出的size由原来的 2 × 2 变成了现在的 3 × 3。这就是向上取整的结果。为什么会出现这样的结果呢?

这看起来像是我们对输入进行了填充,但是这个填充值不会参与到计算最大值中

验证 padding 参数

import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3), stride=(3, 3), padding=(1, 1))

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print('\n\n')

print(output)

在这里插入图片描述
我们对周围填充了一圈0,我们滑动窗口的范围就变化了,这就是填充的作用。

但是有一点需要注意,就是即使我们填充了0,这个0也不会被选为最大值。例如上图的左上角四个数据,如果我们全部变为负数,结果是-0.1711,而不会是我们填充的0值,这一点要注意。

验证 return_indices 参数

import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3), return_indices=True)

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print(output)

在这里插入图片描述

验证 dilation 参数


```python
import torch
import torch.nn as nn

# 仅定义一个 3x3 的池化层窗口
m = nn.MaxPool2d(kernel_size=(3, 3),dilation=2)

# 定义输入
# 四个参数分别表示 (batch_size, C_in, H_in, W_in)
# 分别对应,批处理大小,输入通道数,图像高度(像素),图像宽度(像素)
# 为了简化表示,我们只模拟单张图片输入,单通道图片,图片大小是6x6
input = torch.randn(1, 1, 6, 6)

print(input)

output = m(input)

print(output)

在这里插入图片描述

参考文档: https://blog.csdn.net/weixin_38481963/article/details/109962715

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐