• yolo系列的Neck模块


    学习:【Make YOLO Great Again】YOLOv1-v7全系列大解析(Neck篇)

    本文研究yolo系列的Neck模块。yolov1、yolov2没有使用Neck模块,yolov3开始使用。Neck模块的目的是融合不同层的特征检测大中小目标。

    模块
    yolov3FPN
    yolov4spp+FPN
    yolov5spp+FPN,Concat层后的CBL模块改成了CSP_V5模块
    yoloxspp+FPN
    yolov7sppscp+优化的PAN(Concat层前的CBL改成MPConv,Concat层后使用E-ELAN)

    在进行yolo系列Neck模块研究前,先研究FPN、SPP和PAN模块。

    1.FPN(feature pyramid networks)

    目的:提高小目标的检出。

             原来很多目标检测算法都是只采用高层特征进行预测,高层的特征语义信息比较丰富,但是分辨率较低,目标位置比较粗略。假设在深层网络中,最后的高层特征图中一个像素可能对应着输出图像20*20的像素区域,那么小于20*20像素的小物体的特征大概率已经丢失。与此同时,低层的特征语义信息比较少,但是目标位置准确,这是对小目标检测有帮助的。FPN将高层特征与底层特征进行融合,从而同时利用低层特征的高分辨率和高层特征的丰富语义信息,并进行了多尺度特征的独立预测,对小物体的检测效果有明显的提升。

    2.SPP(Spatial Pyramid Pooling)

    SPP,即空间金字塔池化。SPP的目的是解决了输入数据大小任意的问题。SPP网络用在YOLOv4中的目的是增加网络的感受野

     SPP的使用方法:

    • 首先划分输入:将输入特征分别划分成不同份:最左边有16个蓝色小格子的图,它的意思是将从输入特征分成16份,16X256中的256表示的是channel,即SPP对每一层都分成16份(不一定是等比分)。中间的4个绿色小格子和右边1个紫色大格子也同理,即将输入特征分别分成4X2561X256份。(注意上面划分成多少份是可以自定义)
    • 对每份特征进行池化:一般选择MAX Pooling,即对每一份进行最大池化。看上图,通过SPP层,输入特征被转化成了16X256+4X256+1X256 = 21X256的矩阵。
    • 后面连接一个全连接层:连接一个1X10752的全连接层。这样就解决了输入数据大小任意的问题了。

    SPP中卷积核的 尺寸、和步长大小计算方法:

    在这里插入图片描述在这里插入图片描述

    假设输入数据大小是 (7,11), 池化数量 (4,4):

    那么核大小为 (2,3), 步长大小为 (2,3), padding 为 (1,1), 得到池化后的矩阵大小的确是 4∗4。 

    SPP的pytorch实现:

    1. #coding=utf-8
    2. import math
    3. import torch
    4. import torch.nn.functional as F
    5. # 构建SPP层(空间金字塔池化层)
    6. class SPPLayer(torch.nn.Module):
    7. def __init__(self, num_levels, pool_type='max_pool'):
    8. super(SPPLayer, self).__init__()
    9. self.num_levels = num_levels
    10. self.pool_type = pool_type
    11. def forward(self, x):
    12. num, c, h, w = x.size() # num:样本数量 c:通道数 h:高 w:宽
    13. for i in range(self.num_levels):
    14. level = i+1
    15. kernel_size = (math.ceil(h / level), math.ceil(w / level))
    16. stride = (math.ceil(h / level), math.ceil(w / level))
    17. pooling = (math.floor((kernel_size[0]*level-h+1)/2), math.floor((kernel_size[1]*level-w+1)/2))
    18. # 选择池化方式
    19. if self.pool_type == 'max_pool':
    20. tensor = F.max_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1)
    21. else:
    22. tensor = F.avg_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1)
    23. # 展开、拼接
    24. if (i == 0):
    25. x_flatten = tensor.view(num, -1)
    26. else:
    27. x_flatten = torch.cat((x_flatten, tensor.view(num, -1)), 1)
    28. return x_flatten

    SPPCSP

    SPP的优化,在SPP模块基础上在最后增加concat操作,与SPP模块之前的特征图进行融合,更加丰富了特征信息。

     

    3.PANet

    网络结构如下图所示,与FPN相比,PANet 在UpSample之后又加了DownSample的操作。PANet对不同层次的特征进行疯狂融合,其在FPN模块的基础上增加了自底向上的特征金字塔结构,保留了更多的浅层位置特征,将整体特征提取能力进一步提升。

     PAN模块的优化:

     PAN模块在每个Concat层后面引入一个E-ELAN结构,使用expand、shuffle、merge cardinality等策略实现在不破坏原始梯度路径的情况下,提高网络的学习能力。

    4.yolov3

        yolov3的NECK模块引入了FPN的思想,并对原始FPN进行修改。

     YOLOv3设置了三个不同的尺寸,分别是19*19,38*38,76*76

     YOLOv3采用全卷积的思路,在Neck侧也不例外(YOLOv1-v2中采用池化层做特征图的下采样, v3中采用卷积层来实现)。

    5.yolov4

    yolov4的Neck模块主要包含了SPP模块和PAN模块。

    YOLOv4引入PAN时,特征图最后的融合操作相比于原论文发生了变化,从add操作改为concat操作,增加了特征图的通道数:

    6. yolov5

    YOLOv5的Neck侧也使用了SPP模块和PAN模块,但是在PAN模块进行融合后,将YOLOv4中使用的CBL模块替换成借鉴CSPnet设计的CSP_v5结构,加强网络特征融合的能力。

    7.yolovx

    YOLOx的Neck侧依然使用了YOLOv3的结构,并且使用了SPP模块。

     在Neck侧,yolox和yov3的差别在于:在高层特征支路上使用了SPP模块:

     

    8.yolov7

     YOLOv7的Neck侧主要包含了SPPSCP模块和优化的PAN模块

     SPPCSP模块在SPP模块基础上在最后增加concat操作,与SPP模块之前的特征图进行融合,更加丰富了特征信息。

    PAN模块引入E-ELAN结构,使用expand、shuffle、merge cardinality等策略实现在不破坏原始梯度路径的情况下,提高网络的学习能力。

  • 相关阅读:
    【云原生】K8s pod优雅退出(postStart、terminationGracePeriodSeconds、preStop)
    多智能体协作如何处理
    采购数字化提升企业竞争壁垒,供应商系统助力冷链生鲜企业强化供应商管理能力
    内核开发-同步场景与概念
    免费开源的地图解析工具【快速上手】
    军品与民品的区别
    DateUtil时间工具类的基本使用
    字符串匹配算法KMP原理
    Python中的enumerate用法
    合同法重点知识总结
  • 原文地址:https://blog.csdn.net/baidu_38262850/article/details/126148560