在今年3月份结束的AI Studio无人车车道线检测挑战赛中,参赛选手王林华取得了总决赛第二名的好成绩。赛后选手积极投稿,分享了从备赛到参赛过程中的宝贵经验,获得了额外1000元京东卡的稿费奖励。
以下是王林华选手的参赛心得,希望对你后续参赛有帮助,更多问题加入AI Studio常规赛QQ讨论群(797772627)在线讨论。
为期四个月的百度无人车车道线检测挑战赛在3月20号落下帷幕,我的决赛排名为第二。在参加比赛前,我刚接触到项目中的图像分割任务,因此了解到这个赛事后,迅速报名参加,也同时加入官方qq群,在开赛之前大概熟悉了下比赛任务、流程、平台及一些要求。这里需要提醒各位小伙伴们,一定要及时加入官方qq群,所有的问题都会在群里面及时解答,官方方面出现的纰漏、对于任务更详细的阐述、群里各位大牛的一些指点和讨论等都会让参赛者省去不少麻烦,得到一些珍贵启发,也能更好融入比赛氛围。
比赛开始阶段,详细阅读了题目要求,要求分割出所有的车道线、导向线、停止线、斑马线等交通路面标志,不区分实例,因此确定了语义分割技术方案。为了偷懒,省去自己通过飞桨(PaddlePaddle)实现模型的麻烦和困难。首先去github上关键字搜索了一番,发现官方原来早上传有两个baseline,icnet和deeplabv3 ,于是赶紧拉下来复现。icnet主要特点是比较快,但精度比deeplabv3 稍微要低些。考虑到比赛中对速度没有作出要求,因此确定采用deeplabv3 作为比赛的baseline。这两个baseline后来有人在官方qq群里有贴出来,所以对于没找到baseline的同学是个很大的福利。
训练平台的选择上,百度有自己的AI Studio一站式开发平台。集合了AI教程、代码环境、算法算力和数据集,上面集成好了飞桨(PaddlePaddle)深度学习框架,一般不需要重新配置环境和依赖包。使用百度AI Studio的优势比较明显,数据可以直接load公开数据集,省去好几个G的下载时间;支持python交互式编程,环境秒级启动;环境基本也不需要配置,同时方便随时登入操作。不过可惜的是,当时gpu还没有完全部署到位,所以还是使用自己的GTX1080设备。整个比赛过程中,百度方面一直在积极吸收参赛者关于平台和框架上的使用感受和建议,已经完成了不少重要优化和改版。目前的训练平台已经配置了v100 gpu显卡,体验相比之前有了很大提升。
我对比赛流程做了简单的切分,分为数据准备、数据清洗、模型训练和优化、模型预测四个方面。具体我将会在以下作下阐述。
数据准备方面,准确生成数据标签非常重要,标签生成错误将对后面的训练和预测带来不少困难,同时排查耗时费力,因此最好一开始就小心翼翼,仔细反复核对。赛题给的标签映射规则显得比较混乱,容易产生一些疏漏。因此我根据这些映射规则和需要忽视的像素值,重新梳理出一张映射表,可以清晰反映各类别像素值和训练标签对应关系。根据该表再去编写处理脚本,读取所有标签灰度图将灰度值根据映射表转换为0~8。灰度图标签转换很耗时,可以启用多个线程或进程同时处理,同时要避免非常耗时的粗暴的逐像素遍历方式,使用python可用numpy矩阵进行快速转换。重新整理的映射表如下:
数据准备方面还包括了样本均衡,通过编写脚本统计各类别在数据中的三个指标:有效占有样本数量、有效类别像素点总数、有效类别像素点平均数。首先定义有效类别像素块,类别像素块指的是某类别像素点8邻域连通构成的区域,有效类别像素块要求类别像素块需要大于设定阈值。有效类别像素块可以避免噪声像素点造成的误统计。
其中有效占有样本指的是某样本含有某类别的有效类别像素块。有效类别像素点总数是指统计某类别的所有有效占有样本的全部有效类别像素块像素点总数。有效类别像素点平均数由有效类别像素点总数除以有效占有样本数量得到。对9个类别统计发现,有效占有样本数量指标:第1、2、7类别最高,第3、6类别次之,第5、8类别最少;有效类别像素点总数指标:第1、2、7、6最高为近同一数量级、第3、5、8类别次之;有效类别类别像素点平均数指标:第6、1、2、7最高为近同一数量级、第3、8、5类次之。对数据均衡同时兼顾均衡有效占有样本数量及有效类别像素点总数,优先均衡有效占有样本,以此基础尽可能均衡有效类别像素点总数。
数据清洗方面,需要将数据标签可视化出来观察。根据以上标签映射表,每个标签都对应一个伪彩色。将标签按映射表生成伪彩图,然后与真实图像加权叠加,可以直接观察判断标签是否有误。但对总量达到约67000条的数据都采用人工观察的方式剔除异常数据,工作量还是太大了,因此需要配合一定的策略来减少人工审核工作量。
出于效率的考虑,数据清洗在准备工作、模型训练过程和结束都可以进行。模型训练loss的突然抖动、预测图像iou偏小都一定程度上说明了数据存在问题或训练效果不佳。对这些数据进行人工审核,可以大大缩小审核范围。反复进行这个过程,完成标签错误、缺少标签、图像过曝等问题数据的删除。当然还有其他更多巧妙的策略欢迎看文的小伙伴们补充。
完成数据转换及初步的数据清洗后就已经可以开始使用搭建好的训练环境进行训练啦。图像大小为1710*3384,利用deeplabv3 的baseline训练只能设置batch size为1,训练效率低下,过小的batch size也会导致准确率较低。因此有必要先思考下怎么解决图像过大、batch size太小的问题。
首先观察图像数据,容易发现,图像的上方1/3区域是车载摄像头拍摄的建筑、天空等非路面信息,没有任何正样本存在,也就是说该区域的所有像素点都属于背景类别。所以这部分区域可以不必训练和预测,我们将这块区域给裁掉可以节约训练成本,设置裁剪高度为570像素可以保证没有路面信息被误裁,裁后图像尺寸为1140*3384。
其次容易想到的一个点,是将图像比例缩小再进行训练和预测,之后反比例还原,可以得到最终的预测结果。比例缩小方式通过牺牲一定的图像空间细节,可减少大量的计算,节省的显存可以设置更大的batch size,因此模型收敛速度相对很快,准确率可以达到更高。这种方式要注意把握平衡点,过大的比例会造成过多的细节丢失,同时预测还原的时候容易出现明显锯齿边缘影响精度。在前期为了得到快速收敛,可以先用大比例得到预训练模型,再设小比例,在预训练模型上进行finetune。这个finetune的过程可以反复设小比例继续,直到达到表现最佳状态。以上方法一般针对模型的整图输入策略,指将整张图输入网络直接训练;也可用于滑窗策略,在降低图像分辨率的同时,同比例减小滑窗尺寸大小。
baseline的滑窗策略通过设置crop size,对输入整图随机裁剪,将裁减出来的部分图像送入网络训练。滑窗策略将完整的场景碎片化,聚焦于多个基本构成元素,在复杂场景下表现突出。baseline的crop size设置为769*769,我们通过设置多个不同的尺寸可以得到不同尺度的信息处理能力,同时crop size设小可以设置更大的batch size。在GTX1080的8G显卡上crop size和batch size对应关系如下:
以上都是模型训练过程中解决图像过大,batch size过小的策略。其中不同crop size的设置可以引入多尺度信息处理,我们可以考虑将这些多尺度信息进行融合,这就涉及到模型融合了。
除了多尺度信息融合,我们还可以考虑加入不同数据侧重、不同迭代、不同模型的多维度信息,以达到加强模型融合效果的目的。比如在不同数据侧重维度上,我们训练模型A侧重数据集a、模型B侧重数据集b、模型C偏向于学习实线、虚线等信息,模型D偏向于学习车位线、黄网格等难例。通过加权综合各模型优势。
模型加权融合上主要采用两种融合方式,一种是对每个模型的softmax层融合,一种是对输出结果的加权投票。
前一种方式中,每个模型softmax层输出预测图像尺寸为(N, C,H, W)的四维得分矩阵。N为预测图像的数量,此处为1;C代表像素点分类数量,此处为9个类别。H和W分别表示图像的宽和高。对多模型的四维得分矩阵逐点加权,得到最终的加权的(N, C,H, W)的四维得分矩阵,再通过argmax输出每个像素得分最高所属的类别。
后一种方式中,对多模型的输出label进行加权投票,规定背景类别占据总票数的0.85判为背景类。9个类别分别设置不同的投票权重,如容易分割的实线权重设为1,不易分割的车位线权重设为10,分割不易出错的类别如斑马线权重也可以设大些。
回到单个模型的优化上,主要从loss和学习率上考虑。考虑了使用不同的loss驱动训练,首先采用交叉熵先实现收敛,后采用focal loss、dice loss继续训练,指标可提升1~3个点左右。学习率先后采用了step、inv和比较流行cycle策略,相对而言,cycle策略通过合理设置,可以实现1~2个点指标提升。
模型预测上,主要就是利用多模型融合预测结果输出,这个过程中由于模型数量比较多所以会比较缓慢,因此考虑通过多显卡多进程进行加速。将数据、模型切份分配到多张显卡和进程可以带来成倍的速度提升。通过设置CUDA_VISIBLE_DEVICES可以指定显卡,通过shell脚本多进程分配资源。如采用softmax层融合方案,我们将测试集的1000条图像均分成n份,启用n个进程分别分配到n张显卡中实现加速。而采用多模型投票法时,我们先对m个模型均分成n份,启用n个进程分配到n张显卡,每一份跑完所有的1000条图像,之后对生成的m组label加权投票输出投票结果。
以上就是本次比赛的流程和一些策略,希望能给到参加这类比赛的各位同学一些正面的参考和借鉴,也欢迎随时补充新内容。