【SPP】来自何凯明在2015年发表的顶刊。一起学习池化层的变形体SPP

简介: 【SPP】来自何凯明在2015年发表的顶刊。一起学习池化层的变形体SPP

前言

  在卷积神经网络中使用全连接层时,需要将特征图转换成固定的尺寸以便连接到全连接层中。这种固定尺寸的需求会导致卷积神经网络对输入图片的大小和比例变化非常敏感,而无法适应各种尺寸和比例的输入图片。SPP层的作用就是针对这种问题提供一种解决方案,允许卷积神经网络能够适应任意大小的输入图片,从而更好地完成图像分类、目标检测等任务。

原理

  SPP层的原理可以简单概括为将不同尺寸的网格子图进行金字塔式的池化,将每个子图都映射到一个固定长度的向量中,再将这些向量级联在一起,最终形成一个固定长度的特征向量。

  具体来说,SPP层将输入的特征图分成多个不同大小的子区域,对每个子区域进行池化操作,得到一个固定长度的向量表示该子区域的特征。不同大小的子区域可以通过金字塔式的分割来实现,即将原始特征图先分成2×2的小块,然后分成4×4的块,再分成8×8的块,以此类推。每个子区域的池化方式可以采用最大值池化或平均值池化等方式。

  最后,将每个子区域的特征向量级联在一起,就可以得到输入特征图的固定长度的特征表示。这种特征表示可以适用于不同大小和比例的输入图片,从而增强了卷积神经网络对输入图片的鲁棒性和泛化能力。

ini

复制代码

import torch
import torch.nn as nn
import math
def spatial_pyramid_pool(previous_conv, num_sample, previous_conv_size, out_pool_size):
    for i in range(len(out_pool_size)):
        h_wid = int(math.ceil(previous_conv_size[0] / out_pool_size[i]))
        w_wid = int(math.ceil(previous_conv_size[1] / out_pool_size[i]))
        h_pad = (h_wid * out_pool_size[i] - previous_conv_size[0] + 1) // 2
        w_pad = (w_wid * out_pool_size[i] - previous_conv_size[1] + 1) // 2
        maxpool = nn.MaxPool2d((h_wid, w_wid), stride=(h_wid, w_wid), padding=(h_pad, w_pad))
        x = maxpool(previous_conv)
        if (i == 0):
            spp = x.view(num_sample, -1)
        else:
            spp = torch.cat((spp, x.view(num_sample, -1)), 1)
    return spp

SPP与传统池化层

  传统的池化层采用固定大小的滑动窗口进行池化,它们的池化大小和步长都是固定的,所以对于不同大小的输入图像,需要通过修改网络结构或调整输入图像的大小来适应。这种方法在处理不同尺寸的输入图像时存在一定的局限性。

image.png

  与传统的池化层相比,SPP层则可以适应不同大小的输入图像,不需要修改网络结构或调整输入图像的大小。通过金字塔分割和多层池化,SPP层可以从输入特征图中提取更加丰富和复杂的特征信息,与传统的池化层相比,可以提高网络的表达能力和分类准确率。

  此外,SPP层还可以提高网络的运行效率。传统的池化层需要对每个池化区域进行池化操作,这会导致池化层的运算量非常大,而SPP层只需要在每个子区域中进行一次池化操作,同时将不同层次的子区域的特征向量连接在一起,运算量大大降低,从而提高了网络的速度和效率。

image.png

  SPP层与传统的池化层相比,具有更好的鲁棒性、更强的特征表达能力和更高的运算效率。这也是SPP层在目标检测、图像分类等任务中得到广泛应用的重要原因之一。

实验

ini

复制代码

if __name__ == "__main__":
    input = torch.randn(5, 3, 22, 82)
    conv = nn.Sequential(
    nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
    nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
    nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
    nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1)
    )
    # 假设我们要使用 SPP,在第四个卷积层的输出上应用池化操作,输出池化尺寸为 [1, 2, 4]
    out_pool_size = [1, 2, 4]
    previous_conv = conv(input)
    num_sample = previous_conv.size(0)
    previous_conv_size = previous_conv.size()[2:4]
    spp = spatial_pyramid_pool(previous_conv, num_sample, previous_conv_size, out_pool_size)
    print(previous_conv.shape)
    print(spp.shape)
    # 现在我们可以将 SPP 的输出馈送给全连接层
    fc = nn.Linear(spp.size(1), 10)
    out = fc(spp)
    print(out.shape)


相关文章
|
21天前
|
机器学习/深度学习 编解码 数据可视化
英特尔提出新型卷积 | 让ResNet/MobileNet/ConvNeXt等Backbone一起涨点
英特尔提出新型卷积 | 让ResNet/MobileNet/ConvNeXt等Backbone一起涨点
129 2
|
机器学习/深度学习 编解码 算法
改进UNet | 透过UCTransNet分析ResNet+UNet是不是真的有效?(一)
改进UNet | 透过UCTransNet分析ResNet+UNet是不是真的有效?(一)
737 0
|
机器学习/深度学习 PyTorch 算法框架/工具
【论文泛读】 ResNeXt:深度神经网络的聚合残差变换(ResNet的改进,提出了一种新的维度)
【论文泛读】 ResNeXt:深度神经网络的聚合残差变换(ResNet的改进,提出了一种新的维度)
【论文泛读】 ResNeXt:深度神经网络的聚合残差变换(ResNet的改进,提出了一种新的维度)
|
21天前
|
机器学习/深度学习 算法 固态存储
MFDS-DETR开源 | HS-FPN多级特征融合+Deformable Self-Attention,再续DETR传奇
MFDS-DETR开源 | HS-FPN多级特征融合+Deformable Self-Attention,再续DETR传奇
437 0
|
机器学习/深度学习 PyTorch 算法框架/工具
即插即用 | 5行代码实现NAM注意力机制让ResNet、MobileNet轻松涨点(超越CBAM)
即插即用 | 5行代码实现NAM注意力机制让ResNet、MobileNet轻松涨点(超越CBAM)
350 0
|
机器学习/深度学习 编解码 PyTorch
金字塔ViT | 华为提出使用金字塔结构改进Transformer,涨点明显(Pytorch逐行解读)
金字塔ViT | 华为提出使用金字塔结构改进Transformer,涨点明显(Pytorch逐行解读)
247 0
|
机器学习/深度学习 缓存 计算机视觉
即插即用 | 卷积与Self-Attention完美融合X-volution插入CV模型将带来全任务的涨点(文末附论文)(一)
即插即用 | 卷积与Self-Attention完美融合X-volution插入CV模型将带来全任务的涨点(文末附论文)(一)
242 0
|
计算机视觉
即插即用 | 卷积与Self-Attention完美融合X-volution插入CV模型将带来全任务的涨点(文末附论文)(二)
即插即用 | 卷积与Self-Attention完美融合X-volution插入CV模型将带来全任务的涨点(文末附论文)(二)
221 0
|
机器学习/深度学习 计算机视觉
深度残差网络(ResNet)之ResNet34的实现和个人浅见
深度残差网络(ResNet)之ResNet34的实现和个人浅见
198 0
深度残差网络(ResNet)之ResNet34的实现和个人浅见
|
机器学习/深度学习 网络架构 计算机视觉
经典神经网络 | 从Inception v1到Inception v4全解析
经典神经网络 | 从Inception v1到Inception v4全解析
经典神经网络 | 从Inception v1到Inception v4全解析

热门文章

最新文章