百度AI Studio “无人车车道线检测挑战赛”已于3月20日落幕。自2018年11月报名开始,共有700多支队伍报名参赛,经过初赛的激烈角逐,50支队伍晋级复赛阶段,瓜分9.9万元奖金。
本次比赛要求参赛者基于给定的交通场景图像和车道线标注的训练数据集,使用百度PaddlePaddle深度学习平台训练模型,来预测测试图像中每个像素所属的车道线类别。带车道线属性的高精地图,是无人驾驶的重要一环,目前高精地图车道线的分类主要靠人工标注,成本高、效率低。本次比赛的赛题即是为解决这一问题而推出,邀请全社会人才利用深度学习技术和PaddlePaddle,探索高效精准的车道线检测方案。
比赛地址:
https://aistudio.baidu.com/aistudio/#/competition/detail/5
车道线检测示例:上图为实景图像,下图为使用特定颜色标注不同类型车道线的结果
复赛排行榜
经过复赛阶段近两个月的角逐,Seigato选手以0.63547的成绩夺冠,并于比赛结束后,在Github开源了自己的解决方案及代码:
https://github.com/gujingxiao/Lane-Segmentation-Solution-For-BaiduAI-Autonomous-Driving-Competition
以下是冠军选手的解决方案:
本次比赛训练使用框架为PaddlePaddle。在为期四个月的比赛中,初步了解了PaddlePaddle,并且能够学以致用,收获颇多。最终以0.63547分数取得第一名,ID为Seigato。
总体描述
本次比赛图像分辨率非常的大,3384x1710,我的设备是两块1070Ti,可用显存15.6G,无奈只好忍痛缩小图像。下面说下主要思路:
【1】经过对label的分析,首先裁掉了图片最上部的3384x690的图像,因为这部分都是天空和树木,没有正样本的存在,裁掉后还可以减小图像的压缩比例,一举两得。
【2】裁掉后,为了尽可能保持图像比例,在比赛不同阶段采用了3种分辨率(768x256,1024x384,1536x512)进行训练,并且大分辨率的模型是基于前一个小分辨率的预训练模型而来(这样做的原因是大分辨率由于感受野的问题,很难训练,所以先从小分辨率入手,不仅可以快速验证模型的有效性,还能够提供较好的特征与分布;事实证明,基于小分辨率的预训练,确实可以帮助大分辨率更好地进行收敛)。
【3】本次比赛精简了paddle提供的deeplabv3p的模型,并且根据以往在kaggle的比赛经验,重新设计了两个基于resnet残差模块的unet网络,最终成绩了采用了三个网络的平均结果。
【4】在训练策略上,采用了修改版的CycleLR策略(原本写了个全自动的,但是由于训练偶尔出现loss为NaN的情况,耽误了很多时间,所以只好改为手动了)。采用Adam,前3个epochs采用默认参数训练(lr=0.001),在之后3个epochs的训练中,每个epoch平均分配出6个改变lr的地方,改变方式为:0.001-0.0006-0.0003-0.0001-0.0004-0.0008-0.001。最后两个epoch一般采用0.0004-0.0001之间学习率训练的策略。由于测试集与训练集在图像质量和视觉感知上差距不小,太小的学习率很容易导致过拟合,所以最小的学习率采用0.0001。在8-10个epochs后,训练基本上就结束了。
【5】在loss function的使用上,最先的三个epochs采用sigmoid bce,后面的训练中采用bce + dice的方式,这种方式会比单一的bce提升0.01-0.015。
【6】数据清洗上,最一开始采用了全部数据训练,发现loss经常出现不规则的跳动,经过排查,发现road 3存在几乎一半以上图像过曝的问题,并且road 3大多在强光下拍摄,不符合测试集的分布,所以很果断的舍弃了road 3,分数也提升了0.01左右(好神奇。。。)。
【7】数据增强上,由于第五类和第八类训练数据较少(但是测试集中占比不少),所以针对这两类,采用了iaa的图像处理,从亮度、饱和度、噪点、对比度、crop、scale等方面做了共计12000张图片的增强。最后排查了一遍road 2和road 4,把一些错误和过曝的图片都删掉了,最终保留了56000张图片(包括数据增强的图片)进行训练。
【8】训练时采用上述分辨率,但是在实际提交结果时,添加一层bilinear,直接将结果缩放到3384x1020,实测结果会有0.005左右的提升
【9】最终的融合先使用每个模型将每个testimage的结果保存为1536x512x8的npy文件,然后加载test image的三个模型的npy文件进行求平均值,然后创建了一个bilinearNet将结果缩放成3384x1020,再将之前裁掉的3384x690的背景与结果拼接,得到最终的预测结果。
【10】【最终夺冠关键】当完成了1-9步骤后,得到的分数是0.61234分,位列第三,但是local CV的结果却不应该对应这个分数,于是我将label叠加到了原图上,发现了一个巨大的问题,由于我训练的分辨率为1536x512,原始图像为3384x1020,我首先使用了最邻近插值来缩放label,但是后来在生成结果时,却使用了bilinear,再加上本身分辨率并不是能够被原始分辨率整除,导致了我所有的prediction都向图像右侧偏移了4-5个像素。于是在results_correction.py中,我将label进行了位置修正,当使用4个像素修正时,得到了当前的0.63547分。(Note:如果使用原始图像训练、或者使用恰好被二整除关系的分辨率训练则不会出现这个问题,主要还是我设计的unet有点小问题,所以无法这样训练)
模型记录
依赖说明
Python 3.6
opencv-python 3.4.3.18
paddlepaddle-gpu 1.3.0.post97
imgaug 0.2.7
代码结构
点击阅读原文,可直接访问冠军开源代码页面。