yolo核心组件10:SPP 空间金字塔池化
SPP 空间金字塔池化
[!abstract] 论文信息
- 论文标题: Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
- 作者: Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
- 发表: ECCV 2014 / TPAMI 2015
- 论文地址: https://arxiv.org/abs/1406.4729
- 核心贡献: 提出空间金字塔池化层,使CNN能够接受任意尺寸的输入图像,同时增强多尺度特征表达能力
一、核心思想
SPP (Spatial Pyramid Pooling) 的核心思想是在不同空间尺度上进行池化,然后将结果拼接,从而捕获多尺度的特征信息。
SPP 解决了两个关键问题:
- 输入尺寸固定:传统CNN要求固定尺寸输入,SPP 允许任意尺寸输入
- 多尺度特征:通过多尺度池化,同时捕获局部细节和全局语义
在 YOLO 中,SPP 主要用于增强网络的感受野,通过多个不同大小的池化窗口提取多尺度特征。
二、模块结构
2.1 SPP 池化结构
输入特征图 [B×C×H×W] │ ┌─────┼─────┬─────────────┐ │ │ │ │ │ MaxPool MaxPool MaxPool │ 5×5 9×9 13×13 │ │ │ │ │ [B×C [B×C [B×C │ ×1×1] ×1×1] ×1×1] │ │ │ │ └─────┴─────┴─────────────┘ │ Concat (通道维度) │ [B×4C×1×1] │ 保持或降维2.2 在 YOLO 中的 SPP 结构
输入特征图 [B×C×H×W] │ Conv1×1 (通道压缩) │ ┌─────┼─────┬─────────────┐ │ │ │ │ 原图 MaxPool MaxPool MaxPool 保留 5×5 9×9 13×13 │ │ │ │ │ padding padding padding │ =2,1,2 =4,4,6 =6,6,6 │ │ │ │ └─────┴─────┴─────────────┘ │ Concat (通道维度) │ [B×4C×H×W] │ Conv1×1 (通道恢复) │ 输出 [B×C×H×W]2.3 不同池化核的效果
| 池化核 | 感受野 | 捕获信息 |
|---|---|---|
| 原始 | 1×1 | 局部细节 |
| 5×5 | ~5×5 | 局部模式 |
| 9×9 | ~9×9 | 中等尺度 |
| 13×13 | ~13×13 | 大尺度/全局 |
三、数学公式
3.1 最大池化
MaxPoolk(X)i,j=max(m,n)∈Ri,jkXm,n\text{MaxPool}_k(X)_{i,j} = \max_{(m,n) \in \mathcal{R}_{i,j}^k} X_{m,n}MaxPoolk(X)i,j=(m,n)∈Ri,jkmaxXm,n
其中Ri,jk\mathcal{R}_{i,j}^kRi,jk是以(i,j)(i,j)(i,j)为中心、大小为k×kk \times kk×k的区域。
3.2 SPP 输出
SPP(X)=Concat(X,MaxPool5(X),MaxPool9(X),MaxPool13(X))\text{SPP}(X) = \text{Concat}\Big(X, \text{MaxPool}_5(X), \text{MaxPool}_9(X), \text{MaxPool}_{13}(X)\Big)SPP(X)=Concat(X,MaxPool5(X),MaxPool9(X),MaxPool13(X))
3.3 等效感受野
RFSPP=max(k1,k2,k3,...)\text{RF}_{\text{SPP}} = \max(k_1, k_2, k_3, ...)RFSPP=max(k1,k2,k3,...)
使用5×55\times55×5、9×99\times99×9、13×1313\times1313×13的池化核时,等效感受野为13×1313\times1313×13。
3.4 输出尺寸(通用公式)
对于输入尺寸H×WH \times WH×W,使用k×kk \times kk×k池化核和 paddingppp:
Hout=⌊H+2p−ks⌋+1H_{out} = \left\lfloor\frac{H + 2p - k}{s}\right\rfloor + 1Hout=⌊sH+2p−k⌋+1
在 YOLO 的 SPP 中,通过选择合适的 padding 使得输出尺寸与输入相同(Hout=HH_{out} = HHout=H)。
四、代码实现
4.1 标准 SPP 实现
importtorchimporttorch.nnasnnclassSPP(nn.Module):"""Spatial Pyramid Pooling 多尺度最大池化,增强感受野。 """def__init__(self,c1,c2,k=(5,9,13)):""" Args: c1: 输入通道数 c2: 输出通道数 k: 池化核大小列表 """super().__init__()c_=c1//2# 隐藏通道数self.cv1=nn.Conv2d(c1,c_,1,1,bias=False)self.cv2=nn.Conv2d(c_*(len(k)+1),c2,1,1,bias=False)self.bn=nn.BatchNorm2d(c2)self.act=nn.SiLU(inplace=True)self.pools=nn.ModuleList()forkiink:self.pools.append(nn.MaxPool2d(kernel_size=ki,stride=1,padding=ki//2))defforward(self,x):x=self.cv1(x)# 原始 + 多尺度池化outs=[x]+[pool(x)forpoolinself.pools]returnself.act(self.bn(self.cv2(torch.cat(outs,dim=1))))4.2 原始论文版本(支持任意输入)
classSPP_Original(nn.Module):"""原始论文的 SPP,支持任意尺寸输入"""def__init__(self,pool_sizes=[1,2,4]):super().__init__()self.pool_sizes=pool_sizesdefforward(self,x):bs,c,h,w=x.size()pooled=[]forsizeinself.pool_sizes:pool=nn.AdaptiveMaxPool2d(size)pooled.append(pool(x).view(bs,-1))returntorch.cat(pooled,dim=1)4.3 简化版 SPP(YOLO 常用)
classSPP_Simple(nn.Module):"""简化的 SPP 模块"""def__init__(self,c1,c2):super().__init__()c_=c1//2self.cv1=nn.Sequential(nn.Conv2d(c1,c_,1,bias=False),nn.BatchNorm2d(c_),nn.SiLU(inplace=True))self.cv2=nn.Sequential(nn.Conv2d(c_*4,c2,1,bias=False),nn.BatchNorm2d(c2),nn.SiLU(inplace=True))self.m1=nn.MaxPool2d(5,1,2)self.m2=nn.MaxPool2d(9,1,4)self.m3=nn.MaxPool2d(13,1,6)defforward(self,x):x=self.cv1(x)returnself.cv2(torch.cat([x,self.m1(x),self.m2(x),self.m3(x)],1))五、在YOLO中的应用
5.1 SPP 在 YOLO 中的位置
Backbone: ... → C3/C2f (高层特征) → SPP (增强感受野) ← 在这里 → C3/C2f (进一步融合) → 输出到 Neck5.2 YOLOv5 配置示例
# YOLOv5 backbone (含 SPP)backbone:-[-1,1,Conv,[64,3,2]]-[-1,1,Conv,[128,3,2]]-[-1,3,C3,[128]]-[-1,1,Conv,[256,3,2]]-[-1,6,C3,[256]]-[-1,1,Conv,[512,3,2]]-[-1,9,C3,[512]]-[-1,1,Conv,[1024,3,2]]-[-1,3,C3,[1024]]-[-1,1,SPP,[1024,[5,9,13]]]# SPP层-[-1,3,C3,[1024]]5.3 SPP 的作用分析
| 方面 | 无 SPP | 有 SPP |
|---|---|---|
| 感受野 | 受限于卷积核 | 扩展到 13×13+ |
| 多尺度能力 | 单一尺度 | 多尺度融合 |
| 大目标检测 | 较弱 | 增强 |
| 计算量 | 基准 | 增加约 5-10% |
| 参数量 | 基准 | 增加少量 |
六、优缺点
优点
- 增强感受野:通过大尺度池化核扩大特征图的有效感受野
- 多尺度特征:同时捕获不同尺度的特征信息
- 计算高效:池化操作本身计算量极小
- 即插即用:可方便地插入到任何 CNN 架构中
- 减少过拟合:池化操作具有一定的正则化效果
缺点
- 信息丢失:最大池化会丢失部分空间信息
- 固定池化核:池化核大小需要预先设定,不够灵活
- 边界效应:大池化核在特征图边界处的处理可能引入误差
- 量化敏感:池化操作在模型量化时可能造成精度损失
- 缺乏自适应:对所有位置使用相同的池化策略
参考
- He, K., Zhang, X., Ren, S., & Sun, J. (2015). Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition.TPAMI 2015.
- https://arxiv.org/abs/1406.4729
- https://github.com/ShaoqingRen/SPP_net
