原始SPP及在YOLO中的SPP/SPPF对比详解

简介: 原始SPP及在YOLO中的SPP/SPPF对比详解

b7a98eb5a3354ae39870e6af321244e4.png在卷积神经网络中我们经常看到固定输入的设计,但是有的时候难以控制,何凯明大神的论文SPPNet中的SPP结构解决了该问题。

后续在YOLO系列中也出现了SPP结构及改进的结构,但是作用与最初的SPP结构却是不同的。

✨1 SPPNet中的SPP

原始SPP结构如下图所示:

67f7a3cf8aab4ee9a5c4ae4efcdf182d.png

下面默认通道数不变

首先输入Feature map(w,h,c)需要经过三个池化层:

k=(w, h, c)的池化层相当于将对整个图像取一次最大化操作,输出为(1, 1, c)的特征图。

k=(w/2, h/2, c)的池化层相当于将整个图像平均划分为4分,每一份取一次最大化操作,输出为(2, 2, c)的特征图。

k=(w/4, h/4, c)的池化层相当于将整个图像平均划分为16分,每一份取一次最大化操作,输出为(4, 4, c)的特征图。

然后将三个池化操作分别进行维度变换,再进行拼接操作。最终产生维度为(21, c)的向量。

通过上述两个步骤,可以看到我们的输入(w, h, c)不管如何变化,最终的输出都是(21, c)。

这里更多的是提供了一个思想,在不同网络中采用了不同的尝试,比如利用卷积层代替池化层等等…

✨2 YOLO中的SPP/SPPF

与上面何凯明大神提出的不同,这里的SPP虽然也叫SPP,但是作用更多的是实现局部特征和全局特征的featherMap级别的融合

🥓2.1 SPP

下面忽略了通道数的变化

eca2f2fd470048b4912be6dbf293e7f0.png

其中k(kernel_size)为卷积核尺寸。s(stride)为步长,p(padding)为在所有边界增加值。

可以看到与上面介绍的何凯明大神提出的SPP是不同的,输入Feature map(w, h, c)经过三次卷积操作像素并没有发生改变,作用更多的是实现局部特征和全局特征的featherMap级别的融合。

YOLO中的代码

class SPP(nn.Module):
    def __init__(self, c1, c2, k=(5, 9, 13)):  # 5,9,13分别是三个卷积操作的卷积核大小
        super().__init__()
        c_ = c1 // 2
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
    def forward(self, x):
        x = self.cv1(x)
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')  # suppress torch 1.9.0 max_pool2d() warning忽略警告
            return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))

💫2.2 SPPF

SPPF由yolo系列中的SPP结构改进而来,目的没有变化,只是从SPP改进为SPPF后,模型的计算量变小了很多,模型速度提升

YOLOV5中的SPPF结构:

忽略了通道数的变化

f1cc368b06df4856a2ecb998905a3405.png

其中Conv和Maxpool中第一个数(kernel_size)为卷积核尺寸。第二个数(stride)为步长,第三个数(padding)为在所有边界增加值。

YOLO V5代码:

class SPPF(nn.Module):
    """
        This code referenced to https://github.com/ultralytics/yolov5
    """
    def __init__(self, in_dim, out_dim, expand_ratio=0.5, pooling_size=5, act_type='lrelu', norm_type='BN'):
        super().__init__()
        inter_dim = int(in_dim * expand_ratio)
        self.out_dim = out_dim
        self.cv1 = Conv(in_dim, inter_dim, k=1, act_type=act_type, norm_type=norm_type)
        self.cv2 = Conv(inter_dim * 4, out_dim, k=1, act_type=act_type, norm_type=norm_type)
        self.m = nn.MaxPool2d(kernel_size=pooling_size, stride=1, padding=pooling_size // 2)
    def forward(self, x):
        x = self.cv1(x)
        y1 = self.m(x)
        y2 = self.m(y1)
        return self.cv2(torch.cat((x, y1, y2, self.m(y2)), 1))

从代码中可以看到其中进行的三次池化操作用到的均是统一个池化核。

相关文章
|
3天前
|
机器学习/深度学习 Go 计算机视觉
YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)
YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)
173 1
|
3天前
|
机器学习/深度学习 算法 Go
YOLOv5网络结构解析
YOLOv5网络结构解析
|
3天前
|
机器学习/深度学习 Go 计算机视觉
YOLOv5改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)
YOLOv5改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)
201 0
|
3天前
|
编解码 计算机视觉
YOLOv8改进 | Conv篇 | 2024.1月最新成果可变形卷积DCNv4(适用检测、Seg、分类、Pose、OBB)
YOLOv8改进 | Conv篇 | 2024.1月最新成果可变形卷积DCNv4(适用检测、Seg、分类、Pose、OBB)
401 0
|
3天前
|
计算机视觉
YOLOv5改进 | 2023Neck篇 | 利用Damo-YOLO的RepGFPN改进特征融合层
YOLOv5改进 | 2023Neck篇 | 利用Damo-YOLO的RepGFPN改进特征融合层
103 1
YOLOv5改进 | 2023Neck篇 | 利用Damo-YOLO的RepGFPN改进特征融合层
|
3天前
|
机器学习/深度学习 计算机视觉
YOLOv8改进 | 2023Neck篇 | 利用Damo-YOLO的RepGFPN改进特征融合层
YOLOv8改进 | 2023Neck篇 | 利用Damo-YOLO的RepGFPN改进特征融合层
89 0
YOLOv8改进 | 2023Neck篇 | 利用Damo-YOLO的RepGFPN改进特征融合层
|
12月前
|
机器学习/深度学习 计算机视觉
RMNet推理去除残差结构让ResNet、MobileNet、RepVGG Great Again(必看必看)(一)
RMNet推理去除残差结构让ResNet、MobileNet、RepVGG Great Again(必看必看)(一)
134 0
|
12月前
|
PyTorch 算法框架/工具 计算机视觉
RMNet推理去除残差结构让ResNet、MobileNet、RepVGG Great Again(必看必看)(二)
RMNet推理去除残差结构让ResNet、MobileNet、RepVGG Great Again(必看必看)(二)
133 0
|
存储 索引
Yolov3-spp系列 | yolov3spp的正负样本匹配
Yolov3-spp系列 | yolov3spp的正负样本匹配
275 0
Yolov3-spp系列 | yolov3spp的正负样本匹配
|
数据可视化 算法 数据处理
Yolov3-spp系列 | yolov3spp的训练验证与测试过程
Yolov3-spp系列 | yolov3spp的训练验证与测试过程
181 0

相关实验场景

更多