• yolov5原理


    目录

    1 网络结构

    1.1 整体网络结构参考

    1.2 backbone C3结构

    1.3 Neck

    1.3.1 SPPF

    1.3.2 带C3结构的FPN-PAN

    1.4 Head


    1 网络结构

    1.1 整体网络结构参考

     yolov5 6.0版本  参考

    https://blog.csdn.net/qq_37541097/article/details/123594351

    1.2 backbone C3结构

    可以看出yolov5- 5.0后面的版本主干主要由CSP模块变成了C3模块,yolov5-5.0之前的版本主干还是和yolov4类似的CSP结果,可参考

    YOLOV5网络结构_Laughing-q的博客-CSDN博客_yolov5结构图

    CSP和C3区别如下:

    之前讲yolov4 yolov4原理_xd_MrCheng的博客-CSDN博客

    时CSP结构如下:

    一般来说CBM1只起到下采样2倍,真正意义上的CSP结构如下,把CBM1不要(因为CBM1只是为了下采样2倍)

     

    其中CBM结构都是卷积核1x1且步长为1的卷积层

    残差模组Resunit则是一个1x1的卷积加一个3x3的卷积,在相加

    而C3结构和CSP结构有些不一样,C3结构如下:

     其中CBM换成了CBS, 表示激活函数有Mish换成了SiLu

    并且相对CSP,C3结构经过残差模组Resunit后少了一个卷积层, 直接连到了Concat,正好只有3个CBS,或者说只有3个卷积,可能才叫C3,并且C3中的残差模组,有的地方也叫BottleNeck1

    单纯的C3结构是不会进行下采样的,每次下采样都是C3前面会接一个3x3且步长为2的卷积

    1.3 Neck

    1.3.1 SPPF

    在Neck部分的变化还是相对较大的,首先是将SPP换成成了SPPF(Glenn Jocher自己设计的),两者的作用是一样的,但后者效率更高。SPP结构如下图所示,是将输入并行通过多个不同大小的MaxPool,然后做进一步融合,能在一定程度上解决目标多尺度问题。


    SPP结构

     SPPF结构

     而SPPF结构是将输入串行通过多个5x5大小的MaxPool层,这里需要注意的是串行两个5x5大小的MaxPool层是和一个9x9大小的MaxPool层计算结果是一样的,串行三个5x5大小的MaxPool层是和一个13x13大小的MaxPool层计算结果是一样的。

    也就说用两个串联的5x5的MaxPool层替代一个9x9的maxPool层,因为两个5x5的串联的池化层效果就是9x9的池化层.

    用3个串联的5x5的MaxPool层替代一个13x13的maxPool层, 以此减小计算时间。二者效果基本是一样的。但计算时间SPPF比SPP减半了

    这和用2个3x3的卷积来替代5x5的卷积一样,减小计算量

    1.3.2 带C3结构的FPN-PAN

    在YOLOv4中,Neck的PFN和PAN结构是没有引入CSP结构的,但在YOLOv5中作者在FPN和PAN结构中加入了C3结构,但注意,Neck中C3中用到的叫bottleneck2, 和backbone中的bottleneck1(即残差模组resunit)是不一样的,bottleneck2没有残差连接,如下图:

    Neck中的C3结构:

    yolov5-Neck

     YoloV5-Neck

    1.4 Head

    yolov5的head和yolov4,yolov3一样

    2 损失函数

    参考YOLOv5网络详解_太阳花的小绿豆的博客-CSDN博客_yolov5网络结构详解

    3  消除Grid敏感度

    继续参考YOLOv5网络详解_太阳花的小绿豆的博客-CSDN博客_yolov5网络结构详解

     

    4 正负样本分配

    4.1 匹配正样本(Build Targets)

    还是参考 YOLOv5网络详解_太阳花的小绿豆的博客-CSDN博客_yolov5网络结构详解

     

     yolov3是GT中心点G落在那个格子,那个格子对应的Anchor就负责预测这个GT

    比如上图,只有A这个格子回去预测GT,那现在由于网络预测目标中心点相对gird cell左上角的偏移调整到了-0.5-1.5,所以只要gird cell左上角点距离GT中心点在(-0.5,1.5)范围内它们对应的Anchor都能回归到GT的位置处,比如C点, 距离GT中心点x方向距离明显<0.5 , y方向的距离明<1.5, 所以C这个单元格满足, 同理B也是, 满足这样就扩充了正样本数量

    更详细的介绍,参考【YOLOv5】正样本分配详解_mjiansun的博客-CSDN博客

    具体如下:

    4.2 正样本采样

    Yolov5算法使用如下3种方式增加正样本个数:

     

     

     

    如上图,绿色框是GT,假设中心点为绿色的点G, 红色实线锚框是1这个gird单元格对应的锚框,其中心点为A,也就是1单元格中心那个黑色的点,而网络预测的x,y偏移量其实就是想让虚线 红色实线锚框上下左右平移,使得中心点变为G,即让中心点与GT重合, 如红色虚线锚框(假设红色虚线锚框中心点是G),之前这个平移量范围是0-1之间的,现在变成了-0.5-1.5, 所以2和3这个单元格对应的anchor通过平移也能和GT的中心点重合,(在缩放宽度和高度,就能让anchor和GT完全重合,所以是一个平移+缩放的过程,这里只讨论平移)

    debug 代码

    上述正样本采样过程在yolov5通过函数build_targets实现,为了方便理解上述代码,对每一步进行debug,具体如

    1. def build_targets(self, p, targets):
    2. # Build targets for compute_loss(), input targets(image,class,x,y,w,h)
    3. na, nt = self.na, targets.shape[0] # number of anchors, targets
    4. tcls, tbox, indices, anch = [], [], [], []
    5. gain = torch.ones(7, device=targets.device) # normalized to gridspace gain
    6. ## 前置处理
    7. # same as .repeat_interleave(nt)
    8. ai = torch.arange(na, device=targets.device).float().view(na, 1).repeat(1, nt)
    9. targets = torch.cat((targets.repeat(na, 1, 1), ai[:, :, None]), 2) # append anchor indices
    10. g = 0.5 # bias
    11. off = torch.tensor([[0, 0],
    12. [1, 0], [0, 1], [-1, 0], [0, -1], # j,k,l,m
    13. # [1, 1], [1, -1], [-1, 1], [-1, -1], # jk,jm,lk,lm
    14. ], device=targets.device).float() * g # offsets
    15. for i in range(self.nl):
    16. ## target映射到当前层的尺度
    17. anchors = self.anchors[i]
    18. gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]] # xyxy gain
    19. # Match targets to anchors
    20. t = targets * gain
    21. if nt:
    22. # Matches
    23. r = t[:, :, 4:6] / anchors[:, None] # wh ratio
    24. j = torch.max(r, 1 / r).max(2)[0] < self.hyp['anchor_t'] # compare
    25. t = t[j] # filter
    26. # Offsets
    27. gxy = t[:, 2:4] # grid xy
    28. gxi = gain[[2, 3]] - gxy # inverse
    29. j, k = ((gxy % 1 < g) & (gxy > 1)).T
    30. l, m = ((gxi % 1 < g) & (gxi > 1)).T
    31. j = torch.stack((torch.ones_like(j), j, k, l, m))
    32. t = t.repeat((5, 1, 1))[j]
    33. offsets = (torch.zeros_like(gxy)[None] + off[:, None])[j]
    34. else:
    35. t = targets[0]
    36. offsets = 0
    37. # Define
    38. b, c = t[:, :2].long().T # image, class
    39. gxy = t[:, 2:4] # grid xy
    40. gwh = t[:, 4:6] # grid wh
    41. gij = (gxy - offsets).long()
    42. gi, gj = gij.T # grid xy indices
    43. # Append
    44. a = t[:, 6].long() # anchor indices
    45. indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1))) # image, anchor, grid indices
    46. tbox.append(torch.cat((gxy - gij, gwh), 1)) # box
    47. anch.append(anchors[a]) # anchors
    48. tcls.append(c) # class
    49. return tcls, tbox, indices, anch

     

     

     

     

     

     

     

  • 相关阅读:
    springboot毕设项目大学校园公益回收平台设计与实现 9kwh9(java+VUE+Mybatis+Maven+Mysql)
    PAT甲级刷题记录-(AcWing)-Day09数学(8题)
    顺序表<数据结构 C 版>
    metapath和meta-graph(持续更新ing...)
    来看看老旧物件这样与现代空间结合完美结合
    知虾shopee收费,多少钱一个月
    第104天: 权限提升-Linux 系统&环境变量&定时任务&权限配置不当&MDUT 自动化
    SQL企业微信群机器人消息推送
    npm基本使用
    80%测试员被骗,关于jmeter 的一个弥天大谎!
  • 原文地址:https://blog.csdn.net/xd_wjc/article/details/127583668