深入浅出Yolo系列之Yolox核心基础完整讲解

技术

picture.image

在Yolov4、Yolov5刚出来时,大白就写过关于Yolov3、Yolov4、Yolov5的文章,并且做了一些讲解的视频,反响都还不错。

而从 2015年的Yolov1 , 2016年Yolov2 , 2018年的Yolov3 ,再到 2020年的Yolov4、Yolov5 ,Yolo系列也在不断的进化发展。

就在大家质疑,Yolo如何进一步改进时,旷视科技发表了 研究改进的Yolox算法 。

大白对于Yolox文章和相关的代码,进行了学习,发现有很多改进的方式。

比如 Decoupled Head、SimOTA等方式 ,效果还是非常不错的,很值得借鉴。

但因为很难 直接可视化的学习 ,了解Yolox和之前Yolo相关算法的区别。

因此本文,大白对 Yolox的一些细节 ,和之前的Yolov3、Yolov4、Yolov5算法对比,进行 深入浅出的分析讲解 ,和大家一些探讨学习。

文章目录

1 Yolov3&Yolov4&Yolov5相关资料

1.1 Yolov3相关资料

1.2 Yolov4相关资料

1.3 Yolov5相关资料

2 Yolox相关基础知识点

2.1 Yolox的论文及代码

2.2. Yolox个版本网络结构图

2.2.1 Netron工具

2.2.2 各个Yolox的onnx文件

2.2.3 各个Yolox网络结构图

3 Yolox核心知识点

3.1 Yolov3&Yolov4&Yolov5网络结构图

3.2 Yolox基础知识点

3.2.1 基准模型:Yolov3_spp

3.2.2 Yolox-Darknet53

3.2.3 Yolox-s、l、m、x系列

3.2.4 轻量级网络研究

4 深入浅出Yolox之自有数据集训练

5 不同的落地模型部署方式

6 后续更新ing

7 相关推荐:数据集分类下载

1 Yolov3&Yolov4&Yolov5相关资料

在了解Yolox之前,我们首先要对之前的一些Yolo算法,比如 Yolov3、Yolov4、Yolov5 进行了解。

因为Yolox很多的网络结构,都是在其基础上,延伸而来的。

比如Yolox-Darknet53,就是在Yolov3的基础上进行的改进。

而 Yolox-s 、 Yolox-l 等网络,就是在 Yolov5-s 、 Yolov5-l 等网络的基础上,进行的改进。

所以大白将之前整理的,Yolo相关文章和视频,进行汇总。有需要的同学,可以先进行了解。

① Yolov3相关资料

【视频】:深入浅出Yolov3(上)、深入浅出Yolov3(下)

② Yolov4相关资料

【视频】:深入浅出Yolov4(上)、深入浅出Yolov4(下)

【文章】:《深入浅出Yolo系列之Yolov3&4核心基础知识完整讲解》

③ Yolov5相关资料

【文章】:《深入浅出Yolo系列之Yolov5核心基础知识完整讲解》

④ Yolox相关资料

【文章】:《深入浅出Yolox之自有数据集训练超详细教程》

注意:因无法直接放文章或视频外链,可点击最下方,阅读原文进行查看。

2 Yolox相关基础知识点

2.1 Yolox的论文及代码

Yolox论文名:《YOLOX: Exceeding YOLO Series in 2021》

Yolox论文地址:https://arxiv.org/abs/2107.08430

Yolox代码地址: https://github.com/Megvii-BaseDetection/YOLOX

2.2 Yolox各版本网络结构图

想学习一个算法,最好从 直观图示的角度 ,进行了解。

如果纯粹从代码上进行查看,很可能会一头雾水。

而且Yolox的各种网络结构也很多,比如下面的各个网络结构权重文件。

picture.image

因此可以采用,将 各个模型文件转换成onnx格式 ,再用 netron工具打开的方式, 对网络结构进行可视化学习。

picture.image

注意: 以上所有模型,可点击最下方, 阅读原文 ,查看下载。

2.2.1 Netron工具

如果有同学对netron工具还不是很熟悉,这里还是放上netron工具安装的详细流程。

可以移步大白的另一篇文章: 《网络可视化工具netron详细安装流程》。

https://blog.csdn.net/nan355655600/article/details/106245563

2.2.2 各个Yolox的onnx文件

各个onnx文件,可以采用代码中的,tools/export_onnx.py脚本,进行转换。

此外,官方代码中的这个版块,已经转换好了各个版本的onnx,也可以直接下载使用。

picture.image

2.2.3 各个Yolox网络结构图

不过考虑到,有些同学可能不方便,使用netron查看。

因此,大白也上传了使用netron打开的, 每个网络结构图的图片 ,也可以直接 查看。

(1)Yolox-Nano

Yolox-Nano是Yolox系列最小的结构,网络参数只有0.91M。

此处放上netron打开的,Yolox-Nano网络结构可视图 的地址,点击 查看

https://blog.csdn.net/nan355655600/article/details/119329864

(2)Yolox-Tiny

此处放上Yolox-Tiny网络结构可视图 的地址,点击 查看

https://blog.csdn.net/nan355655600/article/details/119329848

(3)Yolox-Darknet53

Yolox-Darknet53是在Yolov3的基础上,进行的改进,也是后面主要介绍的网络结构。

此处放上Yolox-Darknet53网络结构可视图 的地址,点击 查看

https://blog.csdn.net/nan355655600/article/details/119329834

(4)Yolox-s

Yolox-s是在Yolov5-s的基础上,进行的改进,也是后面主要介绍的网络结构。

此处放上Yolox-s网络结构可视图 的地址,点击 查看

https://blog.csdn.net/nan355655600/article/details/119329727

(5)Yolox-m

此处放上Yolox-m网络结构可视图 的地址,点击 查看

https://blog.csdn.net/nan355655600/article/details/119329801

(6)Yolox-l

此处放上Yolox-l网络结构可视图 的地址,点击 查看 。

https://blog.csdn.net/nan355655600/article/details/119329801

(7)Yolox-x

此处放上Yolox-x网络结构可视图的地址,点击 查看 。

https://blog.csdn.net/nan355655600/article/details/119329818

3 Yolox核心知识点

3.1 Yolov3&Yolov4&Yolov5网络结构图

在学习Yolox之前,我们先了解一下 Yolov3、Yolov4、Yolov5 的网络结构图,而后面的Yolox网络,都是在此基础上延伸而来的。

① Yolov3网络结构图

picture.image

Yolov3是在2018年提出,也是工业界使用非常广泛的目标检测算法。

不过在Yolox系列中的,Yolox-Darknet53模型,采用的Baseline基准网络,采用的并不是 Yolov3版本 ,而是改进后的 Yolov3_spp版本。

而Yolov3和Yolov3_spp的不同点在于,Yolov3的主干网络后面, 添加了spp组件 ,这里需要注意。

② Yolov4网络结构图

picture.image

上图是DarknetAB大神,在2020年提出的Yolov4算法。

在此算法中,网络的很多地方,都进行了改进。

比如 输入端: 采用Mosaic数据增强;

Backbone: 采用了CSPDarknet53、Mish激活函数、Dropblock等方式;

Neck: 采用了SPP(按照DarknetAB的设定)、FPN+PAN结构;

输出端: 采用CIOU_Loss、DIOU_Nms操作。

因此可以看出,Yolov4对Yolov3的各个部分,都进行了很多的整合创新。

关于Yolov4,如果有不清楚的,可以参照大白之前写的 《深入浅出Yolo系列之Yolov3&Yolov4核心基础知识完整讲解》 ,写的比较详细。

③ Yolov5网络结构图

picture.image

而在Yolov5网络中,和Yolov4不同,最大的创新点在于,作者将网络结构,做成了可选择配置的方式。

比如主干网络结构,根据各个网络的宽度、高度不同,可以分为 Yolov5s、Yolov5l、Yolov5s、Yolo5x等版本。

这种转变,在目标检测领域,引领了一股网络拆分的热潮。

本文的Yolox算法,也从这个角度出发,将Yolox模型,变为多种可选配的网络,比如标准网络结构和轻量级网络结构。

(1)标准网络结构: Yolox-s、Yolox-m、Yolox-l、Yolox-x、Yolox-Darknet53。

(2)轻量级网络结构: Yolox-Nano、Yolox-Tiny。

在实际的项目中,大家可以根据不同项目需求,进行挑选使用。

3.2 Yolox基础知识点

从上面的描述中,我们可以知道 Yolox整体的改进思路:

(1)基准模型:Yolov3_spp

选择Yolov3_spp结构,并添加一些常用的改进方式,作为 Yolov3 baseline 基准模型;

(2)Yolox-Darknet53

对Yolov3 baseline基准模型,添加各种trick,比如Decoupled Head、SimOTA等,得到 Yolox-Darknet53 版本

(3)Yolox-s、Yolox-m、Yolox-l、Yolox-x系列

对Yolov5的四个版本,采用这些有效的trick,逐一进行改进,得到 Yolox-s、Yolox-m、Yolox-l、Yolox-x四个版本;

(4)轻量级网络

设计了 Yolox-Nano、Yolox-Tiny轻量级网络 ,并测试了一些trick的适用性;

总体来说,论文中做了很多的工作,下面和大家一起,从以上的角度,对Yolox算法的网络结构,以及各个创新点进行讲解。

3.2.1 基准模型:Yolov3_spp

在设计算法时,为了对比改进trick的好坏,常常需要选择 基准的模型算法。

而在选择Yolox的基准模型时,作者考虑到:

Yolov4和Yolov5系列,从基于锚框的算法角度来说, 可能有一些过度优化 ,因此最终选择了Yolov3系列。

不过也并没有直接选择Yolov3系列中,标准的Yolov3算法,而是选择添加了spp组件,进而性能更优的 Yolov3_spp版本。

以下是论文中的解释:

Considering YOLOv4 and YOLOv5 may be a little over-optimized for the anchor-based pipeline, we choose YOLOv3 [25] as our start point (we set YOLOv3-SPP as the default YOLOv3)。

为了便于大家理解,大白在前面Yolov3结构图的基础上,添加上spp组件,变为下图所示的 Yolov3_spp网络。

picture.image

大家可以看到,主干网络Backbone后面,增加了一个SPP组件。

当然在此基础上, 对网络训练过程中的很多地方,都进行了改进 ,比如:

(1)添加了EMA权值更新、Cosine学习率机制等训练技巧

(2)使用IOU损失函数训练reg分支,BCE损失函数训练cls与obj分支

(3)添加了RandomHorizontalFlip、ColorJitter以及多尺度数据增广,移除了RandomResizedCrop。

在此基础上,Yolov3_spp的AP值达到38.5,即下图中的Yolov3 baseline。

picture.image

不过在对上图研究时, 有一点点小疑惑 :

YOLOv3_ultralytics的AP值为44.3,论文中引用时,说是目前Yolov3_spp算法中,精度最好的版本。( the current best practice of YOLOv3)。

接着对此代码进行查看,发现正如论文中所说,增加了很多trick的Yolov3_spp版本,AP值为44.3。

picture.image

而Yolox的基准模型,是最原始的Yolov3_spp版本,经过一系列的改进后, AP值达到38.5。

在此基础上,又增加了Strong augmentation、Decoupled head、anchor-free、multi positives、SimOTA,等5种trick,最终达到了AP47.3。

但存在疑惑的是?

如果直接采用YOLOv3_ultralytics的Yolov3_spp版本,再增加上面的4种trick(除掉strong augmentation,因为代码中已经改进了), 是否会有更好的AP提升?

3.2.2 Yolox-Darknet53

我们在前面知道,当得到Yolov3 baseline后,作者又添加了一系列的trick,最终改进为Yolox-Darknet53 网络结构 。

picture.image

上图即是Yolox-Darknet53网络结构图。

为了便于分析改进点,我们对Yolox-Darknet53网络结构进行拆分,变为四个板块:

① 输入端: Strong augmentation数据增强

② BackBone主干网络: 主干网络没有什么变化,还是Darknet53。

③ Neck: 没有什么变化,Yolov3 baseline的Neck层还是FPN结构。

④ Prediction: Decoupled Head、End-to-End YOLO、Anchor-free、Multi positives。

在经过一系列的改进后,Yolox-Darknet53最终达到 AP47.3的效果。

picture.image

下面我们对于Yolox-Darknet53的 输入端、Backbone、Neck、Prediction 四个部分,进行详解的拆解。

3.2.2.1 输入端

(1)Strong augmentation

picture.image

在网络的输入端,Yolox主要采用了 Mosaic、Mixup两种数据增强方法。

而采用了这两种数据增强,直接将Yolov3 baseline,提升了2.4个百分点。

① Mosaic数据增强

Mosaic增强的方式,是U版YOLOv3引入的一种非常有效的增强策略。

而且在Yolov4、Yolov5算法中,也得到了广泛的应用。

通过 随机缩放 、 随机裁剪 、 随机排布 的方式进行拼接,对于 小目标 的检测效果提升,还是很不错的。

picture.image

Mosaic数据增强 的内容,在之前

《深入浅出Yolo系列之Yolov3&Yolov4核心基础知识完整讲解》 文章中写的很详细,详情可以查看之前的内容。

② MixUp数据增强

MixUp是在Mosaic基础上,增加的一种 额外的增强策略。

主要来源于2017年,顶会ICLR的一篇论文 《mixup: Beyond Empirical Risk Minimization》。

当时主要应用在 图像分类任务中 ,可以在几乎无额外计算开销的情况下, 稳定提升1个百分点的分类精度。

而在Yolox中,则也应用到目标检测中,代码在yolox/datasets/mosaicdetection.py这个文件中。

picture.image

其实方式很简单,比如我们在做 人脸检测的任务 。

先读取一张图片,图像两侧填充,缩放到640*640大小,即Image_1,人脸检测框为红色框。

再随机选取一张图片,图像上下填充,也缩放到640*640大小,即Image_2,人脸检测框为蓝色框。

然后设置一个融合系数,比如上图中,设置为0.5,将Image_1和Image_2,加权融合,最终得到右面的Image。

从右图可以看出, 人脸的红色框和蓝色框是叠加存在的。

我们知道,在Mosaic和Mixup的基础上,Yolov3 baseline增加了 2.4个百分点 。

不过有两点需要注意:

(1)在训练的 最后15个epoch ,这两个数据增强会被关闭掉。

而在此之前,Mosaic和Mixup数据增强,都是打开的,这个细节需要注意。

(2)由于采取了更强的数据增强方式,作者在研究中发现, ImageNet预训练将毫无意义 ,因此,所有的模型,均是 从头开始训练的。

3.2.2.2 Backbone

Yolox-Darknet53的Backbone主干网络,和原本的Yolov3 baseline的主干网络都是一样的。

picture.image

都是采用Darknet53的网络结构,大白在Yolov3的视频中,对于它的来源,结构,各个组件的细节,都有很清晰的讲解,如何有不了解的,可以点击最下方, 阅读原文 ,查看视频 《Yolov3相关算法的原理及实现》

3.2.2.3 Neck

在Neck结构中,Yolox-Darknet53和Yolov3 baseline的Neck结构,也是一样的,都是采用 FPN的结构 进行融合。

picture.image

如下图所示, FPN自顶向下 ,将高层的特征信息,通过 上采样的方式进行传递融合 ,得到进行预测的特征图。

picture.image

而在Yolov4、Yolov5、甚至后面讲到的Yolox-s、l等版本中,都是采用 FPN+PAN的形式 ,这里需要注意。

3.2.2.4 Prediction层

在输出层中,主要从四个方面进行讲解: Decoupled Head 、 Anchor Free 、 标签分配、Loss计算。

picture.image

(1)Decoupled Head

我们先来看一下Decoupled Head,目前在很多一阶段网络中都有类似应用,比如 RetinaNet、FCOS等 。

而在Yolox中,作者增加了三个Decoupled Head,俗称“解耦头”

大白这里从两个方面对Decoupled Head进行讲解:

① 为什么使用Decoupled Head?

② Decoupled Head的细节?

picture.image

从上图右面的Prediction中,我们可以看到,有三个Decoupled Head分支。

① 为什么使用Decoupled Head?

在了解原理前,我们先了解下改进的原因。为什么将原本的 Yolo head ,修改为 Decoupled Head 呢?

我们先看一张论文中的表格:

picture.image

在前面3.2.1 基准网络中,我们知道 Yolov3 baseline的AP值为38.5。

作者想继续改进,比如输出端改进为End-to-end的方式(即无NMS的形式)。

但意外的发现,改进完之后的AP值 只有34.3 。

而在2020年12月份,旷视科技发表的《End-to-End Object Detection with Fully Convolution Network》中。

在对FCOS改进为无NMS时,在COCO上,达到了与有NMS的FCOS,相当的性能。

那这时就奇怪了, 为什么在Yolo上改进,会下降这么多?

在偶然间,作者将End-to-End中的Yolo Head,修改为Decoupled Head的方式。

picture.image

惊喜的发现,End-to-end Yolo的AP值, 从34.3增加到38.8。

那End-to-end的方式有效果,Yolov3 baseline中是否也有效果呢?

然后作者又将Yolov3 baseline 中Yolo Head,也修改为Decoupled Head。

发现AP值,从 38.5 ,增加到 39.6 。

当然作者在实验中还发现,不单单是 精度上的提高 。替换为Decoupled Head后, 网络的收敛速度也加快了。

因此可以得到一个非常关键的结论:

★ 目前Yolo系列使用的检测头,表达能力可能有所欠缺,没有Decoupled Head的表达能力更好。

这里添加Yolo Head和Decoupled Head的对比曲线:

picture.image

曲线表明:Decoupled Head的收敛速度更快,且精度更高一些。

但是需要注意的是: 将检测头解耦,会增加运算的复杂度。

因此作者经过速度和性能上的权衡,最终使用 1个1x1 的卷积先进行降维,并在后面两个分支里,各使用了 2个3x3 卷积,最终调整到仅仅增加一点点的网络参数。

而且这里解耦后,还有一个更深层次的重要性:

Yolox的网络架构,可以和很多算法任务,进行一体化结合。

比如:

(1)YOLOX + Yolact/CondInst/SOLO , 实现端侧的实例分割。

(2)YOLOX + 34 层输出,实现端侧人体的 17 个关键点检测。

② Decoupled Head的细节?

了解了Decoupled Head的来源,再看一下Decoupled Head的细节。

我们将Yolox-Darknet53中,Decoupled Head①提取出来,经过前面的Neck层,这里Decouple Head①输入的长宽为20*20。

picture.image

从图上可以看出,Concat前总共有 三个分支 :

(1)cls_output: 主要对目标框的类别,预测分数。因为COCO数据集总共有80个类别,且主要是N个二分类判断,因此经过Sigmoid激活函数处理后,变为202080大小。

(2)obj_output: 主要判断目标框是前景还是背景,因此经过Sigmoid处理好,变为20201大小。

(3)reg_output: 主要对目标框的坐标信息(x,y,w,h)进行预测,因此大小为20204。

最后三个output,经过Concat融合到一起,得到202085的特征信息。

当然,这只是 Decoupled Head① 的信息,再对 Decoupled Head②和③ 进行处理。

picture.image

Decoupled Head②输出特征信息,并进行 Concate,得到404085特征信息。

Decoupled Head③输出特征信息,并进行 Concate,得到808085特征信息 。

再对①②③三个信息,进行Reshape操作,并进行总体的Concat,得到 8400*85的预测信息。

并经过一次Transpose,变为85*8400大小的 二维向量信息。

这里的8400, 指的是预测框的数量 ,而85是每个 预测框的信息(reg,obj,cls)。

有了预测框的信息,下面我们再了解,如何将这些预测框和标注的框,即groundtruth进行关联,从而计算Loss函数,更新网络参数呢?

(2)Anchor-free

这里就要引入Anchor的内容,目前行业内,主要有Anchor Based和Anchor Free两种方式。

在Yolov3、Yolov4、Yolov5中,通常都是采用 Anchor Based的方式 ,来提取目标框,进而和标注的groundtruth进行比对,判断两者的差距。

① Anchor Based方式

比如输入图像,经过Backbone、Neck层,最终将特征信息,传送到输出的Feature Map中。

这时,就要设置一些Anchor规则, 将预测框和标注框进行关联。

从而在训练中,计算两者的差距,即损失函数,再更新网络参数。

比如在下图的,最后的三个Feature Map上,基于每个单元格,都有三个不同尺寸大小的锚框。

picture.image

这里为了更形象的展示,以大白Yolov3视频中,输入图像大小416*416为例。

picture.image

当输入为416416时,网络最后的三个特征图大小为 1313,2626,5252。

我们可以看到,黄色框为小狗的Groundtruth,即标注框。

而蓝色的框,为 小狗中心点所在的单元格 ,所对应的锚框,每个单元格都有3个蓝框。

当采用COCO数据集,即有80个类别时。

基于每个锚框,都有x、y、w、h、obj(前景背景)、class(80个类别),共85个参数。

因此会产生3*(1313+2626+52*52)*85= 904995个预测结果。

如果将输入从416416,变为640640,最后的三个特征图大小为 2020,4040,80*80。

则会产生3*(2020+4040+80*80)*85= 2142000个预测结果。

② Anchor Free方式

而Yolox-Darknet53中,则采用Anchor Free的方式。

我们从两个方面,来对Anchor Free进行了解。

a.输出的参数量

我们先计算下,当得到包含目标框所有输出信息时, 所需要的参数量?

这里需要注意的是:

最后黄色的85*8400,不是类似于Yolov3中的Feature Map,而是特征向量。

picture.image

从图中可知,当输入为 640640 时,最终输出得到的特征向量是 858400。

我们看下,和之前Anchor Based方式,预测结果数量 相差多少?

通过计算,8400*85=714000个预测结果,比基于 Anchor Based 的方式,少了2/3的参数量。

b.Anchor框信息

在前面Anchor Based中,我们知道,每个Feature map的单元格,都有3个大小不一的锚框。

那么Yolox-Darknet53就没有吗?

其实并不然,这里只是巧妙的,将前面Backbone中, 下采样的大小信息引入进来。

picture.image

比如上图中,最上面的分支,下采样了5次, 2的5次方为32 。

并且Decoupled Head①的输出,为 202085大小。

picture.image

因此如上图所示:

最后8400个预测框中,其中有400个框,所对应锚框的大小, 为32*32。

同样的原理,中间的分支,最后有1600个预测框,所对应锚框的大小, 为16*16。

最下面的分支,最后有6400个预测框,所对应锚框的大小, 为8*8。

当有了8400个 预测框的信息 ,每张图片也有标注的 目标框的信息。

这时的锚框, 就相当于桥梁。

这时需要做的,就是将8400个锚框,和图片上所有的目标框进行关联,挑选出 正样本锚框。

而相应的, 正样本锚框 所对应的位置,就可以将 正样本预测框 ,挑选出来。

这里采用的关联方式,就是 标签分配。

(3)标签分配

当有了8400个Anchor锚框后,这里的每一个锚框,都对应85*8400特征向量中的预测框信息。

不过需要知道,这些预测框只有 少部分是正样本,绝大多数是负样本。

那么到底哪些是正样本呢?

这里需要利用锚框和实际目标框的关系,挑选出 一部分适合的正样本锚框。

比如第3、10、15个锚框是正样本锚框,则对应到网络输出的8400个预测框中,第3、10、15个预测框,就是相应的 正样本预测框。

训练过程中,在锚框的基础上,不断的预测,然后不断的迭代,从而更新网络参数,让网络预测的越来越准。

那么在Yolox中,是 如何挑选正样本锚框的呢?

这里就涉及到两个关键点: 初步筛选 、 SimOTA。

① 初步筛选

初步筛选的方式主要有两种: 根据中心点来判断 、 根据目标框来判断 ;

这部分的代码,在models/yolo_head.py的get_in_boxes_info函数中。

a. 根据中心点来判断:

规则: 寻找anchor_box中心点,落在groundtruth_boxes矩形范围的所有anchors。

比如在get_in_boxes_info的代码中,通过groundtruth的[x_center,y_center,w,h],计算出每张图片的每个groundtruth的左上角、右下角坐标。

picture.image

为了大家更容易理解,大白以人脸检测的任务绘制图片:

picture.image

通过上面的公式,可以对左面人脸图片,计算出左上角(gt_l,gt_t),右下角(gt_r,gt_b)。

groundtruth的矩形框范围确定了,再根据范围去选择适合的锚框。

这里再绘制一个锚框的中心点,(x_center,y_center)。

而右面的图片,就是寻 找锚框和groundtruth的对应关系。

即计算锚框中心点(x_center,y_center),和人脸标注框左上角(gt_l,gt_t),右下角(gt_r,gt_b)两个角点的相应距离。

比如下面代码图片中的 前四行代码 :

picture.image

而在第五行,将四个值叠加之后,通过第六行, 判断是否都大于0?

就可以将落在groundtruth矩形范围内的所有anchors,都提取出来了。

因为ancor box的中心点,只有落在矩形范围内,这时的 b_l,b_r,b_t,b_b都大于0。

b.根据目标框来判断:

除了根据锚框中心点,和groundtruth两边距离判断的方式外,作者还设置了根据目标框判断的方法。

规则: 以groundtruth中心点为基准,设置边长为5的正方形,挑选在正方形内的所有锚框。

同样在get_in_boxes_info的代码中,通过groundtruth的[x_center,y_center,w,h],绘制了一个边长为5的正方形。

picture.image

为了大家容易理解,大白还是以人脸检测的任务绘制图片:

picture.image

在左面的人脸图片中,基于人脸标注框的中心点,利用上面的公式,绘制了一个 边长为5的正方形。 左上角点为(gt_l,gt_t),右下角点为(gt_r,gt_b)。

这时groundtruth正方形范围确定了,再根据范围去挑选锚框。

而右面的图片,就是找出所有中心点(x_center,y_center)在正方形内的锚框。

picture.image

在代码图片中的前四行代码,也是计算锚框中心点,和正方形两边的距离。

通过第五行的叠加,再在第六行, 判断c_l,c_r,c_t,c_b是否都大于0?

就可以将落在边长为5的正方形范围内,所有的anchors,都提取出来了,因为这时的c_l,c_r,c_t,c_b都大于0。

经过上面两种挑选的方式,就完成初步筛选了,挑选出一部分 候选的anchor ,进入下一步的精细化筛选。

② 精细化筛选

而在精细化筛选中,就用到论文中提到的SimOTA了:

picture.image

从提升效果上来看,引入SimOTA后,AP值提升了2.3个百分点,还是非常有效的。

而SimOAT方法的提出,主要来源于旷视科技,2021年初CVPR上的一篇论文: 《Ota: Optimal transport assignment for object detection》。

我们将SimOTA的前后流程进行拆解,看一下是如何进行精细化筛选的?

整个筛选流程,主要分为四个阶段:

a.初筛正样本信息提取

b.Loss函数计算

c.cost成本计算

d.SimOTA求解

为了便于理解,我们假定图片上有3个目标框,即 3个groundtruth。

再假定目前在做的项目是对人脸和人体检测,因此 检测类别是2。

上一节中,我们知道有8400个锚框,但是经过初步筛选后,假定有 1000个锚框是正样本锚框。

a.初筛正样本信息提取

初筛出的1000个正样本锚框的位置,我们是知道的。

而 所有锚框的位置 ,和网络最后输出的 85*8400特征向量 是一一对应。

所以根据位置,可以将网络预测的 候选检测框位置bboxes_preds 、 前景背景目标分数obj_preds 、 类别分数cls_preds等信息 ,提取出来。

picture.image

上面的代码位于yolo_head.py的get_assignments函数中。

以前面的假定信息为例,代码图片中的 bboxes_preds_per_image 因为是候选检测框的信息,因此维度为 [1000,4] 。

obj_preds 因为是目标分数,所以维度是 [1000,1] 。

cls_preds 因为是类别分数,所以维度是 [1000,2] 。

b. Loss函数计算

针对筛选出的 1000个候选检测框 ,和 3个groundtruth 计算Loss函数。

计算的代码,也在yolo_head.py的get_assignments函数中。

首先是位置信息的loss值:pair_wise_ious_loss

picture.image

通过第一行代码,可以计算出 3个目标框 ,和 1000个候选框 ,每个框相互之间的iou信息 pair_wise_ious ,因为向量维度为[3,1000]。

再通过-torch.log计算,得到 位置损失 ,即代码中的 pair_wise_iou_loss。

然后是综合类别信息和目标信息的loss值:pair_wise_cls_loss

picture.image

通过第一行代码,将类别的条件概率和目标的先验概率做乘积,得到目标的类别分数。

再通过第二行代码, F.binary_cross_entroy 的处理,得到3个目标框和1000个候选框的综合loss值,即 pair_wise_cls_loss, 向量维度为[3,1000]。

c.cost成本计算

有了reg_loss和cls_loss,就可以将两个损失函数加权相加,计算 cost成本函数 了。

这里涉及到论文中提到的一个公式:

picture.image

相应的,对应于yolo_head.py的get_assignments函数中的代码:

picture.image

可以看出,公式中的加权系数,即 代码中的3。

d.SimOTA

有了上面的一系列信息,标签分配问题,就转换为了标准的OTA问题。

但是经典的Sinkhorn-Knopp算法,需要多次迭代求得最优解。

作者也提到,该算法会导致25%额外训练时间,所以采用一种简化版的 SimOTA方法 ,求解近似最优解。这里对应的函数,是get_assignments函数中的self.dynamic_k_matching:

picture.image

其中的流程如下:

第一步:设置候选框数量

picture.image

picture.image

首先按照cost值的大小,新建一个全0变量matching_matrix,这里是[3,1000]。

picture.image

通过上面第二行代码,设置候选框数量为10。

再通过第三行代码,从前面的pair_wise_ious中,给每个目标框,挑选 10个iou最大的候选框。

因为前面假定有3个目标,因此这里topk_ious的维度为[3,10]。

第二步:通过cost挑选候选框

下面再通过topk_ious的信息,动态选择候选框, 这里是个关键。

代码如dynamic_k_matching函数中,下图所示:

picture.image

为了便于大家理解,大白先把第一行制作成图示效果。

这里的topk_ious,是3个目标框和预测框中,最大iou的10个候选框:

picture.image

经过torch.clamp函数,得到最终右面的dynamic_ks值。

我们就知道,目标框1和3,给他分配3个候选框,而目标框2,给它分配4个候选框。

那么基于什么标准分配呢?

这时就要利用前面计算的cost值,即[3,1000]的损失函数加权信息。

在for循环中,针对每个目标框挑选,相应的 cost值最低的一些候选框。

picture.image

比如右面的matching_matrix中,cost值最低的一些位置,数值为1,其余位置都为0。

因为目标框1和3,dynamic_ks值都为3,因此matching_matrix的第一行和第三行,有3个1。

而目标框2,dynamic_ks值为4,因此matching_matrix的第二行,有4个1。

第三步:过滤共用的候选框

不过在分析matching_matrix时,我们发现,第5列有两个1。

这也就说明,第五列所对应的候选框,被目标检测框1和2,都进行关联。

因此对这两个位置,还要使用cost值进行对比, 选择较小的值 ,再进一步筛选。

picture.image

这里为了便于理解,还是采用图示的方式:

首先第一行代码,将matching_matrix,对每一列进行相加。

picture.image

这时anchor_matching_gt中,只要有大于1的, 说明有共用的情况。

上图案例中,表明 第5列存在共用的情况。

再利用第三行代码,将cost中,第5列的值取出,并进行比较,计算最小值所对应的行数,以及分数。

我们将第5列两个位置,假设为0.4和0.3。

picture.image

经过第三行代码,可以找到最小的值是0.3,即cost_min为0.3,所对应的行数,cost_argmin为2。

picture.image

经过第四行代码,将matching_matrix第5列都置0。

再利用第五行代码,将matching_matrix第2行,第5列的位置变为1。

最终我们可以得到3个目标框,最合适的一些候选框,即matching_matrix中, 所有1所对应的位置。

(4)Loss计算

经过第三部分的标签分配,就可以将目标框和正样本预测框对应起来了。

下面就可以计算两者的误差,即Loss函数。

计算的代码,位于yolo_head.py的get_losses函数中。

picture.image

我们可以看到:

检测框位置的iou_loss,Yolox中使用传统的iou_loss,和giou_loss两种,可以进行选择。

而obj_loss和cls_loss,都是采用BCE_loss的方式。

当然除此之外,还有 两点需要注意 :

a.在前面精细化筛选中,使用了reg_loss和cls_loss,筛选出和目标框所对应的预测框。

因此这里的iou_loss和cls_loss,只针对目标框和筛选出的正样本预测框进行计算。

而obj_loss,则还是针对8400个预测框。

b.在Decoupled Head中, cls_output 和 obj_output 使用了sigmoid函数进行归一化,

但是在训练时,并没有使用sigmoid函数,原因是训练时用的 nn.BCEWithLogitsLoss函数 ,已经包含了sigmoid操作。

picture.image

而在推理过程中,是使用Sigmoid函数的。

picture.image

PS:不同的实验数据对比

因为想测试Yolox不同trick的性能,和好友 潘大强 在使用自有数据,对多种trick进行对比测试时发现:

① 方案一: Yolox-s+数据增强+(obj_output的Loss函数, 用BCELoss )

picture.image

② 方案二: Yolox-s+数据增强+(obj_output的Loss函数, 改为FocalLoss )

picture.image

对比发现: 在使用自有数据集训练时, 如果将obj_loss的 BCE_Loss ,修改为 Focal_Loss ,发现效果很明显,涨点也很多。而且iou_loss收敛的更好了,不知道是否有朋友也试过?可以在评论区讨论。

3.2.3 Yolox-s、l、m、x系列

在对Yolov3 baseline进行不断优化,获得不错效果的基础上。

作者又对Yolov5系列,比如Yolov5s、Yolov5m、Yolov5l、Yolov5x四个网络结构,也使用一系列trick进行改进。

先来看一下,改进了哪些地方?

我们主要对Yolov5s进行对比,下图是Yolov5s的网络结构图:

picture.image

我们再看一下Yolox-s的网络结构:

picture.image

由上面两张图的对比,及前面的内容可以看出, Yolov5s和Yolox-s主要区别 在于:

(1)输入端: 在Mosa数据增强的基础上,增加了Mixup数据增强效果;

(2)Backbone: 激活函数采用SiLU函数;

(3)Neck: 激活函数采用SiLU函数;

(4)输出端: 检测头改为Decoupled Head、采用anchor free、multi positives、SimOTA的方式。

在前面Yolov3 baseline的基础上,以上的tricks,取得了很不错的涨点。

在Yolov5一系列框架中呢?

下图是对Yolov5s、Yolov5m、Yolov5l、Yolov5x四个网络的改进效果对比图:

picture.image

可以看出,在速度增加1ms左右的情况下,AP精度实现了 0.8~2.9的涨点。

且网络结构越轻,比如Yolox-s的时候,涨点最多,达到 2.9的涨点。

随着网络深度和宽度的加深,涨点慢慢降低,最终Yolox-x有 0.8的涨点。

3.2.4 轻量级网络研究

在对Yolov3、Yolov5系列进行改进后,作者又设计了两个轻量级网络,与Yolov4-Tiny、和Yolox-Nano进行对比。

在研究过程中,作者有两个方面的发现,主要从轻量级网络,和数据增强的优缺点,两个角度来进行描述。

3.2.4.1 轻量级网络

因为实际场景的需要,很多同学想将Yolo移植到边缘设备中。

因此作者针对Yolov4-Tiny,构建了 Yolox-Tiny网络结构。

针对FCOS 风格的NanoDet,构建了 Yolox-Nano网络结构。

picture.image

从上表可以看出:

(1)和Yolov4-Tiny相比,Yolox-Tiny在参数量下降1M的情况下,AP值实现了 9个点的涨点。

(2)和NanoDet相比,Yolox-Nano在参数量下降,仅有0.91M的情况下,实现了 1.8个点 的涨点。

(3)因此可以看出,Yolox的整体设计,在轻量级模型方面,依然有很不错的改进点。

3.2.4.2 数据增强的优缺点

在Yolox的很多对比测试中,都使用了数据增强的方式。

但是不同的网络结构,有的深有的浅,网络的学习能力不同,那么 无节制的数据增强是否真的更好呢?

作者团队,对这个问题也进行了对比测试。

picture.image

通过以上的表格有以下发现:

① Mosaic和Mixup混合策略

(1)对于轻量级网络,Yolox-nano来说,当在Mosaic基础上,增加了Mixup数据增强的方式,AP值不增反而降,从 25.3降到24。

(2)而对于深一些的网络,Yolox-L来说,在Mosaic基础上,增加了Mixup数据增强的方式,AP值反而有所上升,从 48.6增加到49.5。

(3)因此不同的网络结构,采用数据增强的策略也不同,比如Yolox-s、Yolox-m,或者Yolov4、Yolov5系列,都可以使用不同的数据增强策略进行尝试。

② Scale 增强策略

在Mosaic数据增强中,代码Yolox/data/data_augment.py中的random_perspective函数,生成仿射变换矩阵时,对于图片的缩放系数,会生成一个随机值。

picture.image

(1)对于Yolox-l来说,随机范围scale设置在[0.1,2]之间,即文章中设置的默认参数。

(2)而当使用轻量级模型,比如YoloNano时,一方面只使用Mosaic数据增强,另一方面随机范围scale,设置在[0.5,1.5]之间,弱化Mosaic增广的性能。

3.3 Yolox的实现成果

3.3.1 精度速度对比

前面我们了解了Yolox的各种trick改进的原因以及原理,下面我们再整体看一下各种模型精度速度方面的对比:

picture.image

左面的图片是相对比较 标准的 ,网络结构的对比效果,主要从 速度和精度 方面,进行对比。

而右面的图片,则是 轻量级网络 的对比效果,主要对比的是 参数量和精度。

从左面的图片可以得出:

(1)和与Yolov4-CSP相当的 Yolov5-l 进行对比,Yolo-l在COCO数据集上,实现AP50%的指标,在几乎相同的速度下超过Yolov5-l 1.8个百分点。

(2)而 Yolox-Darknet53 和Yolov5-Darknet53相比,实现AP47.3%的指标,在几乎同等速度下,高出3个百分点。

而从右面的图片可以得出:

(1)和Nano相比, Yolox-Nano 参数量和GFLOPS都有减少,参数量为0.91M,GFLOPS为1.08,但是精度可达到25.3%,超过Nano1.8个百分点。

(2)而 Yolox-Tiny 和Yolov4-Tiny相比,参数量和GFLOPS都减少的情况下,精度远超Yolov4-Tiny 9个百分点。

3.3.2 Autonomous Driving竞赛

在CVPR2021自动驾驶竞赛的, Streaming Perception Challenge赛道 中,挑战的主要关注点之一,是自动驾驶场景下的实时视频流 2D目标检测 问题。

由一个服务器收发图片和检测结果,来模拟视频流30FPS的视频,客户端接收到图片后进行实时推断。

竞赛地址:https://eval.ai/web/challenges/challenge-page/800/overview

picture.image

在竞赛中旷视科技采用 Yolox-l作为参赛模型 , 同时使用TensorRT进行推理加速,最终获 得了full-track和detection-only track,两个赛道比赛的第一。

因此Yolox的各种改进方式还是挺不错,值得好好学习,深入研究一下。

picture.image

4 深入浅出Yolox之自有数据集训练

因为 Yolox 的代码,和之前的 Yolov3、Yolov4、Yolov5版本 还是有很多不同的地方。

很多同学可能对于如何利用自有数据集训练?还是有些疑惑。

因此大白另外也写了一篇《深入浅出Yolox之自有数据集训练》的文章。

利用 教室场景中,人头部标注的数据集 ,和大家一起一步步训练。

文章链接: 《深入浅出Yolox之自有数据集训练超详细教程》

5 不同的落地模型部署方式

当模型训练好,需要在 项目中进行部署时。

作者在代码中,还贴心的整理了各种版本的部署方式:

picture.image

比如以上5种方式:

(1)MegEngine: 基于旷视科技的深度学习框架,MegEngine的部署方式。也是Brain++的核心组件,主要有C++和Python两种方式。

(2)ONNX和Tensorrt两种方式: 英伟达的两种方式都有支持,主要有C++和Python两个方式,常常用在GPU服务器推理中。

(3)NCNN: 腾讯优图开源的手机端推理框架,主要有C++和Java版本。

(4)OpenViNO: Intel公司开源的深度学习应用套件,主要有C++和Python版本。

一般情况下,可以选择 Yolox-Nano、Yolox-Tiny、Yolox-s用于移动端部署 。

Yolox-m、Yolox-l、Yolox-x用于GPU服务器部署。

大家也可以根据自己项目的需求,选择不同的部署方式。

6 后续更新ing

当然在Yolox的代码中,大白发现旷视作者的工作,还是不断改进中。后期也会推出很多改进的工作。

picture.image

大家也可以先 关注、点赞、收藏 ,后续有更新后,大白也会在本文中进行调整修改,更新到文章中。

7 相关推荐:数据集分类下载

当然除了训练中使用到的人头数据集,在 大白网站 的数据集下载版块,还整理了数百种,不同类型的数据集:

picture.image

大家也可以根据自己的需要,选择不同的数据集,进行下载尝试。

数百种数据集汇总链接: www.jiangdabai.com

希望大白制作的,关于Yolov3、Yolov4、Yolov5、Yolox的一系列文章和视频,对大家工作和学习有帮助!

[picture.image

牛津大学提出PSViT | Token池化+Attention Sharing让Transformer模型不在冗余!!!](http://mp.weixin.qq.com/s?__biz=MzU5OTA2Mjk5Mw==&mid=2247490236&idx=1&sn=a1601dd82f570b61e6a923fe1924591c&chksm=febbfa02c9cc7314fd6d964cea17265dacc3d36a08d7dc438873267ff8539ab774113cf10d4c&scene=21#wechat_redirect)

[picture.image

YOffleNet | YOLO V4 基于嵌入式设备的轻量化改进设计](http://mp.weixin.qq.com/s?__biz=MzU5OTA2Mjk5Mw==&mid=2247490063&idx=1&sn=d22fe29cca4a9b7eb1b136b7fbb79795&chksm=febbfab1c9cc73a78c4ee401da97b848c5a81b61a293a68803a4280800e8fec4a986d7c1cda7&scene=21#wechat_redirect)

[picture.image

详细解读GraphFPN | 如何用图模型提升目标检测模型性能?](http://mp.weixin.qq.com/s?__biz=MzU5OTA2Mjk5Mw==&mid=2247490028&idx=1&sn=4166889e22c31f3c0af7a376967b5dca&chksm=febbf952c9cc70442f63ef7155bbd6cb0535ccb4ae6ea6f110af8e14cdabfad9fa4865feeaae&scene=21#wechat_redirect)

长按扫描下方二维码添加小助手并加入交流群, 群里博士大佬云集, 每日讨论话题有目标检测、语义分 割、 超分辨率、模型部署、数学基础知识、算法面试题分享的等等内容,当然也少不了搬砖人的扯犊子

长按扫描下方二维码添加小助手。

可以一起讨论遇到的问题

picture.image

声明:转载请说明出处

扫描下方二维码关注【 集智书童 】公众号,获取更多实践项目源码和论文解读,非常期待你我的相遇,让我们以梦为马,砥砺前行!

picture.image

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
如何利用云原生构建 AIGC 业务基石
AIGC即AI Generated Content,是指利用人工智能技术来生成内容,AIGC也被认为是继UGC、PGC之后的新型内容生产方式,AI绘画、AI写作等都属于AIGC的分支。而 AIGC 业务的部署也面临着异构资源管理、机器学习流程管理等问题,本次分享将和大家分享如何使用云原生技术构建 AIGC 业务。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论