## 2020中国华录杯·数据湖算法大赛—定向算法赛(吸烟打电话检测)第二名开源
* 作者:fire15
* 联系邮箱:fire15@126.com
* 队伍名称:一个人要像一支队伍
* 成绩:
* 初赛A榜:99.84 / 第二名 (两周周冠军)
* 初赛B榜:84.09 / 第七名
* 复赛A榜:99.15 / 第五名
* 复赛B榜:93.13 / 第二名
* 决赛答辩:第二名
* 比赛地址:https://dev.ehualu.com/dev/home/competition/competitionDetail?competitionId=3
### 一、算法简介
数据处理时,观察很多手机拍摄高清图片分辨率很大,因为我机器不大好,IO比较耗时,为了加速训练,先预先等比缩放保存好;
然后合并初赛的数据,进行一个清洗、去重;
最后通过定制化的CutMix进行数据预增强,先生成好部分图片。
主要训练方式基础模型是EfficientNet-B4,使用了对抗学习的预训练模型,使用了Ranger优化器,使用了SGDR的学习率衰减策略,然后通过监测验证集的mAP分数来选择最好的模型,使用early stop停止训练。在训练时还加入了梯度截断等策略。
最后使用了模型自蒸馏的训练方案。具体训练过程是,第一步先把训练集随机划分为5折,分别训练5个模型,然后生成对应的训练集预测标签;第二步重新训练5折模型,此时训练集所使用的标签为原始标签和蒸馏标签的加权和,分别训练5个模型。最后尝试不同的模型组合,选择A榜最高的作为最终提交方案。
### 二、数据处理
使用了初赛发布的两批数据混合在一起,没有使用外部数据。
训练数据处理过程:
1. 先按最大边等比缩放到600尺寸;(参考脚本data/resize.py)
2. 使用DuplicateCleaner扫描重复图片,删除;
3. 人工大致清洗一遍,修正标注错误的;
4. 使用自定义的CutMix生成部分增强数据;(参考脚本data/addData.py)
5. 统一重命名,命名方式:aug_开头的代表cutmix预生成的,其余图片v1开头的代表初赛第一批数据,v2开头的代表初赛第二批数据,v3开头的代表复赛数据,后面的数字对应原始的图片名,可以查看验证;
复赛A榜测试数据处理:
在群里官方人员回答允许的情况下,对复赛A榜测试数据中方向偏左90度或者偏右90度的手动转正,其余未作任何修改。
在此之外,训练时代码里数据增强使用了等比填充、随机旋转、水平翻转、对比度饱和度变化、噪声和模糊等,具体实现和参数见代码。
### 三、算法结构
#### 3.1 网络结构
模型选择了EfficientNet-B4,考虑到图片有很多比较模糊的,选择了使用对抗学习的预训练模型。然后修改了输出神经元的数量。其他未作修改,尝试了增加全连接层、Dropout层、剪枝、SE模块、CBAM模块,均未有明显提升。
使用的模型项目来自于[EfficientNet-PyTorch](https://github.com/lukemelas/EfficientNet-PyTorch),[预训练模型下载地址](https://github.com/lukemelas/EfficientNet-PyTorch/releases/download/1.0/adv-efficientnet-b4-44fb3a87.pth)
#### 3.2 loss部分
使用了交叉熵损失,在蒸馏部分直接修改了训练标签,未修改loss。尝试过Focal loss,但是没有明显提升,可能跟数据类型有关,因为咱们不同类别相关性很大。
#### 3.3 优化器
初赛使用的Adam,复赛最终用的是比较新的Ranger。
### 四、算法运行说明
#### 4.1 训练说明
第一步,先训练原始5折模型,先进入目录/HLB_partB_docker/code,然后确认config.py中的use_distill为0,最后运行train.py即可。训练完得到5个模型,位于save/下,移动到save/model1/下;
第二步,运行makeDistill.py脚本,通过第一步训练的五折模型,生成训练集的预测标签,输出文件为save/result_distill.py;
第三步,修改config.py中的use_distill为1,运行train.py,训练完得到5个模型,位于save/下,移动到save/model2/下;
第四步,尝试不同的模型融合方案(赛制只允许最多三个模型融合),复制三个模型到save/merge/下,然后运行predict.py,得到save/result_merge.json。目前尝试的最高分为复赛a榜99.15,组合方式为1个蒸馏前模型+2个蒸馏后模型。选择A榜得分最高的融合方案作为最终提交方案。
#### 4.2 测试说明
复现A榜成绩,直接进入/root/hualucup目录,直接运行python predict.py即可.
获取B榜结果,运行python predict.py /notebooks/test即可,输出为/notebooks/results/hualucup-13183875717.json。
### 五、算法性能
我的机器比较杂,可分为三个机器:
机器A: 一台2070super的windows机器;
机器B: 一个1060的ubuntu机器;
机器C: 租的2070的ubuntu机器。
训练时,第一轮五折模型,机器A训练两折(第1、3折),机器B训练一折(第4折),机器C训练两折(第2、5折);因为1060比较慢,训练完一折另外两个差不多训练完两折。第二轮蒸馏训练五折模型也一样在三个机器上训练。
为了保持代码的一致性,虽然2070有8G显存,但是1060只有6G显存,所以我设置的训练batchsize为3,刚好占用6G显存(如果有更好的机器,加大batchsize应该还有提分空间)。推理是在1060的机器上进行的,因为官方用P4复现,而1060性能低于P4,所以我只要保证1060不超时P4就不会超时。1060上的推理显存占用情况如下,在2G显存左右.
平均推理时间,对于复赛A榜1710张,在1060上单卡推理总计耗时285秒(包括加载模型的时间、读取数据的时间和模型推理时间)。平均耗时为285/1710 = 0.167s,小于200ms。
### END
由于奖金一直没发,开源计划也一直拖着,眨眼过了几个月了,方案细节倒是记得,只是部分代码可能有点混乱了,本项目的代码是从最后决赛提交的docker项目里拷出来的,可能存在遗漏,部分路径可能也不正确,请见谅,相关的代码已经尽可能都放进来了。
之前主要用的Keras+Tensorflow的组合,这次比赛学习、实践了Pytorch,还是挺香的,自己也根据本项目整理了一个图像分类框架:[Fire: Deep Learning for lazy humans](https://github.com/fire717/Fire),欢迎交流~
有什么其他算法相关的想法也欢迎交流讨论~