【飞桨开发者说】黎昆昌,CCF BDCI遥感影像地块分割赛道冠军团队、CCF BDCI 2020 综合特等奖团队队长,中国科学院深圳先进技术研究院20级硕士。
CCF大数据与计算智能大赛(CCF BCI)由中国计算机学会于2013年创办,作为全球大数据及人工智能领域最具影响力的大型赛事之一,本届大赛共吸引了全球3万多支队伍参赛,提交作品8万余件,参赛人数与竞赛成果质量再创新高。
本次比赛首度设立了全新的“自主平台”赛道,百度首发 “遥感影像地块分割” 赛题,飞桨作为该赛题的指定深度学习平台为选手提供技术支持。值得一提的是,本次分享的冠军团队在最终决赛中突破重围,一举拿下了含金量极高的CCF BDCI综合特等奖。
背景
遥感影像地块分割, 旨在对遥感影像进行像素级内容解析,对遥感影像中感兴趣的类别进行提取和分类,在城乡规划、防汛救灾等领域具有很高的实用价值。然而,现有的遥感影像地块分割数据处理方法,局限于特定的场景和特定的数据来源,且精度无法满足需求。因此,在实际应用中,遥感影像地块分割仍然依赖于人工处理,需要消耗大量的人力、物力、财力。本次大赛旨在利用人工智能技术,对多来源、多场景的异构遥感影像数据进行充分挖掘,打造高效、实用的算法,提高遥感影像的分析提取能力。
任务
对于预训练模型,大赛只允许使用飞桨官方开源的预训练模型,或者是通过监督、自监督、无监督方法,对比赛训练集(不允许用比赛测试集)、公开数据集(已发表论文、arXiv除外)训练得到的模型作为预训练模型。
本次评测旨在衡量遥感影像地块分割模型在多个类别上的效果,具体包括建筑、耕地、林地、水体、道路、草地和其他等7个类别。初赛阶段主要考察7个类别的预测mIOU,复赛在初赛的基础上,增加了对水体和道路类连通性的度量。
复赛指标
方案介绍
我们首先进行数据分析,在挖掘赛题关键问题之后提出了整体思路,之后对核心的数据处理、模型训练、模型预测、连通性后处理进行介绍。
方案的代码位于https://github.com/Andy1621/seg-for-fun,核心代码在data/code目录下,基于PaddleSeg静态图版本开发,方案仅供参考。建议使用功能更加丰富灵活的PaddleSeg 2.0动态图版本https://github.com/PaddlePaddle/PaddleSeg,下面结合部分代码进行方案介绍。
数据分析
统计数据集中的各类面积占比如图3饼状图所示,从中,我们可以发现数据集中存在类别不均衡现象,建筑、道路和草地类占比较少,而其他类占比较多。当我们完成进一步的统计工作,可以得知只有分别约7%、10%、13%的图片分别满足建筑、道路、草地面积占比大于1%。数据存在极度类别不均衡现象,常规的方法并不适于训练。
分析飞桨官方提供的baseline,我们可以发现,尽管建筑类数据较少,但由于其地貌容易辨识,分类结果还是比较准确的;而道路和草地类,则因为与其他类存在相似性,且训练数据不足,因此结果较差。所以,提升模型分类能力(mIOU)的关键是解决类别不均衡问题,尤其是道路类和草地类。
baseline: https://aistudio.baidu.com/aistudio/projectdetail/1090790
整体思路
要解决这些问题,直接的方式是使用针对IOU设计的损失函数进行re-weighting(如Lovasz-Softmax loss、Focal loss等),但训练较慢,结果收敛不稳定。其次,我们可以针对特殊类设计模块,但结构复杂且周期长。最终,我们借鉴了Adaboost的思想,用不同概率分布的训练数据训练一系列弱分类器,并通过投票融合得到强分类器。需要注意的是,此处数据并不是每轮增加错误样本权重,弱分类器的“弱”也是指特殊类别上弱,融合权重根据准确率与连通性需求人为规定。
PaddleSeg官方实现了较常用的几种loss:Weighted softmax loss、Dice loss 、BCE loss、Lovasz hinge loss、Lovasz-Softmax loss。训练时加入Dice loss,可略有提升。
数据处理
为了获取不同的训练数据,我们设计了不同的数据处理方案:
(1)划分道路类和草地类正负样本(负样本指不包含该类的样本),多阶段逐步增加负样本比例,可以借鉴Bengio的课程学习(Curriculum Learning)思想,由简单到复杂训练,结果更好收敛;
(2)在原数据的基础上,对道路类和草地类样本re-sampling,为了避免过拟合,对重采样数据进行多种数据增强(水平翻转、垂直翻转、随机90度倍数旋转等),与re-weighting相比,简单、直接、效果好;
(3) 对建筑类、道路类、水体类样本进行转换处理,得到二分类训练数据(同样进行数据增强并加入随机旋转90、180、270度),训练特殊的二分类器,加强模型对特殊类别的前景和后景区分能力。在数据增强时,我们还进行了阈值筛选,仅对面积占比较大的图像进行相应处理,直觉上认为这些数据对训练更友好。
本文讲述用于产生数据集的代码位置在:data/code/pdseg/tools/generate_my_dataset.py,数据增强借助Albumentations库实现。一组数据增强如下所示:
-
v_flip_aug = Compose([
-
VerticalFlip(
p=1.
0),
-
RandomRotate90(
p=0.
3)
-
])
值得注意的是,通过上图中预测效果对比,我们发现多分类模型只能识别笔直的道路,部分弯曲的道路难以识别,而二分类模型可以很好地识别弯曲的道路,并且连通性也更好,这也是我们复赛的主要思路(很长一段时间内我们都比第二名高3-5个点)。
模型训练
有了这些数据,我们训练了一系列以HRNet和OCRNet为骨干网络的模型。在训练过程中,我们也探索了SE、CBAM、scSE等注意力机制模块(Attention Module),最后采用了提升效果最多的SE模块。由于比赛经验生疏,我们当时错误地训练了部分大模型,然而融合后提升微薄。事实上,模型差异越大,后续融合结果一般更好。实际环境下,若考虑计算开销,也许训练U-Net等诸多小模型融合,效果更好,速度更快。
我们使用PaddleSeg开源的预训练模型,在data/code/pdseg/models/modeling/hrnet.py的原HRNet模型中加入了SE、CBAM、scSE的实现。由于OCRNet无预训练模型,我们拷贝了当时PaddleSeg最新版本静态图的ocrnet.py,在训练时只加载骨干网络中HRNet的参数。以SE模块为例,代码如下所示:
-
# channel SE (SE/SCSE)
-
def channel_se(input,
-
num_channels,
-
reduction_ratio,
-
name=None):
-
pool = fluid.layers.pool
2d(
-
input=input, pool_size=
0, pool_type='avg', global_pooling=True)
-
stdv =
1.
0 / math.sqrt(pool.shape[
1] *
1.
0)
-
squeeze = fluid.layers.conv
2d(
-
input=pool,
-
num_filters=int(num_channels / reduction_ratio),
-
filter_size=
1,
-
act='relu',
-
param_attr=fluid.param_attr.ParamAttr(
-
initializer=fluid.initializer.Uniform(-stdv, stdv),
-
name=name + '_sqz_weights',
-
trainable=TRAINABLE),
-
bias_attr=False)
-
stdv =
1.
0 / math.sqrt(squeeze.shape[
1] *
1.
0)
-
excitation = fluid.layers.conv
2d(
-
input=squeeze,
-
num_filters=num_channels,
-
filter_size=
1,
-
act='sigmoid',
-
param_attr=fluid.param_attr.ParamAttr(
-
initializer=fluid.initializer.Uniform(-stdv, stdv),
-
name=name + '_exc_weights',
-
trainable=TRAINABLE),
-
bias_attr=False)
-
scale = fluid.layers.elementwise_mul(x=input, y=excitation, axis=
0)
-
return scale
模型预测
在测试时,我们进行了多种数据增强(Test Time Augmentation,TTA),包括尺度放缩、水平和垂直翻转、90度倍数旋转,实际上,“原图+水平翻转+垂直翻转+180度旋转”就足够了,更多的TTA提升效果很小。得到这些预测后,我们不是进行Softmax分数求和的软投票,而是逐像素少数服从多数的硬投票,并且用二分类预测逐优先级覆盖多分类预测,人为地规定了“道路>水体>建筑>其他”的优先级。这里,我们利用“多进程+numpy矩阵运算”,大大减少了投票花费的时间。
测试时增强,需要对输入进行transform,并对输出进行相反transform,代码见:
data/code/pdseg/tools/invert_multi_class_results.py
invert_binary_class_results.py
硬投票代码见:
data/code/pdseg/tools/multi_class_voting.py
binary_class_voting.py。
连通性后处理
最后,我们使用形态学处理,进一步提高了连通性。首先,我们用闭运算连接断裂处,再用中值滤波去除毛刺;其次,用面积和长度筛选阈值孤立像素团,并用左边像素类别进行替换去除;然后,我们设计了骨架连通性增强方案,提取出某类的骨架,并适当地膨胀腐蚀,保证连通的同时不会过度超出原始预测区域;最后,我们设计了一个动态优先级算法,动态地进行不同类别的覆盖(主要考虑水体与道路类覆盖优先级)。
具体代码见data/code/pdseg/tools/post_processing.py,主要使用cv2进行图像处理。
结果对比
原图(左)、单模型预测(中)、多模型预测(右)
最终的结果输出如图10中右图所示。从中,我们可以看到最终的预测图更加平滑,类别噪点大大减少,并且保证了道路和水体较好的连通性。此处融合结果更多考虑了连通性,因而可能存在“误判”的结果,实际环境下可考虑准确性和连通性的权衡,调整阈值和权值。
附录:语义分割trick总结
基于SegNet和U-Net的遥感图像语义分割
-
数据增强:原图与label图旋转90度的整数倍(90/180/270),原图和label图沿y轴旋转,原图做模糊操作、光照调整操作、加噪声(高斯/椒盐);
-
转为二分类:对每一分类训练二分类模型,对预测图按优先级叠加;
-
模型融合:对结果进行投票叠加。
语义分割训练与优化技巧
-
这篇文章介绍了更多可用的数据增强,这里推荐使用Albumentations库,速度更快,内容更丰富;
-
几何变换:水平翻转(遥感还可以垂直翻转)、平移、随机裁剪和缩放(比例需要研究)、旋转;
-
纹理增强:亮度和对比度、色调饱和度对比度HSV、运动模糊、颜色抖动、限制对比度的自适应直方图均衡化;
-
其他增强:超像素、锐化、透视变换。
Airbus Ship Detection 卫星图像分割检测
-
数据扩增,与前面内容类似,进行90度倍数旋转等;
-
TTA单图多测,单图多scale投票:https://zhuanlan.zhihu.com/p/131539596。
Kaggle 气胸识别分割比赛新手铜牌总结及冠军分案
-
均衡采样:不同训练阶段不同采样;
-
联合损失函数:利用BCE loss、Dice loss和Focal loss;
-
针对二分类进行后处理。
Kaggle优胜者详解:如何用深度学习实现卫星图像分割与识别
-
为不同类别训练特定模型;
-
对数据先归一化为具有零均值和单位方差,之后进行数据增强过采样;
-
在测试的时候滑动窗口拼接,TTA平均输出;
-
后处理简单使用扩展和腐蚀操作,去除小于给定阈值的物体和小孔。
-
ECCV 2020 大规模实例分割挑战赛(LVIS Challenge)冠军方案
-
Repeat Factor Sampling样本采样技术,类似于重采样保证样本均衡;
-
数据增广中使用了Mosaic、旋转和尺度扰动;
-
利用DCE loss和weighted BCE loss;
-
分类器平衡:在表示学习部分结束后,冻结网络中的部分内容,使用Balanced Group Softmax进行分类器平衡(目标检测长尾效应中使用)。
-
CRF后处理
-
有关“CRF+填孔后处理”,具体可参考文章“【图像后处理】python实现全连接CRFs后处理”;
-
代码参考:
https://github.com/Gurupradeep/FCN-for-Semantic-Segmentation
https://github.com/1044197988/Semantic-segmentation-of-remote-sensing-images等。
如在使用过程中有问题,可加入官方QQ群进行交流:778260830。
如果您想详细了解更多飞桨的相关内容,请参阅以下文档。
·飞桨官网地址·
https://www.paddlepaddle.org.cn/
·飞桨开源框架项目地址·
GitHub:
https://github.com/PaddlePaddle/Paddle
Gitee:
https://gitee.com/paddlepaddle/Paddle
转载:https://blog.csdn.net/PaddlePaddle/article/details/113869571