前段时间我们支持了 YOLOX,在复现中多亏了 5 位社区用户的积极参与,使其有望在短时间发布,在此再次表示感谢!
关于 YOLOX 复现细节见:
https://zhuanlan.zhihu.com/p/398545304
5 位社区用户的 github 账号如下,欢迎大家去主页逛逛~
- HAOCHENYE :
https://github.com/HAOCHENYE
- xiaohu2015 :
https://github.com/xiaohu2015
- zhiqwang :
https://github.com/zhiqwang
- HsLOL :
https://github.com/HsLOL
- shinya7y :
https://github.com/shinya7y
后续,我们也和参与的社区用户进行了深入沟通,希望能够得到宝贵意见以便更好的共同完善 MMDetection (shinya7y 由于不在国内,没有联系到)。
罗马不是一日建成,大佬也不是生来就是大佬~
我们的贡献者们又经历过怎样的灵感闪光,怎样迈过一座座大山呢?
让我们一起来听听社区贡献者的心声吧!!!
@HAOCHENYE
作为 MMDetection 的忠实粉丝以及重度用户,能够参与到这次 YOLOX 的复现中,真的是太令人兴奋了。回顾整个过程委实收获颇丰,在此十分感谢 OpenMMLab 的大佬们的指导以及一起奋战的小伙伴~!在这次过程中我主要负责数据部分的对齐,在此记录一些感悟心得。
团队协作复现
作为一个小厂工作的算法工程师,其实鲜有多人协作贡献代码的经历,基本一个项目就是自己在主线分支一路狂奔。这次复现经历对我来说最宝贵,其实不是一些代码,理论层面的知识,而是这样团队协作模式的学习。
这里真的真的非常感谢 OpenMMLab 大佬对我的帮助,帮我解决各种愚蠢的 GIT 问题,耐心的教我 PR 流程,规范我的 GIT 行为,太有爱了!!
代码迁移
YOLOX 相较于 YOLOv5,其马赛克增强部分的代码基本是完全迁移的,其原创的部分主要在于 MixUp增强,以及最后 15 个 epoch 开关数据增强的模式。考虑到第一版的复现旨在还原精度,因此我只需要把 YOLOX 的整个 MosaicDetectionDataset 移植过来,做好和 Pipeline 的对接工作即可。但是需要注意的有两点:
1. YOLOX 的 YOLOBatchSampler 不仅仅返回当前所需的 Index,还会返回当前 batch 图像的 size,辅助 Dataset 进行多尺度训练,因此 MMDetection 也需要一个 Hook 进行类似操作,在 after_train_iter 的方法中修改 Dataset 的尺度。
2. 最后 15 个epoch关闭增强的操作也在 Hook 中进行,Dataset 需要为其预留 flag。
代码整合
在完成精度校验后,需要将 YOLOX 的代码转换成 MMDetection 风格,这个步骤做了非常多的讨论尝试,主要分为以下几种:
(1) 把 MosaicDataset 作为一个新的 Wrapped_dataset,内置 Mosaic 和 MixUp 增强。
- 优点:风格和 YOLOX 基本一致,改动小,维持了 Pipeline 的轻量。
- 缺点:Mosaic 和 MixUp 本质上是一种数据增强,放在 Dataset 中理不合,不利于其他任务的灵活调用
(2) 新增 Mosaic 和 Mixup Pipeline,在 Pipeline 中完成 Dataset 的构造,内部可以访问训练数据集,实现数据增强。
- 优点:逻辑清晰,调用灵活。
- 缺点:Pipeline过于重,构造缓慢,以 YOLOX 任务为例,训练过程重新需要加载3遍训练数据,耗时过长。
(3) 新增 MultiImageMixDataset 和 Mosaic 和 Mixup 的 Pipeline,MultiImageMixDataset 调用Mosaic 和 Mixup Pipeline 的接口,获取融合图片的 Index,将图片取出后传递给 Pipeline,实现数据增强。
- 优点:Pipeline 灵活,并且共享一个 Dataset,轻量,可太妙了。
- 缺点:有啥缺点嘞?
经过和大佬的讨论,最后敲定了第三种方案。
精度复查
不幸的是,经过代码整合后,精度没有对上,为了排除 Dataset 部分的问题,只能做 1 对 1 的校验了。我将 YOLOX 的 MosaicDetection Dataset 移植到 MMDetection 中。
同时建立 MultiImageMixDataset 及对应 Pipeline 和 MosaicDetection,使用一个猥琐的函数去除所有随机性,for 循环顺序遍历两个 Dataset,核对精度。经验证的确发现了一些问题 ——
YOLOX 的 bboxes 获取存在 1 个像素的误差;
YOLOX 过滤了小 bboxes,而 MMDetection 版本没有做;
np.array 转换成 float 后,图像总体均值会有 0.5 左右的差异,而 MMDetection 和 YOLOX 转浮点的时机不同,会造成 0.5 左右的均值像素误差;
然而经测试,以上原因均不是导致训练误差的原因,经测试,对齐后的两个 Dataset,image 和 bbox 的误差均在 1e-4 以内。
精度再查
梅开二度,训练精度还是没对上,于是我考虑 Dataset 在完整项目中的对齐效果。我将 YOLOX 的Trainer 抄到 MMDetection 中,删除 Model 相关的代码,保留 Dataset、Dataloader 和多尺度训练的代码。
此外还保留每个数据增强函数的随机性, 使用装饰器对每个函数设置随机种子,保证每个对应的函数产生相同的随机数。一顿操作下来,验证 Dataset 的精度是对齐的。
总结
经过这次的合作开发,我对 MMDetection 理解又更上一层楼啦,也对一些设计理念有了更深的理解,感觉稍微孵化一下,再结合 MMCV,自己也能写出个比较规范的其他领域的项目。此外更重要的是,我在平时的工作中能够更加规范的使用 GIT 来进行合作开发,也会用更加严格的标准去规范自己的编程风格,委实受益匪浅。能参与到这样的项目中,和大佬们交流学习真的太好啦!
最后祝 MMDetection 发展越来越好,Star 蹭蹭涨,高性能又快又好模型越来越多!
@xiaohu2015
这次有幸参与使用 MMDetection 复现 YOLOX 的工作,收获很大,也非常感谢 reviewer 对我的帮助。这个过程中,除了加深了对 YOLOX 的理解外,我也对 MMDetection 的设计有了更多的理解,最重要的是对代码书写也有几点体会:
规范性
前期我曾参与 YOLOX 的训练 loss 的实现,其实也就是简单地把原始的实现给稍微修改一下,但这个明显不符合 MMDetection 的规范,看到后面 MMDetection 的 developer 实现的 loss,真是学习到了很多,比如说将 simOTA 单独抽离出来形成了一个类 SimOTAAssinger。
一个高质量的开源项目需要保持一定的规范性,我觉得这也是 MMDetection 受众多的一个重要原因。
简洁性
实现功能只是一个方面,在代码优化方面,我们应该多多想想怎么让代码更加简洁可懂,减少代码的冗余,这个也非常重要。在优化 EMA 那块时,对于两种不同的 EMA,我也抽离了它们共用的部分,放在base 类里面,让代码更加简洁。
这是我第一次参与开源项目的 PR,也是第一次参与 github 项目的团队协作,再次感谢 MMDetection 团体以及小组的每一个协助者。
在参与过程中,最大的体会是代码优化没有极限,一个优秀的开源框架,背后经过了很多人不断的打磨,不断的优化,不断的完善文档,不断的提高易用性等等。
感谢 MMDetection 团队不断的努力,不断的优化打造出如此优异的框架,同时也期待 OpenMMLab 开源框架系列越来越好,用户越来越多!
个人知乎账号
https://www.zhihu.com/people/xiaohuzc
@zhiqwang
首先感谢眸哥在整个 YOLOX 开发过程中给我们提供了很多帮助,仔细精准分配了任务,并帮助我们纠正对 YOLOX 网络和 MMDetection 框架的认识误区。
其次要感谢 MMDetection 给我们提供了一个非常好的平台供我们学习和成长,可以看出 MMDetection 花了很大心思来维护社区,所以才有了现在如此好的氛围和环境。
这次协同开发的过程中我也深刻感受到 MMDetection 的模块化设计优秀之处。可以看到 MMDetection 设计之初为考虑到能够容纳各种优秀的目标检测模型,MMDetection 对目标检测任务进行了优雅的抽象。这种抽象也形成了很大的影响力,不断被优秀的论文所引用,也被其他深度学习框架而借鉴。
详细来说 MMDetection 的模块化也能帮助我们快速认识新的目标检测模型,例如在 YOLOX 的开发过程中,我们将原 YOLOX 设计重构成 MMDetection 的形式,能更快吸收原 YOLOX 设计的精妙点,能快速抓住 YOLOX 的本质提升之处,也方便我们接下来做消融实验。
最后要提到 MMDetection 的工程化也做得非常好,文档和单元测试都非常齐全。虽然是协同开发,因为模块化和完整的单元测试,我们整个小组也能在比较快的时间里面完成这个任务!
MMDetection yyds!
个人知乎账号
https://www.zhihu.com/people/zhiqwang
@HsLOL
MMDetection 作为当下最成熟、最流行的目标检测框架,已经被广大开发者所使用,而我也感到非常荣幸能够与眸哥和诸多大佬共同参与到此次 YOLOX 的复现工作中,为 MMDetection 这一优秀的目标检测框架贡献自己的一份力量。
虽然我接触 MMDetection 的时间并不是很长,但是 MMDetection 良好的社区氛围和对小白非常友好的新手教程,使我在阅读源码理解算法流程的同时,也想进一步的学习 MMDetection 的构建流程。
我在此次复现工作中主要负责学习率调整模块的复现,最初的计划是直接调用 MMCV 库中有关学习率余弦衰减的代码,但是阅读 YOLOX 源码发现,YOLOX 在数据增强达到一定轮数之后就固定住了学习率,而且 MMCV 库中的实现方式及 Warm Up 函数与 YOLOX 相比均有所不同,所以需要按照 YOLOX 的思路继承 MMCV 库中的相关类后,在对其中的相关代码进行复写。
在这里非常感谢眸哥在项目开发过程中对我的帮助,如果没有眸哥的耐心解答和帮助,我很可能坚持不到最后。在经过此次复现工作后,我对 MMDetection 框架和构建流程有了更深的理解,我也非常希望今后还可以参与到 MMDetection 的复现工作中。
最后祝 MMDetection 越来越好!
个人知乎账号
https://www.zhihu.com/people/fhs-37