YOLO V6系列(二) -- 网络结构解析

19 篇文章 43 订阅
3 篇文章 2 订阅

YOLO V6系列(二) – 网络结构解析

YOLO V6系列(一) – 跑通YOLO V6算法这篇blog中简单的介绍了YOLO V6算法的训练及测试过程。那么后面,尽可能地对源码进行解析。首先,先对YOLO V6算法的网络架构进行解析吧~(如果中间有不对的地方,还请指出来,权Q ^ _ ^)


首先基于tools/train.pytrainer = Trainer(args, cfg, device)创建训练的类,通过对训练类的初始化model = self.get_model(args, cfg, self.num_classes, device)来创建网络模型。在models/yolo.pybuild_network函数可见,YOLO V4算法网络架构基本上就是三部分:backbone、neck、head,跟yolo系列算法相似。

    backbone = EfficientRep(
        in_channels=channels,
        channels_list=channels_list,
        num_repeats=num_repeat
    )
    neck = RepPANNeck(
        channels_list=channels_list,
        num_repeats=num_repeat
    )
    head_layers = build_effidehead_layer(channels_list, num_anchors, num_classes)

这三个部分分别来看下:

一、EfficientRep结构

在YOLO V4算法中,弃用了YOLO V5中CSPDarknet结构,采用ReVGG的结构,并且基于硬件又进行了改良,提出了效率更高的EfficientRep。
这里,先介绍下RepVGGBlock模块,他的实现代码在yolov6/layers/common.py中。

    def forward(self, inputs):
        '''Forward process'''
        if hasattr(self, 'rbr_reparam'):
            return self.nonlinearity(self.se(self.rbr_reparam(inputs)))
        if self.rbr_identity is None:
            id_out = 0
        else:
            id_out = self.rbr_identity(inputs)
        return self.nonlinearity(self.se(self.rbr_dense(inputs) + self.rbr_1x1(inputs) + id_out))
self.rbr_identity = nn.BatchNorm2d(num_features=in_channels) if out_channels == in_channels and stride == 1 else None
self.rbr_dense = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding, groups=groups)
self.rbr_1x1 = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=stride, padding=padding_11, groups=groups)

这里,为了简洁,我只摘取了训练过程中EfficientRep模块的实现代码。其实可以看的出来,它首先对输入特征图进行3X3卷积,同时进行1X1卷积,最后再加上输入本身。这里盗个图(转载于EfficientRep模块示意图
在这里插入图片描述
基于RepVGGBlock模块,可组成EfficientRep结构

outputs = []
x = self.stem(x)
x = self.ERBlock_2(x)
x = self.ERBlock_3(x)
outputs.append(x)
x = self.ERBlock_4(x)
outputs.append(x)
x = self.ERBlock_5(x)
outputs.append(x)

二、RepPANNeck结构

        (x2, x1, x0) = input

        fpn_out0 = self.reduce_layer0(x0)
        upsample_feat0 = self.upsample0(fpn_out0)
        f_concat_layer0 = torch.cat([upsample_feat0, x1], 1)
        f_out0 = self.Rep_p4(f_concat_layer0)

        fpn_out1 = self.reduce_layer1(f_out0)
        upsample_feat1 = self.upsample1(fpn_out1)
        f_concat_layer1 = torch.cat([upsample_feat1, x2], 1)
        pan_out2 = self.Rep_p3(f_concat_layer1)

        down_feat1 = self.downsample2(pan_out2)
        p_concat_layer1 = torch.cat([down_feat1, fpn_out1], 1)
        pan_out1 = self.Rep_n3(p_concat_layer1)

        down_feat0 = self.downsample1(pan_out1)
        p_concat_layer2 = torch.cat([down_feat0, fpn_out0], 1)
        pan_out0 = self.Rep_n4(p_concat_layer2)

        outputs = [pan_out2, pan_out1, pan_out0]

上述x2, x1, x0均为backbone进行特征提取之后所得到的三个特征图。从结构上来看,其实还是用了YOLO V5这PANET结构,只不过将其中的CSPDarknet换做了RepBlock。
在这里插入图片描述

三、effidehead模块

在这里插入图片描述
这里,获取预测头的代码有点长,我就直接贴图了。从上图所示,YOLO V6相对于YOLO X来说把解耦头部分的两个卷积减少成一个卷积,这样做应该是缩短训练和测试时间,但是精度应该会有一些损失。最后生成的head应该是

  • (cls_convs): ModuleList()
  • (reg_convs): ModuleList()
  • (cls_preds): ModuleList()
  • (stems): ModuleList()
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进我的收藏吃灰吧~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值