本文给大家带来的百面算法工程师是深度学习目标检测YOLOv5面试总结,文章内总结了常见的提问问题,旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中,我们还将介绍一些常见的深度学习目标检测面试问题,并提供参考的回答及其理论基础,以帮助求职者更好地准备面试。通过对这些问题的理解和回答,求职者可以展现出自己的深度学习目标检测领域的专业知识、解决问题的能力以及对实际应用场景的理解。同时,这也是为了帮助求职者更好地应对深度学习目标检测岗位的面试挑战,提升面试的成功率和竞争力。
1.数据增强模块
YOLOv5 目标检测算法中使用的数据增强比较多,包括:
- Mosaic 马赛克
- RandomAffine 随机仿射变换
- MixUp
- 图像模糊等采用 Albu 库实现的变换
- HSV 颜色空间增强
- 随机水平翻转
其中 Mosaic 数据增强概率为 1,表示一定会触发,而对于 small (s)和 nano(n) 两个版本的模型不使用 MixUp,其他的 l/m/x 系列模型则采用了 0.1 的概率触发 MixUp。小模型能力有限,一般不会采用 MixUp 等强数据增强策略。
其核心的 Mosaic + RandomAffine + MixUp 过程简要绘制如下:
下面对其进行简要分析
- Mosaic 马赛克
Mosaic 属于混合类数据增强,因为它在运行时候需要 4 张图片拼接,变相的相当于增加了训练的 batch size。其运行过程简要概况为:
- 随机生成拼接后 4 张图的交接中心点坐标,此时就相当于确定了 4 张拼接图片的交接点
- 随机选出另外 3 张图片的索引以及读取对应的标注
- 对每张图片采用保持宽高比的 resize 操作将其缩放到指定大小
- 按照上下左右规则,计算每张图片在待输出图片中应该放置的位置,因为图片可能出界故还需要计算裁剪坐标
- 利用裁剪坐标将缩放后的图片裁剪,然后贴到前面计算出的位置,其余位置全部补 114 像素值
- 对每张图片的标注也进行相应处理
注意:由于拼接了 4 张图,所以输出图片面积会扩大 4 倍,从 640x640 变成 1280x1280,因此要想恢复为 640x640, 必须要再接一个 RandomAffine 随机仿射变换,否则图片面积就一直是扩大 4 倍的。
- RandomAffine 随机仿射变换
随机仿射变换有两个目的:
- 对图片进行随机几何仿射变换
- 将 Mosaic 输出的扩大 4 倍的图片还原为 640x640 尺寸
随机仿射变换包括平移、旋转、缩放、错切等几何增强操作,同时由于 Mosaic 和 RandomAffine 属于比较强的增强操作,会引入较大噪声,因此需要对增强后的标注进行处理,过滤规则为:
- 增强后的 gt bbox 宽高要大于 wh_thr
- 增强后的 gt bbox 面积和增强前的 gt bbox 面积比要大于 ar_thr,防止增强太严重
- 最大宽高比要小于 area_thr,防止宽高比改变太多
[!CAUTION]
由于旋转后标注框会变大导致不准确,因此目标检测里面很少会使用旋转数据增强。
- MixUp
MixUp 和 Mosaic 类似也属于混合图片类增强方法。随机选出另外一张图后将两图再随机混合。具体实现方法有多种,常见的做法是要么将 label 直接拼接起来,要么将 label 也采用 alpha 方法混合。原作者的做法非常简单,对 label 即直接拼接,而图片通过分布采样混合。
需要特别注意的是: YOLOv5 实现的 MixUp 中,随机出来的另一张图也需要经过 Mosaic 马赛克 + RandomAffine 随机仿射变换 的增强后才能混合。这个和其他开源库实现可能不太一样。
- 图像模糊和其他数据增强策略
剩下的数据增强包括
- 图像模糊等采用 Albu 库实现的变换【这个库默认是被注释掉的,不进行这个增强操作】
- HSV 颜色空间增强
- 随机水平翻转
2.网络结构
YOLOv5 网络结构是标准的 CSPDarknet
+ PAFPN
+ 非解耦 Head
。
YOLOv5 网络结构大小由 deepen_factor
和 widen_factor
两个参数决定。其中 deepen_factor
控制网络结构深度,即 CSPLayer
中 DarknetBottleneck
模块堆叠的数量;widen_factor
控制网络结构宽度,即模块输出特征图的通道数。以 YOLOv5-l 为例,其 deepen_factor = widen_factor = 1.0
。P5 的模型整体结构如第一张图所示
图的上半部分为模型总览;下半部分为具体网络结构,其中的模块均标有序号,方便用户与 YOLOv5 官方仓库的配置文件对应;中间部分为各子模块的具体构成。
如果想使用 netron 可视化网络结构图细节,可以直接在 netron 中将导出的 ONNX 文件格式文件打开。
Backbone
CSPDarknet
继承自BaseBackbone
,整体结构和ResNet
类似。P5 模型共 5 层结构,包含 1 个Stem Layer
和 4 个Stage Layer
:Stem Layer
是 1 个 6x6 kernel 的ConvModule
,相较于 v6.1 版本之前的Focus
模块更加高效。- 除了最后一个
Stage Layer
,其他均由 1 个ConvModule
和 1 个CSPLayer
组成。如上图 Details 部分所示。 其中ConvModule
为 3x3的Conv2d
+BatchNorm
+SiLU 激活函数
。CSPLayer
即 YOLOv5 官方仓库中的 C3 模块,由 3 个ConvModule
+ n 个DarknetBottleneck
(带残差连接) 组成。 - 最后一个
Stage Layer
在最后增加了SPPF
模块。SPPF
模块是将输入串行通过多个 5x5 大小的MaxPool2d
层,与SPP
模块效果相同,但速度更快。 - P5 模型会在
Stage Layer
2-4 之后分别输出一个特征图进入Neck
结构。以 640x640 输入图片为例,其输出特征为 (B,256,80,80)、(B,512,40,40) 和 (B,1024,20,20),对应的 stride 分别为 8/16/32。 P6 模型会在
Stage Layer
2-5 之后分别输出一个特征图进入Neck
结构。以 1280x1280 输入图片为例,其输出特征为 (B,256,160,160)、(B,512,80,80)、(B,768,40,40) 和 (B,1024,20,20),对应的 stride 分别为 8/16/32/64。Neck
YOLOv5 官方仓库的配置文件中并没有 Neck 部分,为方便用户与其他目标检测网络结构相对应,我们将官方仓库的 Head
拆分成 PAFPN
和 Head
两部分。
基于 BaseYOLONeck
结构,YOLOv5 Neck
也是遵循同一套构建流程,对于不存在的模块,我们采用 nn.Identity
代替。
Neck 模块输出的特征图和 Backbone 完全一致。即 P5 模型为 (B,256,80,80)、 (B,512,40,40) 和 (B,1024,20,20);P6 模型为 (B,256,160,160)、(B,512,80,80)、(B,768,40,40) 和 (B,1024,20,20)。
- Head
YOLOv5 Head 结构和 YOLOv3 完全一样,为 非解耦 Head
。Head 模块只包括 3 个不共享权重的卷积,用于将输入特征图进行变换而已。
[!IMPORTANT]
前面的 PAFPN 依然是输出 3 个不同尺度的特征图,shape 为 (B,256,80,80)、 (B,512,40,40) 和 (B,1024,20,20)。 由于 YOLOv5 是非解耦输出,即分类和 bbox 检测等都是在同一个卷积的不同通道中完成。以 COCO 80 类为例:
- P5 模型在输入为 640x640 分辨率情况下,其 Head 模块输出的 shape 分别为
(B, 3x(4+1+80),80,80)
,(B, 3x(4+1+80),40,40)
和(B, 3x(4+1+80),20,20)
。 P6 模型在输入为 1280x1280 分辨率情况下,其 Head 模块输出的 shape 分别为
(B, 3x(4+1+80),160,160)
,(B, 3x(4+1+80),80,80)
,(B, 3x(4+1+80),40,40)
和(B, 3x(4+1+80),20,20)
。 其中 3 表示 3 个 anchor,4 表示 bbox 预测分支,1 表示 obj 预测分支,80 表示 COCO 数据集类别预测分支。[x] 正负样本匹配策略
正负样本匹配策略的核心是确定预测特征图的所有位置中哪些位置应该是正样本,哪些是负样本,甚至有些是忽略样本。 匹配策略是目标检测算法的核心,一个好的匹配策略可以显著提升算法性能。
YOLOV5 的匹配策略简单总结为:采用了 anchor 和 gt_bbox 的 shape 匹配度作为划分规则,同时引入跨邻域网格策略来增加正样本。 其主要包括如下两个核心步骤:
[!IMPORTANT]
- 对于任何一个输出层,抛弃了常用的基于 Max IoU 匹配的规则,而是直接采用 shape 规则匹配,也就是该 GT Bbox 和当前层的 Anchor 计算宽高比,如果宽高比例大于设定阈值,则说明该 GT Bbox 和 Anchor 匹配度不够,将该 GT Bbox 暂时丢掉,在该层预测中该 GT Bbox 对应的网格内的预测位置认为是负样本
- 对于剩下的 GT Bbox(也就是匹配上的 GT Bbox),计算其落在哪个网格内,同时利用四舍五入规则,找出最近的两个网格,将这三个网格都认为是负责预测该 GT Bbox 的,可以粗略估计正样本数相比之前的 YOLO 系列,至少增加了三倍
- Anchor 设置
YOLOv5 是 Anchor-based 的目标检测算法,其 Anchor size 的获取方式与 YOLOv3 类似,也是使用聚类获得,其不同之处在于聚类使用的标准不再是基于 IoU 的,而是使用形状上的宽高比作为聚类准则(即 shape-match )。
- Bbox 编解码过程
在 Anchor-based 算法中,预测框通常会基于 Anchor 进行变换,然后预测变换量,这对应 GT Bbox 编码过程,而在预测后需要进行 Pred Bbox 解码,还原为真实尺度的 Bbox,这对应 Pred Bbox 解码过程。
在 YOLOv3 中,回归公式为:
公式中
而在 YOLOv5 中,回归公式为:
改进之处主要有以下两点:
- 中心点坐标范围从 (0, 1) 调整至 (-0.5, 1.5)
- 宽高范围从(0,+∞)调整到(0,4a)【4倍的anchor】
这个改进具有以下好处:
- 新的中心点设置能更好的预测到 0 和 1。这有助于更精准回归出 box 坐标。
- 宽高回归公式中 exp(x) 是无界的,这会导致梯度失去控制,造成训练不稳定。YOLOv5 中改进后的宽高回归公式优化了此问题。
- 匹配策略
anchor既是prior
正样本匹配包含以下两步:
(1) “比例”比较
将 GT Bbox 的 WH 与 anchor的 WH 进行“比例”比较。
此处我们用一个 GT Bbox 与 P3 特征图的 Prior 进行匹配的案例进行讲解和图示:
prior1 匹配失败的原因是 24 / 5 =4.8 > anchor_t
(2) 为步骤 1 中 match 的 GT 分配对应的正样本
依然沿用上面的例子:
GT Bbox (cx, cy, w, h) 值为 (26, 37, 36, 24),
Prior WH 值为 [(15, 5), (24, 16), (16, 24)],在 P3 特征图上,stride 为 8。通过计算,prior2 和 prior3 能够 match。
计算过程如下:
(2.1) 将 GT Bbox 的中心点坐标对应到 P3 的 grid 上
(2.2) 将 GT Bbox 中心点所在的 grid 分成四个象限,由于中心点落在了左下角的象限当中,那么会将物体的左、下两个 grid 也认为是正样本
下图展示中心点落到不同位置时的正样本分配情况:
那么 YOLOv5 的 Assign 方式具体带来了哪些改进?
- 一个 GT Bbox 能够匹配多个 Prior
- 一个 GT Bbox 和一个Prior 匹配时,能分配 1-3 个正样本
- 以上策略能适度缓解目标检测中常见的正负样本不均衡问题。
而 YOLOv5 中的回归方式,和 Assign 方式是相互呼应的:
- 中心点回归方式:
- WH 回归方式:
- [x] Loss
YOLOv5 中总共包含 3 个 Loss,分别为:
- Classes loss:使用的是 BCE loss
- Objectness loss:使用的是 BCE loss
- Location loss:使用的是 CIoU loss
三个 loss 按照一定比例汇总