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,具体如

def build_targets(self, p, targets):
    # Build targets for compute_loss(), input targets(image,class,x,y,w,h)
    na, nt = self.na, targets.shape[0]  # number of anchors, targets
    tcls, tbox, indices, anch = [], [], [], []
    gain = torch.ones(7, device=targets.device)  # normalized to gridspace gain
    
    ## 前置处理
    # same as .repeat_interleave(nt)
    ai = torch.arange(na, device=targets.device).float().view(na, 1).repeat(1, nt)  
    targets = torch.cat((targets.repeat(na, 1, 1), ai[:, :, None]), 2)  # append anchor indices
    g = 0.5  # bias
    off = torch.tensor([[0, 0],
                        [1, 0], [0, 1], [-1, 0], [0, -1],  # j,k,l,m
                        # [1, 1], [1, -1], [-1, 1], [-1, -1],  # jk,jm,lk,lm
                       ], device=targets.device).float() * g  # offsets
 
    for i in range(self.nl):
        ## target映射到当前层的尺度
        anchors = self.anchors[i]
        gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]]  # xyxy gain
        # Match targets to anchors
        t = targets * gain
        if nt:
            # Matches
            r = t[:, :, 4:6] / anchors[:, None]  # wh ratio
            j = torch.max(r, 1 / r).max(2)[0] < self.hyp['anchor_t']  # compare
            t = t[j]  # filter
 
            # Offsets
            gxy = t[:, 2:4]  # grid xy
            gxi = gain[[2, 3]] - gxy  # inverse
            j, k = ((gxy % 1 < g) & (gxy > 1)).T
            l, m = ((gxi % 1 < g) & (gxi > 1)).T
            j = torch.stack((torch.ones_like(j), j, k, l, m))
            t = t.repeat((5, 1, 1))[j]
            offsets = (torch.zeros_like(gxy)[None] + off[:, None])[j]
            else:
                t = targets[0]
                offsets = 0
 
                # Define
                b, c = t[:, :2].long().T  # image, class
                gxy = t[:, 2:4]  # grid xy
                gwh = t[:, 4:6]  # grid wh
                gij = (gxy - offsets).long()
                gi, gj = gij.T  # grid xy indices
 
                # Append
                a = t[:, 6].long()  # anchor indices
                indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1)))  # image, anchor, grid indices
                tbox.append(torch.cat((gxy - gij, gwh), 1))  # box
                anch.append(anchors[a])  # anchors
                tcls.append(c)  # class
 
                return tcls, tbox, indices, anch

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值