|
| 1 | +# 2020-ZhanJiang-Underwater-Object-Detection-Algorithm-Contest |
| 2 | +2020湛江水下目标检测算法赛 |
| 3 | + |
| 4 | +## 前言 |
| 5 | +此次比赛分数不是很理想,A榜20.14,B榜19.63。我认为的原因应该有很多,比如说模型,水下图像增强算法,trick, |
| 6 | +又或者是评价指标比较苛刻(赛事采用的是COCO mAP[@0.5:0.05:0.95] 指标)等等,具体的原因会在之后的分部分详细解释。当然,这也是我第一次参加目标检测的比赛, |
| 7 | +所以过程中难免会有疏漏。而因为此次比赛,让我对keras非常失望, |
| 8 | +具体原因可见我的这一个blog:[Choice keras or pytorch?](https://fieldhunter.github.io/talking_about_keras_and_pytorch/)。虽然说分数不理想, |
| 9 | +但也是好歹做了出来,自己也有自己的idea在里面,只不过应该是中途哪里出了问题,我没发现罢了(但我真的看了源码很久觉得应该没问题), |
| 10 | +可能换了一些策略或者单换个PyTorch实现的模型之后分数就会大幅上涨,毕竟大佬提供的PyTorch的baseline能达到挺高的分数。但肯定的是自己的idea是挺有效的, |
| 11 | +**从裸模型+图像增强的10分提高到了20分**。(所以我就怀疑是yolo的问题)所以在此将它放入我的github中,对今后参加类似的比赛或者项目肯定有借鉴意义。 |
| 12 | +(租GPU就花了500块,真的吐血) |
| 13 | + |
| 14 | +## 说明 |
| 15 | +没有上传的文件夹有data、models和pre_train,即文件太大,不宜上传。原data目录当中,test目录下是测试集,包括图像增强后的图像,trian目录下是训练集, |
| 16 | +也包括图像增强后的图像。data目录中还有yolo模型所需的classes.txt、yolo_anchors.txt和train_data.txt。在pre_train目录当中,有yolo的预训练模型yolov3.weight, |
| 17 | +以及用convert.py转换的yolo_weights.h5。在models目录中,存储训练结束的模型和Tensorboard记录。 |
| 18 | + |
| 19 | +## 图像增强 |
| 20 | +首先,对图像采取增强算法增强(image_aug.py)后进行存储。对于水下图像识别这个领域,我也是参加这个比赛才接触的,同样是第一次参加目标检测的比赛, |
| 21 | +所以着重的去对模型算法做更改而不是针对数据,所以图像增强的算法只是照搬了赛事群里的一个大佬的开源,可视化出来后看着效果是挺不错的, |
| 22 | +但具体怎么样我也不敢下定论,所以可能水下图像增强算法的效果不是很好,导致分数不是很高。具体的算法在data_augmention目录里。为了满足后续的数据增强需求, |
| 23 | +**对训练数据进行原图尺寸增强**,但会使得处理速度很慢。为了解决这个问题,尝试采用gpu版的numpy:cupy来调用gpu加速处理, |
| 24 | +但增强算法中的有些numpy函数cupy尚未支持,所以只能用numpy,之后采用了10个进程的多进程方式来尽量的加速处理。**对于测试集,直接缩放至目标尺寸**来增强, |
| 25 | +这样处理速度就会非常快,避免大尺寸图片耗时的问题,之后再进行输入处理,以满足模型输入需求。具体的处理方式在[数据增强](#数据增强)部分介绍。 |
| 26 | + |
| 27 | +## 数据预处理 |
| 28 | +data_process.py中,对所有图像进行统计,对每一个候选框,进行细致的处理,代码中给出了详细的注释,这里不再阐述。 |
| 29 | +候选框处理时**删除那些面积小于120的过小候选框**。之后再靠kmeans.py来生成yolo所需的anchors,最后得到data目录中的train_data.txt和yolo_anchors.txt。 |
| 30 | + |
| 31 | +另外,赛事的目标种类只有4种,但数据集里有5种,多了一个水草。观察数据集后发现,水草和海胆在某些情况下十分相似,为了使模型增强对水草的区分能力, |
| 32 | +**在训练时用5个类别去训练,在预测的时候把水草类丢弃即可**。 |
| 33 | + |
| 34 | +## 数据增强 |
| 35 | +数据增强代码在yolo3目录的utils.py中。对于模型的输入尺寸,**采用480*480**,原yolo尺寸是416\*416。经过实验验证,**从416到448再到480,分数都是稳步提高的**。 |
| 36 | +由于时间和成本的关系,并没有尝试512\*512尺寸,这或许会进一步提高。针对目标检测的task,并不希望把任意尺寸的图片强行resize,策略是选出高与宽较长的一边, |
| 37 | +计算这条边缩放到480的比例,然后按照这个比例对原图进行**等比例缩放**。等比缩放后,长的一边是480,短的一边则不是。 |
| 38 | +之后在短边上**用灰色像素来填充**以满足480\*480尺寸。统计过数据集的尺寸,都是长大于高,所以短边都是高这条边。灰色像素数量在缩放后的原图上下两侧均分, |
| 39 | +这样使得处理后的图像**正中间是缩放后的训练图像,上下两侧是灰色像素**。[图像增强](#图像增强)部分的测试集处理也是如此。ps:此处尝试用base64来导入图片演示, |
| 40 | +但根本加载不出来,不知道为什么,只能这样靠着文字和代码来理解一下。 |
| 41 | + |
| 42 | +具体步骤:对于训练数据,首先按照7:3的可能性进行**直接缩放或者随机裁剪**。直接缩放过程中删除缩放后面积小于120的过小候选框, |
| 43 | +随机裁剪出来的尺寸也与按照原图直接缩放策略缩放后的尺寸相同。之后都是按照1:1的可能性**按顺序进行二次的轻度图像增强,水平翻转和垂直翻转**。对于测试集, |
| 44 | +直接进行缩放即可。之后按照上述所说的策略填充灰色像素。最后进行模型输入格式的处理,**像素归一化和候选框处理**。同样,代码中有详细的注释。 |
| 45 | + |
| 46 | +## 模型训练 |
| 47 | +在train.py中,输入尺寸为480*480,训练集和测试集按照9:1划分。训练过程分为两个阶段来训练,第一阶段**冻结预训练所有层**,采用RAdam(最小值设为1e-5), |
| 48 | +warm_up策略,batch_size设为32,训练100轮,同时做Tensorboard记录。在第二阶段**打开全部网络层来训练**,采用RAdam(最小值设为1e-6),warm_up策略, |
| 49 | +**swa算法,cosine-annealing学习率策略(范围1e-2到1e-6),batch_size设为8(主要原因是显存限制)**,训练200轮,同时做Tensorboard记录, |
| 50 | +通过ModelCheckpoint策略对每一轮按照val_loss来决定是否保存模型,最终选用val_loss最小的模型来做预测。即将最好的模型更名为trained_weights_final.h5。 |
| 51 | + |
| 52 | +在模型设计上(yolo3目录中的model.py),对class_loss进行修改,采用**label_smoothing策略**。由于在预测的可视化结果中看到候选框的及分类的结果都挺不错, |
| 53 | +但是一些很明显且已经识别出来的目标的置顶度却很低,一些显然不是目标的置信度相对的有点高,所以想对confidence_loss对更改, |
| 54 | +即给它整体或者正样本部分(confidence_loss分为正样本和负样本两部分)乘上一个值,让模型更注重置信度的损失,简单粗暴的想法。但结果并不是很好, |
| 55 | +在训练过程中模型的loss也相对于之前高了几十个点并且下不去,最终的分数也比之前下降了一些。加上COCO mAP[@0.5:0.05:0.95] 这个评价指标候选框越多越好, |
| 56 | +所以最终放弃了对confidence_loss的修改。 |
| 57 | + |
| 58 | +对于其他模型,比如Faster-RCNN,我也有考虑去用过。并且听赛事群里说比赛基本没人用单阶段模型,想想也是,二阶段模型肯定准确率会高一些。但是......算了, |
| 59 | +不想吐槽keras了,至于为什么没有用除了yolo以外的模型,还是看看[前言](#前言)里我提到的我写的blog吧。 |
| 60 | + |
| 61 | +## 预测 |
| 62 | +在predict.py中,对预测出来的候选框进行**WBF**,相对于之前使用的NMS,WBF策略**提升了不少分数**。之后就是一系列的后处理操作,代码中的注释很详细, |
| 63 | +这里不再阐述。另外,**赛事数据集的候选框坐标起点是1,在训练前已经更改为0,所以在后处理中需要再次更改为1**。 |
| 64 | + |
| 65 | +在参数上,**score阈值设为0.001,iou阈值(包括模型阈值和WBF阈值)设为0.25**能得到最高的分数。 |
| 66 | + |
| 67 | +## ps |
| 68 | +**数据预处理和数据可视化**都有Jupyter版本。分别进行了**训练集的统计信息**工作和**各阶段数据(训练集,数据增强,预测结果)可视化**工作。同样也有详细的注释。 |
| 69 | + |
| 70 | +最终训练出来最好的模型和Tensorboard记录我会存放在releases当中。 |
| 71 | + |
| 72 | +yolov3部分的代码是基于[qqwweee/keras-yolo3](https://github.com/qqwweee/keras-yolo3)进行更改的。 |
0 commit comments