池化层模拟器 返回
机器学习

池化层模拟器 — CNN

用于体验CNN(卷积神经网络)池化层的工具。在最大池化和平均池化之间切换,改变池大小、步幅、输入特征图,输出大小、演算次数、走查动画都会实时变化,让你直观理解特征图缩小的下采样机制。

参数设置
池化类型
选择窗口内代表值的取法
池大小 k
k×k 窗口的一边长度
步幅 s
每次窗口移动的像素数
输入特征图大小 N×N
px
进行池化的输入图的一边长度
输入样式
选择要进行池化的输入特征图的形状
计算结果
输出大小
下采样率
输出元素数
学习参数数
运算次数
池化效果
池化走查动画(输入 → 输出)

左侧是输入特征图,右侧是池化后的输出。黄色框是k×k池化窗口,它以步幅s进行滑动,依次计算对应的输出单元。

输出大小 vs 池大小
中央行的输入 vs 输出
理论与主要公式

$$\text{outN}=\left\lfloor\frac{N-k}{s}\right\rfloor+1$$

输出特征图的一边长度。N:输入大小,k:池大小,s:步幅。输出为 outN×outN。

$$y_{max}=\max_{(i,j)\in\text{window}}x_{ij},\qquad y_{avg}=\frac{1}{k^2}\sum_{(i,j)}x_{ij}$$

最大池化输出窗口内的最大值,平均池化输出窗口内的平均值。k是池大小,s是步幅,池化层没有任何需要学习的参数。

什么是池化层

🙋
在CNN的图表中,我经常看到卷积层之后有「池化层」。它是做什么的?
🎓
简单说,它的作用是「把特征图缩小」。卷积层从图像中找出边缘和纹理来创建特征图,但这样的话空间大小太大了,后面层的计算量和内存会膨胀。所以池化层用k×k的小窗口把值合并成一个代表值,把图缩小(下采样)。看左边的滑块,把步幅设为2,你会发现输出在纵横方向都变成了一半。
🙋
只是采样不行吗?为什么要选「最大池化」和「平均池化」两种?
🎓
好问题。窗口中的值怎样合并成一个有两种方式。最大池化保留窗口中「最强的值」。卷积后的特征图中,大值表示「这里有边缘或纹理」的强证据,所以取最大值能很好地保持显著特征。这是CNN中最常用的。平均池化取窗口的平均值,特征会被平滑化。你可以看右上的图和走查动画,比较两种方式输出轮廓的差异。
🙋
池化层像卷积层那样通过学习变聪明吗?
🎓
这是关键点:池化层根本没有需要学习的参数。左边「学习参数数」始终是0就是这个原因。「取最大值」「取平均值」这样的运算是固定的,误差反向传播不会改变任何权重。这和卷积层学习核心数字很不一样。池化层的唯一决定是池大小k和步幅s这两个超参数,这些是设计者事先决定的。
🙋
既然池化层不学习,那为什么还要用它呢?
🎓
意义很大。有两个原因。第一是计算削减——步幅2的池化后,特征图纵横都变成一半,面积变成四分之一。深层的计算量和内存一下子就轻了。第二是「平移不变性」。在最大池化中,如果特征在窗口内移动1-2个像素,只要最大值还是从同一像素取出,输出就不会变。也就是说,狗在图里位置略微偏移,模型还能稳定识别。手写数字识别的LeNet、在ImageNet出名的AlexNet,都在卷积后必然放池化层。
🙋
最近的模型还用池化吗?
🎓
用法有点变化。古典CNN是把「卷积+最大池化」当一个组合,重复很多次。最近的ResNet等,改成用「步幅2的卷积」来代替中间的下采样,减少了池化层。但是在网络最后,把整个特征图压成一个值的「全局平均池化」到现在还是标配。池化虽然形式改了,还是CNN的基本零件。

常见问题

池化层是CNN(卷积神经网络)中对特征图进行缩小(下采样)的层。它在卷积层之后插入,在特征图上用k×k的小窗口以步幅s进行滑动,将每个窗口替换为一个代表值。这样空间大小就会减小,可以大幅降低深层的计算量和内存消耗。输出大小由outN = floor((N−k)/s)+1决定。
最大池化输出每个窗口中的最大值。它保留了窗口内反应最强烈的激活值,即「该特征存在的最显著证据」,因此能更好地保持边缘和纹理等显著特征,是CNN中最常用的方法。平均池化则输出窗口内所有像素的平均值,会平滑化(模糊化)特征。在需要全面平滑处理背景或在最终层的全局平均池化中使用。
没有。池化层执行的是「取最大值」「取平均值」等固定运算,没有任何通过学习优化的权重(学习参数数=0)。这与拥有权重的卷积层和全连接层有很大区别。池化层决定的因素只有池大小k和步幅s两个超参数,这些由设计者事先确定,在学习过程中不会改变。
池化为网络提供了「平移不变性」——即使输入发生轻微平移,输出也基本不变。在最大池化中,如果窗口内的特征移动1-2个像素,只要最大值仍来自同一像素,输出就不会改变。这使得网络能够稳定地识别图像中位置略微偏移的物体。但这种不变性仅限于窗口大小程度的移动,大幅移位需要其他方法如数据增强来处理。

现实世界应用

图像识别AI(CNN):池化层是物体检测、人脸识别、医学影像诊断、自动驾驶等图像AI的基础部件。手写数字识别的LeNet、在ImageNet上闻名的AlexNet和VGG,都用「卷积层+最大池化层」这样的组合重复堆砌。池化分阶段缩小空间大小,让网络从局部边缘逐步到物体部件再到整体形状,在扩大感受野的同时抽象化特征。

计算量和内存削减:如果把高分辨率特征图直接带到深层,计算量和内存会爆炸。只用一次步幅2的池化,特征图面积就能变成四分之一,大幅减少后续全层的运算量和内存。这样即使GPU内存有限,也能训练深网络,边缘设备推理也变得切实可行。

全局平均池化(Global Average Pooling):最近的CNN在网络最后,都用「全局平均池化」把整个特征图(H×W)平均成一个值。这代替了全连接层,大幅削减参数,同时抑制过拟合,让特征图和类的对应关系更清晰。基于全局平均池化的类激活图(CAM)可视化也是现在的标准做法。

信号处理、时间序列:池化概念也能应用到音频、传感器信号这样的一维时间序列。用一维最大/平均池化缩小时间序列,能让语音识别、异常检测网络对时间偏移更鲁棒,计算也更轻。下采样的思想是工程中的共通思考,和CAE计算结果的多重网格粗化通理。

常见误解和注意点

最常见的误解是,「池化层在学习」。池化层完全没有可学习的权重,学习参数数始终为0。误差反向传播时,最大池化只是「把梯度传给取最大值的像素」,平均池化「把梯度均匀分配到窗口内」,遵循固定规则。池化层本身变不聪明,变聪明的是拥有权重的卷积层和全连接层。一定要记住,池化是固定的下采样操作。

其次,「输出大小计算中舍去小数」这点容易忽视。输出大小是 outN = floor((N−k)/s)+1,带着floor(向下取整)。根据输入大小N、池大小k、步幅s的组合,有时输入边缘的几个像素找不到要进入的池化窗口而被忽略。意识不到这点会导致计算的输出大小和实际大小不符,后续层形状不匹配就报错。有时会加内边距来统一大小。

最后,「过估计平移不变性」。池化提供的不变性只对窗口大小程度的小位移有效。物体在图里大幅移动、旋转、缩放时,池化应付不了。要应对大的位置变化和姿态变化,需要数据增强(平移、旋转、翻转)或更全局的机制。池化只是「小位移的保险」,不是万能的不变性魔法,要有这样的正确认识。

使用指南

  1. 设置输入特征图的大小。例如从32×32像素RGB图像提取的特征图,可在gridN中指定为28×28
  2. 选择池大小(2×2或3×3)和步幅(1-3)。ResNet50中标准使用3×3池、步幅2,空间分辨率削减50%
  3. 在最大池化和平均池化间切换对比,观察输出大小、下采样率、运算次数的变化

具体计算示例

以VGG16第一个池化层为例:输入特征图64×64,池大小2×2,步幅2时,输出大小为(64-2)/2+1=32×32。下采样率75%(元素数从4096降到1024)。每个输出位置需进行4个元素的比较或平均计算,总共4096次运算。AlexNet使用5×5池、步幅3,从227×227输入得到55×55输出(95%削减)

实务注意事项