前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kaggle新手银牌:Airbus Ship Detection 卫星图像分割检测

Kaggle新手银牌:Airbus Ship Detection 卫星图像分割检测

作者头像
CV君
发布2019-12-27 16:36:21
1.1K0
发布2019-12-27 16:36:21
举报
文章被收录于专栏:我爱计算机视觉

关键词20天、第一次打Kaggle的新手、银牌、全球第21名

本文为原作者投稿,原载于知乎,感谢对“我爱计算机视觉”的支持。也欢迎其他愿意进行技术分享、扩大个人影响力的朋友投稿,谢谢!

0、前言

10月下旬到11月中旬大概二十天的时间,我除了写大论文开题报告外,一直都忙于Kaggle的一个遥感图像分割检测比赛 Airbus Ship Detection Challenge ,airbus也就是美国空中客车公司,悬赏金额6万美金。

比赛已经结束了,Rank 21/884,TOP2.4%,银牌,这是我第一次打kaggle图像类的比赛,二十天时间取得的成绩不算特别好,但我还是比较满意的,因为这个过程中学到了不少东西。趁这个机会做一下竞赛过程的梳理和分享,给大家提供一个竞赛的baseline,帮助新人快速上手,权当为自己攒人品。

这个比赛有几个问题,需要和大家说明一下:

(1)比赛期间发生了严重的数据泄露,LB上出现大量满分成绩,主办方不得不重新制作数据集,并重置了原有成绩。因此,所有人需要根据新的数据集重新训练重新测试重新提交结果,这件事情严重打击了大家的参赛热情,最终参赛人数仅有800+,隔壁另一个图像类的比赛还有两个月结束却已经有了900+的参赛人数,差距显著。

(2)比赛的public leadboard 和 private leadboard存在显著差异,说明测试数据集的分配存在很大的问题,这在discussion区已经有人提出了,说本地交叉验证集的结果比较靠谱;

相信kaggle官方会不断完善,解决这次比赛暴露出来的问题。但是对于参赛者,名次不是最重要的,学到东西最重要,kernel和discussion区分享的资料让人获益匪浅。相比于国内的大数据竞赛平台,Kaggle不仅是竞赛平台,也是学习和分享的平台,这一点差距还是挺大的。

1、比赛介绍

(0)背景介绍

航运流量增长迅速。更多的船只增加了海上违规行为的机会,这迫使许多组织对公海进行更密切的监视。在过去的10年里,人们做了大量的工作,从卫星图像中自动提取目标,取得了显著的效果,但在实际操作中存在许多不足。现在空中客车公司与kaggle共同举办比赛,寻求更好更快的船舶自动检测方案。

(1)比赛任务:从卫星图片中找到所有的船只

比赛的名字是船只检测,但实际上要做的不是目标检测,可能更接近实例分割,参赛者需要用mask掩码来表示检测到的目标,大概就是下面这种形式:

(2)数据的描述:

在本次竞赛中,需要在图像中定位船只,许多图像不包含船只,而也有部分图片包含多个船只;这个比赛的数据集非常大,光训练集就有28G,且由于Kaggle服务器在国外,所以数据集的下载很困难,我建议用迅雷或者kaggle api,也有人建议kaggle cli;

(3)评价标准:

这个比赛的评分依据主要是不同IOU阈值下的F2-Score。对于一张图片中的某个目标,如果预测值和真实值的IOU超过预设阈值,则认为该目标识别成功。换言之,取阈值为0.5时,如果预测对象与真实值对象的交集大于0.5,则视为识别成功。该赛题的识别阈值有10个:(0.5,0.55,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95)。单个图像的得分是每个IOU阈值上的F2得分值的平均值,最后,竞赛的最终分数是对测试数据集中每个图像的单个平均F2分数取出的平均值得。

2、敲定主体框架(Mask R-CNN in Detectron by Caffe2)

第一直觉这是个实例分割任务,首选Mask R-CNN。

当时期间Mask R-CNN有两大开源版本,一个是Matter Port的Keras版代码,另一个是Facebook官方的Caffe2版代码(即Detectron)。

据说Detectron的性能优于Matter Port 10个百分点,因此我直接选择了性能更好的Detectron。其实11月初官方又开源了Pytorch版本Mask R-CNN,如果这个早一点开源的话,首选的必定是Pytorch版,因为这样子代码能好改很多,这个就暂且不表了。

3、数据扩增

遥感图像有一个很大的特点,就是多方向性。传统数据集里面,人可以说都是站着的,应该没有人倒着的情况吧。夸张点说,说不定CNN就觉得,躯干上顶个圆球脑袋的东西就是人,万一哪天检测一个倒立的人说不定就识别不出来了。

遥感数据集的这个问题就严重,遥数据集多是俯拍,船只的朝向东南西北都有可能的,因此训练集里的朝向应当要丰富,避免学习到的模型不具有泛性。

针对这个问题有很多解决方案,上面这张图是某篇论文的方法,主要改进是在模型里面增加了一个旋转不变层,以解决遥感图像多方向性问题。我说两个比较容易实现的方法:

(1)数据扩增:

我采取了下面几种数据增强方法:随机90°倍数旋转(P=1),水平翻转(p=0.25),随机亮度(p=0.2,limit=0.2),随机对比(p=0.1,limit=0.2)等等。

(2)TTA单图多测:

TTA阶段将待测图片翻转、旋转获取多个待测图片,然后同一个模型对这几张图片分别检测,投票产生最终检测结果,提高系统鲁棒性。

4、制作数据集

竞赛数据集是RLE格式的,具体可见这里 RLE 。

数据集的制作其实非常麻烦,我制作的是标准COCO数据集,具体参见:

pascal1129/kaggle_airbus_ship_detectiongithub.com

代码语言:javascript
复制
        {
           "id": 27614,
           "image_id": 14332,
           "category_id": 1,
           "iscrowd": 0,
           "area": 3307,
           "bbox": [
               168.0,
               65.0,
               170.0,
               24.0
           ],
           "segmentation": [
               [
                   189.0,
                   88.5,
                   168.0,
                   88.5,
                   167.5,
                   70.0,
                   336.5,
                   65.0,
                   337.0,
                   84.5,
                   189.0,
                   88.5
               ]
           ],
           "width": 768,
           "height": 768
       },pascal1129/kaggle_airbus_ship_detection        {
           "id": 27614,
           "image_id": 14332,
           "category_id": 1,
           "iscrowd": 0,
           "area": 3307,
           "bbox": [
               168.0,
               65.0,
               170.0,
               24.0
           ],
           "segmentation": [
               [
                   189.0,
                   88.5,
                   168.0,
                   88.5,
                   167.5,
                   70.0,
                   336.5,
                   65.0,
                   337.0,
                   84.5,
                   189.0,
                   88.5
               ]
           ],
           "width": 768,
           "height": 768
       },

很多图片的标注效果很差,在数据集制作过程中已经跳过这些图片了。

比赛中,训练集共192556张图片,其中无船空图150000张(77.9%),含船图42556张(22.1%),可以看出来负样本很多。

我在制作数据集的时候暂时弃掉了无图样本,是为了提升训练速度,但是最后几个epoch要把所有的样本放进来训练,以防止假阳性过于严重。

5、模型训练

Detectron训练Mask R-CNN比较麻烦,环境我用的是官方docker容器,数据集信息需要添加进入 dataset_catalog.py,然后通过train_net.py训练模型,训练还是比较快的,印象中一天不到就有结果了。

训练方法的话,可以参见这里:

Pascal:用Mask R-CNN训练自己的COCO数据集(Detectron)zhuanlan.zhihu.com

6、重叠处理

训练完模型,infer得到结果提交给kaggle发现报错,应该是部分instance重叠了,这里肯定是需要处理的,简单地说就是重叠区域怎么划分,分配给哪个instance?是按面积还是信度、距离来?这里处理方法因人而异。

我的方法是这样子的,首先通过置信度降序排列候选目标,然后通过一个先【异或】后【与】的运算来解决重叠冲突,也就是(mask^bg)&mask,具体的原因大家可以自行体会一下,我就不多做解释了。

代码语言:javascript
复制
class Airbus_Submit(object):    
   def mask_to_rle_csv(self, img, masks,confidence):
       index = np.argsort(-confidence)                 # index sorted by confidence: high-->low
       bg = np.zeros((768,768), dtype=np.uint8)            # must let dtype=uint8.Otherwise xor will be wrong
       for i in index:
           mask = masks[:,:,i]
           if(mask is None or confidence[i]< self.thresh ):     # Sometimes mask maybe None, but can't use 'mask==None', if confidence[i]<0.5 it's impossible to use
               continue
           mask_xor = (mask^bg)&mask
           area = mask_xor.sum()                       # area of the mask
           if(area == 0):
               continue
           print(confidence[i])
           rle = self.rle_encode(mask_xor)
           bg += mask_xor

步骤5和6写得少但工程量不小

7、Unet模型融合:解决假阳性问题

这个赛题看似是实例分割,但实际上是unet模型大行其道,排名前几的大多是unet相关的,其实主要是数据集有两个特点:

(1)图内只有一个类别的物体,不存在多类别;

(2)船只粘连不严重,重叠极少;

语义分割也就能派上用场了,一个老哥用unet-resnet34单GPU训练30epoch就12名了,让人唏嘘。

我的模型也参考了unet的结果,在detectron模型基础上融合unet结果,这一步涨分0.5个百分点。

8、TTA多模型融合

有点类似于集成学习吧,单图多scale检测投票,scale: 0.6, 0.8, 1.0, 1.2, 1.4, rotate: 90, 180, 270,都是可以尝试的,然后多模型投票取得好的结果

9、心得

(1)选择SOTA模型。kaggle比赛赛制大致上前10名金牌,前5%银牌,前10%铜牌,如果你选择一个好的baseline model,正确运行完,拿个15%是问题不大的,稍作修改拿个铜牌也不难,但是再往上提升就很难了。最艰难的时候,得分变高了,可是排名不断往下掉,心理压力挺大的;

(2)善用模型融合。这个比赛大多都是unet+maskrcnn模型融合,模型融合的策略因人而异,模型与模型之间优势互补是提分利器;

(3)善用数据扩增、TTA测试融合。

(4)相信自己本地的CV验证集。每天在kaggle的提交次数是有限的,因此要设置好离线验证集,不断探索好的参数,不要过分相信kaggle的线上得分。(备注:kaggle的线上得分和最终得分是基于不同数据集得出的,以防止部分参赛者凑结果)。数据集分配示例如下:

代码语言:javascript
复制
from sklearn.model_selection import train_test_split#5% of data in the validation set is sufficient for model evaluationtr_n, val_n = train_test_split(train_names, test_size=0.05, random_state=42)

10、总结

虽然成绩不算特别好,但是这个过程中我还是学到了不少的东西。比赛期间恰逢我毕设开题,且这个比赛的测试数据出现了严重的数据泄露,导致分数重置等各种问题,因此参赛过程很疲惫。不管怎样能学到知识最重要。Pytorch版本的Maskrcnn已经开源了,后面准备好好研读,基于Pytorch对模型做更多改进。等kaggle大佬们开源方案了,我再继续补完分析。

11、代码开源

目前,我的代码已经在Github开源了,一个效果不错的baseline,进入TOP10%是绝对没有问题的

pascal1129/kaggle_airbus_ship_detectiongithub.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我爱计算机视觉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0、前言
  • 1、比赛介绍
  • 2、敲定主体框架(Mask R-CNN in Detectron by Caffe2)
  • 3、数据扩增
  • 4、制作数据集
  • 5、模型训练
  • 6、重叠处理
  • 7、Unet模型融合:解决假阳性问题
  • 8、TTA多模型融合
  • 9、心得
  • 10、总结
  • 11、代码开源
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于生成式AI,自动驾驶,深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档