【深度学习】目标检测比赛技巧总结

Posted by ShawnD on May 22, 2021

数据研究

这个步骤在数据分析领域叫做探索性数据分析EDA(Exploratory Data Analysis)

图像

a. 宽高频次图:

决定图片预处理方式。例如:像宫颈癌病理图属于高分辨率图片,那后续就得切小图准备合适的数据。

了解数据采样方式。例如:在水下检测赛里,就发现虽然有5种不同的宽高搭配,但它们的宽高比就两种:1.22和1.78,说明其水下拍摄采样的设备可能就有两种画幅宽高比,只是画幅大小可能比较多变,导致出现宽高比相同下但分辨率不同的图片。

可视化: 了解数据真实质量,采样环境等。

类别标签:

a. 类别频次图: 是否存在类别不平衡问题,如果类别严重不平衡,可能需要做额外的数据增广操作,最好研究下类别不平衡的原因,有可能是重复图片或者标注问题导致的,例如Kaggle上的鲸鱼尾巴分类大赛,它数据集中存在很多重复的图片,而且同一张图片存在多类别标注。

标注框:

a. 宽高散点图: 在训练尺度设置下,判断模型感受野是否设置合理。在训练模型前,图片往往要被Resize到给定的训练尺度(或多尺度),那么在绘制散点图前,要先将原标注框Resize到最大的给定尺度下,去绘制它Resize后的标注框宽高分布图。之后选取Backbone模型时,应考虑模型感受野尽量大于多数标注框的长边。

b. 各类下宽高比频次图: 是否个别类别存在极端宽高比情况,极端宽高比需要对锚点框相关默认设置(即Anchor Ratio 和 Anchor Scale)进行调整。

c. 各类下框面积大小频次图: 了解数据大/中/小目标的情况,尤其注意小目标,其次是大目标。小目标难检测。而在高分辨率上的过大目标可能需要合适的手段进行切分,例如宫颈癌切片里的Candida异常细胞(大多数目标的宽/高大于1000)。

数据准备

数据处理

a. 线下数据增强:

  • 空间不变性:神经网络模型具有空间不变性,为了解决它,一般需要采用一些空间增强手段例如平移、旋转、翻转、缩放、实例平衡增强等。
  • 噪声:神经网络模型有时候过于依赖训练数据,缺少推断能力而影响通用性,即使人眼能识别出噪声图片里的目标,但模型却不太行,所以为了让模型更加鲁棒,可以考虑在训练集内加入高斯噪声、椒盐噪声等对模型进行干扰。
  • 目标遮挡或重叠:如果数据研究时发现存在多框重叠现象,或者存在目标遮挡,可以试着采用Cutout 或Mixup 等。
  • 过采样 : 有时候整体数据量过少,或某类别数少导致类别不平衡,可以考虑使用copy-paste 、泊松融合等技巧,但要注意,增强的目标不要过于突兀,不然会造成模型过拟合。
  • 图像模糊: 图像模糊的原因有很多,例如:镜头模糊,雾天图像,水下光线散射等,对此的数据增强手段有中值/高斯/动态模糊、去雾算法, MSRCR等。
  • 其它:标签平滑, 色调归一化,Albumentation图片数据增强库等。以上所有数据增强方法分线上和线下两种使用方式,不同数据增强方法之间存在功能重叠,基本都能在一定程度上减少模型过拟合,但也可以会有过拟合的可能(例如copy-paste和实例平衡增强等会重复部分数据集的可能)。

b. 训练和测试集统一化: 有时候训练集和测试集存在分布不统一,例如:采样方式/地点不一致,标注人员/方式不一致。可能的话,尽可能保证它们的一致性,比如在水下目标检测里,训练集和测试集是在不同的水下深度拍摄的,那么图像色调就可能会不统一,如果你对训练集做去雾或一些后处理操作的话,需要考虑是否对测试集也得提前做相同的数据处理操作。另外,在Kaggle X光肺炎检测比赛中,训练集是由唯一的专家标记,而测试集是由三名独立的放射医师标记,这种情况下,使用他们标记的交集用于标签真值可能可以更好地统一训练和测试集的标签分布。

数据增强方式

MixUp

MixUp在分类任务中, 解决的问题主要是让模型更加鲁棒性的区分很相近的类别, 比如我们一个batch一个batch去训练的时候, 猫对应的label就是猫, 狗就是狗, 完全只靠看猫和狗来区分他们. 那么在实际情况中, 如果出现一个样本, 它长得既像猫又像狗, 但实际上这是一条狗, 网络可能就懵逼了。

MixUp采用配对的方式进行训练, 通过混合两个甚至是多个样本的分布, 同时加上对应的标签来训练, 用论文原文的话来说就是:

In essence, mixup trains a neural network on convex combinations of pairs of examples and their labels.

这其实就是MixUp最本生的思想.

Mosiac

这个数据增广方式, 出名于Yolov4, 也是来自于战斗民族的一种增广方法. 它通过排列四张图片, 以及对应的box来实现数据的增广方式.

比如我们在一个安检数据集上增加这个 Mosiac方式,这种方式可以增加单张图片的丰富度, 同时也能更好的让网络去定位每一个类别的位置. 它背后的数学基础并没有太复杂, 只是这个东西它好像确实work, 至少在coco上是如此.

CutMix

CutMix就是把一个物体抠出来, 粘贴到另一张图上去.

这个增强的效果怎么样呢?从分类的角度来说, 貌似对于分类有一些增长, 但是, 问题在于, 你CutMix的方式似乎有讲究, 图片中只是看到了猫头和狗尾巴, 万一反过来了呢? 还应该分类为什么?

填鸭式数据增强

填鸭式对小目标的检测应该效果不错,比如一张图片里目标较少,又比较小,可能网络并不能有效注意到这样的目标。通过填鸭式数据增强方式,即复制此目标至图片多处位置,增加其在图片上的数量来加强训练。

数据集划分

a. 传统划分法: 传统方法就是直接按比例划分,例如原数据80%划为训练集,20%划为测试集。

b. 分层抽样法式划分: 按照规定的比例从各类下抽取一定的样本,优点是抽取的样本考虑到了类别。在该划分的测试集上,后续验证会有更全面且客观的结果。

c. Domain划分法: 按照规定比例从各Domain下抽取一定的样本。该方法是水下目标检测比赛中,听郑烨选手提到的一个划分方法,当时水下图像集是在不同年份、不同水下地点和不同设备拍摄的几段视频中截图标注得到的。因此可以考虑针对不同年份/不同拍摄视频段/设备,划分好Domain后,再从这些Domain下抽取一定比例的样本。

d. K折划分法: 在中,参赛者就将相同模型的四折交叉验证的输出合并,进而检验模型的结果。

在数据集划分中,提到的四种数据集划分方法可以相互结合使用,例如Domain下分层抽样式划分,不同的划分方法耗费的时间都不一样,一般建议如下:

各类别数据量大且类别较平衡:传统划分法。

类别不平衡且某类别数据量少:分层抽样式法。

存在明显Domain且Domain数较少:Domain划分法。

数据量较小或算力充足:K折划分法。

参数调节

训练前

a. 数据增强:

  • 空间不变性:神经网络模型具有空间不变性,为了解决它,一般需要采用一些空间增强手段例如平移、旋转、翻转、缩放、实例平衡增强等。
  • 噪声:神经网络模型有时候过于依赖训练数据,缺少推断能力而影响通用性,即使人眼能识别出噪声图片里的目标,但模型却不太行,所以为了让模型更加鲁棒,可以考虑在训练集内加入高斯噪声、椒盐噪声等对模型进行干扰。
  • 目标遮挡或重叠:如果数据研究时发现存在多框重叠现象,或者存在目标遮挡,可以试着采用Cutout 或Mixup 等。
  • 过采样 : 有时候整体数据量过少,或某类别数少导致类别不平衡,可以考虑使用copy-paste 、泊松融合等技巧,但要注意,增强的目标不要过于突兀,不然会造成模型过拟合。
  • 图像模糊: 图像模糊的原因有很多,例如:镜头模糊,雾天图像,水下光线散射等,对此的数据增强手段有中值/高斯/动态模糊、去雾算法, MSRCR等。
  • 其它:标签平滑, 色调归一化,Albumentation图片数据增强库等。以上所有数据增强方法分线上和线下两种使用方式,不同数据增强方法之间存在功能重叠,基本都能在一定程度上减少模型过拟合,但也可以会有过拟合的可能(例如copy-paste和实例平衡增强等会重复部分数据集的可能)。

训练时

a. 训练尺度: 根据显存和时间安排设置训练是否采取多尺度,正常来说,尺度越大越好,小目标能更好的被检测到,但也存在尺度调整过大,图片失真。在设置尺度上,一般是放开Resize对长边的依赖(即长边至少为:训练原图尺寸最大长短比 * Resize短边上限),mmdetection论文提到提高短边上限能带来提升。

b. 测试尺度: 取训练尺度的中间值即可。假设训练多尺度设置是[(4096, 600), (4096, 1000)],那么测试尺度如果你想设为单尺度,可以是(4096, 800),如果是多尺度,可以是[(4096, 600), (4096, 800), (4096, 1000)]。测试多尺度会更好些,但推理速度会变慢。

c. Anchor (scales & ratios): 正常来说,锚点框的设置保持默认配置就好,但是如果遇到某类别目标是极端长宽比,则可能需要根据数据研究的结果适当调整下锚点框宽高比率,而锚点框大小scale相对来说不太需要对其进行过多调整。可以添加多一个Anchor Ratio,但不建议自行胡乱调参。

如果检测小目标居多,可以调小anchor大小。

d. Backbone: 目标检测的主干网络很多,选择主干网络的第一要素就是得先确认模型的感受野是否尽可能大于数据集多数标注框的长边。当你确定了训练尺度,选择最大Resize比例去绘制标注框宽高散点图,然后选取合适的模型Backbone。如果模型感受野太小,只能观察到局部特征,不足以得到整个目标的信息;如果感受野过大,则会引入过多的无效信息。现在计算感受野有两种方法:(1)从上往下法:即从低层到高层,这种方法计算更便捷些,但只适用于比较有限的卷积,且由于没有处理由Stride引起的抽取像素重叠的问题,使得计算的感受野会偏大些;(2)从下往上法:即从高层到低层,计算感受野是通过递推计算,它很准确。这里不详细展开,详情计算方式可见 目标检测和感受野的总结与想法。限制一些SOTA的主干模型有:ResNet, ResNeXt, DenseNet, SENet等。此外,如果存在极端宽高比的目标,可以使用可变形卷积网络(Deformable Convolution Net, DCN)。

e. Neck: 用的比较多的就特征金字塔网络(Feature Pyramid Networks, FPN),对于小目标检测非常好用。

f. ROIHead: 在mmdetection里RoIHead的作用是帮助模型基于RoI进行预测,现在比较受欢迎的模型是Cascade R-CNN,它级联三个不同IOU阈值(0.5,0.6,0.7)的头,但在2019广东工业智造创新大赛决赛上,某团队针对评测mAP要求的IOU阈值0.1、0.3和0.5,降低了级联的阈值至0.4、0.5和0.6,从而获得了提升,说明宽松评测下,级联头阈值可适当减低以获取更多的预测框,这种方式可能会提升性能。另外,在天池”重庆大赛-瓶装白酒疵品质检”里,好像也还有选手通过增加多一个head,在某种程度上帮助模型更好的拟合数据,但不一定在每个赛题数据上都起作用。

g.混合精度训练: 开启fp16能加快模型运算速度。

h.学习率: 学习率的设置应参考论文 Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour. 该论文提到在使用多GPU并行进行Minibatch SGD的行为被称作Large Minibatch SGD。假设有k个GPUs,那么Large Minibatch size =k * Minibatch size(即mmdetection中的img_per_batch),此时多GPU下学习率 = 单GPU下的Lr * k。总结来说,Lr = GPU数量 * Minibatch Size * 0.00125。

学习率在衰退前使用warmup会好些,衰退策略使用Cosine会比Step更快帮助模型拟合数据。此外,mmdetection作者认为像多尺度训练这样的训练增强应该需要24epoch数进行训练,但一般来说1x的训练epoch数就能应付较多的场景。个人认为,1x(2epochs)和2x(24epochs)的选择得看训练后的损失曲线或mAP曲线的表现来决定。

训练后:

如果EDA发现存在大量同类下多框重叠,例如水下图像中经常多个海胆目标重叠,建议使用Soft NMS。此外,在mmdetection中NMS都是在类内完成的,如果EDA发现数据不存在类间重叠(这种情况比较少发生),则可以考虑自己额外补充类间NMS(即所有类下的框一起NMS)。

模型验证

模型验证阶段看三个曲线:各类别AP曲线、不同IoU下的MAP曲线、损失曲线。

  • AP曲线: 发现哪个类别的目标检测效果差,后续可以针对表现差的类别进行模型改进,例如: 专家模型,改变数据处理方式等。
  • MAP曲线: 更好的贴合比赛的评测指标,给出最直观的结果。
  • 损失曲线: 观察模型拟合表现,如果模型损失下降过快或过慢,可适当调节学习率或学习率衰减节点的设置。

模型融合

融合选择

在知乎上,知乎:你有哪些deep learning(rnn、cnn)调参的经验?提供了关于模型集成的几种选择:

  • 同样的参数,不同的初始化方式。
  • 不同的参数,通过cross-validation,选取最好的几组。
  • 同样的参数,模型训练的不同阶段,即不同迭代次数的模型。
  • 不同的模型,进行线性融合,例如RNN和传统模型。

融合方式:

a. 直接合并: 根据验证集的表现,选取不同模型设置下,最好表现的类别结果进行合并,例如有2个不同的模型设置(设置1和2)且预测类别有2个(类别A和B),类别A在模型设置2下表现最好,而类别B在模型设置1下表现最好,那么最后的提交结果应该由模型设置2下的类别A结果和模型设置1下的类别B结果合并组成。优点是该合并比较简单快速,缺点是它要求验证集的真实反应能力强,比如之前宫颈癌细胞检测比赛,数据集很大,验证集表现和线上测试集表现基本一致,它就很适合直接合并模型结果。

b. WBF: 权重框融合Weighted Boxes Fusion也是比较受欢迎的模型集成方法,它将同类下达到某IoU的框们,进行加权平均得到最终的框,权重为各预测框上预测类别的分数。WBF有两种融合思路: 不同backbone的融合和不同结构的模型的融合,据论文(代码已开源 知乎:你有哪些deep learning(rnn、cnn)调参的经验?)所述这种方法比前者提升更大。在使用中要注意,Soft NMS输出结果要搭配max的置信度融合方法(即在两个模型预测结果中选择其中最大的置信度作为平均融合框的置信度,避免平均融合后的结果不会受冗余低分框影响),而普通NMS输出结果搭配avg融合方式即可。

Tricks

伪标签策略(在kaggle小麦检测上可以提三个点),请参考如下

https://www.kaggle.com/nvnnghia/yolov5-pseudo-labeling

https://www.kaggle.com/nvnnghia/fasterrcnn-pseudo-labeling

WBF,TTA是涨点神器

比赛中无脑降低score的阈值会提升mAP,会有较多误检。

采用coco和pascal voc的评测方法, 一般都会讲confidence_th设的比较低, 0.001左右, 相当于把PR曲线往后拉长了, mAP自然会长。

两个重要的数据增强策略:Mixup以及填鸭式,下面是一个简单的实现

https://github.com/chuliuT/Tianchi_Fabric_defects_detection/blob/master/final_commit/Duck_inject.py

Awesome Library

EDA(Exploratory Data Analysis)

https://github.com/Ying-Kang/TianCHI_guangdong/blob/main/eda.ipynb?spm=5176.12282029.0.0.26b21aaa83A2vL&file=eda.ipynb

https://github.com/gfjiangly/cvtools

model ensemble

soft-NMS

softnms算法可以对检测框进行置信度排序,与最大置信度的检测框的IoU越大,得分越低,所有可以获得这种大小关系, 如果再选择了合适的置信度阈值,就可以保留1号框和2号框,同时剔除3号框。

Weighted Boxes Fusion

WBF的流程

  • 来自每个模型的预测框被添加到列表 B。 列表根据置信度分数 C 降序排列。
  • 声明两个空列表 LF, 分别用作 boxes簇 和 融合boxes。 列表 L 中的每个位置包含来自 boxes簇 的一组或一个检测框; F 中的每个位置仅包含一个检测框, 它是 L 中的boxes簇融合得到的检测框。
  • 循环迭代 B 中的预测框 并且 尝试从列表 F 中匹配一个box。 匹配 被定义为 交并比大于阈值(IoU > THR)。 、
  • 如果没有匹配到, 将来一列表 B 的box添加到列表 L 和列表 F 的尾部。 处理列表 B 的下一个 box。
  • 如果匹配到了, 将这个box添加到列表 L 里, 其索引为列表 F 对应的 pos 位置。
  • 使用 簇 L[pos] 的 T 个 boxes, 重新计算 F[pos] 的 box 坐标和置信度分数, 使用下面的公式
\[C = \frac{\sum_{i=1}^T C_i}{T}\] \[X1, 2 = \frac{\sum_{i=1}^T C_i * X1, 2_i}{\sum_{i=1}^T C_i}\] \[Y1, 2 = \frac{\sum_{i=1}^T C_i * Y1, 2_i}{\sum_{i=1}^T C_i}\]

我们也可以使用一些非线性的权重, 比如,$C^2$, $\sqrt{C}$ 等

设定置信度的分数为所有用于融合的边界框的平均置信度。 融合框的坐标是所有用于融合的坐标的加权和, 其中权重是对应边界框的置信度。 因此, 高置信度的边界框比低置信度的边界框贡献更大。

  • 所有B中的边界框都处理后, 重新缩放列表 F 中的置信度分数。
\[C = C * \frac{\min (T, N)}{N}\]

或者:

\[C = C * \frac{T}{N}\]

Reference

  1. 目标检测类算法比赛的经验总结
  2. 目标检测比赛思路、tricks集锦、资料汇总
  3. 全网最全:盘点那些图像数据增广方式Mosiac,MixUp,CutMix等.
  4. https://github.com/ZFTurbo/Weighted-Boxes-Fusion