1.什么是最大池化
最大池化(Max Pooling)是一种在卷积神经网络(CNN)中常用的操作,主要用于减小特征图的尺寸,从而降低计算量,同时保留最显著的特征。最大池化通过取局部区域内的最大值来减少特征图的空间维度(即宽度和高度),而不改变通道数。
在数学上,就是在每次池化核进行匹配时,取出输入数组里面的最大数字,用于存储输入数据特征。从效果上来看,有效地缩小特征图的空间尺寸,减少模型的计算复杂度,同时保留图像的重要特征,实际观感就相当于打了一层马赛克。
最大池化操作,首先需要一个池化核,与卷积层的卷积核一样,都是一个固定大小的滑动窗口在输入特征图上滑动。对于每一个池化区域,最大池化会在该区域内选择最大的数值作为输出结果。例如,对于一个 2x2 的池化核,如果输入是 [[1, 3], [2, 4]],那么最大池化的输出就是 4,因为 4 是这个区域内的最大值。
2.最大池化的代码理解
MaxPool2d的常见格式如下:
MaxPool2d(kernel_size, stride , padding , ceil_mode)
步长(Stride):步长决定了池化核每次移动的距离。默认情况下,步长与池化核的大小(kernel_size)相同。当步长小于池化核大小时,池化核会重叠在输入图像上,从而增加输出的重叠信息。
填充(padding):决定在输入图像的边缘添加的像素数量,用于控制池化结果的尺寸,通常填充为零。
舍弃处理(ceil_mode):在语言中,ceil和floor是将小数向上取整和向下取整,而在pytorch里,ceil_mode是对不满足kernel的输出结果作舍弃处理。
ceil_mode=False: 默认设置,会丢弃那些无法完全填满池化核的边缘部分。
ceil_mode=True: 会处理边缘部分,不满池化核时会取最大值。比如输入图像为:
1 | 2 | 0 | 3 | 1 |
0 | 1 | 2 | 3 | 1 |
1 | 2 | 1 | 0 | 0 |
5 | 2 | 3 | 1 | 1 |
2 | 1 | 0 | 1 | 1 |
假设kernel(池化核)的尺寸为3*3,第一轮从[0, 0]开始,取最大数字2;
第二轮则会从[3,0]开始,很显然无法填满kernel,如果ceil_mode为true,则会读出最大值3,否则直接舍弃这些数字;
以此类推,最后当ceil_mode = true的情况下,读出输出数组为:
2 | 3 |
5 | 1 |
而ceil_mode = false的情况下,只能读出第一轮的2;
3.对CIFAR数据集进行最大池化操作
import torch.nn as nn
import torch.nn.functional as F
import torch
import torchvision
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10('E:\\PyCharm_Project\\Pytorch_2.3.1\\PytorchVision\\dataset', train=False,
transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)
# 定义了一个简单的模型 Zilliax,其中包含一个最大池化层。MaxPool2d 使用了 kernel_size=3,即 3x3 的池化核,ceil_mode=False 表示在池化过程中不会对不足的部分进行向上取整。
class Zilliax(nn.Module):
def __init__(self):
super(Zilliax, self).__init__()
self.maxpool = MaxPool2d(kernel_size = 3 , ceil_mode = False)
def forward(self, x):
output = self.maxpool(x)
return output
model = Zilliax()
writer = SummaryWriter("logs")
step = 0
for data in dataloader:
imgs , labels = data
writer.add_images("input", imgs,step) # 输入图片加入tensorboard,方便对比
outputs = model(imgs) # 对每个图片进行池化处理
#池化不会转变层数,所以不需要reshape
writer.add_images("output", outputs,step)
step += 1
writer.close()