2018 AI Challenger全球AI挑战赛‘眼底水肿病变区域自动分割’赛道比赛总结
苏州的十月,无论是天气还是桂香都觉得让人无所适从,忙碌的低年级学生一阵风似的从身边经过,恍惚才觉得,这是我最真真切切的体会到的苏州的秋,大概是因为快离开这个校园的缘故吧,一切都是那么匆忙,就连一场夜间的秋雨都是那么急促而又清冷。
这大概是半个月之前的事了,那个时候正值国庆,几乎所有同学都回家了,我们三个却忙了一整个国庆节,这是我准备了将近一个月的比赛,结局却以0.7145而告终,伤心却也庆幸。
赛后感想
从os.walk到glob
这个小标题并没有说明什么实际意义,只是我在这个比赛过程中真的学到了很多,由于比赛数据是类似于三维cube,每128张slice都在一个文件夹里面,所以读取数据这方面真的学到了不少,从之前的os.dirlist到最后的glob,逐渐发掘最简单的最有效的读取数据程序。
从return到yield
以前并不明白生成器是什么东西,自从参加了这个比赛后,觉得生成器真的是神经网络的必备套餐,因为你不可能用一个array存储你所有的数据,这里最好就用生成器,特别在数据增强这一块,如果你训练网络不会数据增强,那要你何用!
赛题简介
训练集包含原始图片和标注图片,分别对应70个cube的128张图片。
标注图片中各标记值如下所示:
Background:0
PED: 128
SRF: 191
REA: 255
例(原图、标记图像对比):
验证集含有15个cube,除了原始图片和标注图片之外还给出了“groundtruth”文件,作为提交结果的标准。
测试集含有15个cube,只有原始图片。
结果提交说明
提交结果包括检测结果和分割结果两部分,要求与验证集中的“groundtruth”格式相同。
1) 检测结果:
每个cube对应一个npy文件,命名格式为“cube名称”+“_detections”,文件中存储[128,3]的矩阵,分别对应1-128号图片的3种水肿的检测结果,水肿顺序为REA,SRF,PED,用0.0-1.0之间的概率值表示。
REA SRF PED
0.5, 0.5, 0.5
0.5, 0.5, 0.5
...
2) 分割结果:
每个cube对应一个npy文件,命名格式为“cube名称”+“_volumes”,文件中存储[128,1024,512]的矩阵,分别对应1-128号图片的体素级分割结果,分别用体素标记0,1,2,3来代表背景和水肿区域,详细标记如下:
1.Retina Edema Area, REA
2.Subretinal Fluid, SRF
3.Pigment Epithelial Detachment, PED
其余部分标记为0.
评价标准
本次比赛的评价标准包括两部分:(1)检测结果,(2)分割结果,因此会产生两份榜单,两份榜单上分数的平均值将决定比赛的最终排行。
1) 检测结果:
检测结果将与专家标注的结果进行比较。分别计算REA,SRF,PED的AUC值,并将三者的平均值作为最终分数。
2) 分割结果:
检测结果将与专家标注的结果进行比较。分别计算REA,SRF,PED的骰子系数,并将三者的平均值作为最终分数
正题——从数据预处理说起
数据统计
进行一个比赛,第一步就是要做数据分析,分析这些数据的特征已经是否样本平衡,由于主要有3类疾病分割,也就涉及到多类分割的问题,但是并不是没张图片上面都有3类疾病,有一半的图片上面是什么都没有的,也就是全为背景。
训练集:
验证集:
具体数据分布:
训练集:8960
000: 数量:4296 不含任何一种病 比例是:0.479
100: 数量:1571 仅含rea 0.1753
101: 数量:159 含rea和ped 0.017
110: 数量:2691 含rea和srf 0.3
111:数量:243 三种都含 0.027
验证集:1920
000:数量:1086 比例:0.5656
100: 446 0.2322
101: 28 0.01458
110: 347 0.1807
111: 13 0.0067
二类分割统计(去掉了label不标准的2个cube(256张)):
训练集:
验证集:
具体数据分布:
训练集:
PED:402
REA:4465
SRF:2802
验证集:
PED:22
REA:559
SRF:248
数据分布分析:
可以看出数据分布也是极不均衡的,大概8960张图片中有一半的图片是无病的,如果进行二类分割的话,PED数量极少,而且目标区域很小,下面给出三个常见的三种疾病区域大小:
REA
SRF
PED
难点分析
- 数据不均衡,背景图片占一大半,比着自然场景的分类,类别不均衡,PED和SRF相对较小,PED的一点偏移都会影响Dice系数。
- 数据量有点大,网络的选取很重要,还有Loss的选取同样重要
策略
在这里我就不过多分析了,直接说我们用的策略
(1)2D-Vnet
输入:无处理送入
输出:4类分割(背景算一类)
Loss: softmax-CE+Dice
这个网络要比U-net好,经过我快一个月的调试,事实证明应该可以应付一般数据的分割,我认为在Loss上做手脚更好。在这个网络中,我们一开始用的是Dice,最后又加了softmax-CE,加了softmax-CE之后效果明显有提升,最后又加了一个Focal-Loss,效果提升不明显
(1.2)2D-Vnet(只送前景)
输入:只训练有前景的图片
输出:4类分割(背景算一类)
Loss: softmax-CE+Dice
怎么说呢,这个想法主要是不让当Dice Loss做主导的时候,出现一直等于1,而不可导的情况,另一方面也可以解释为减少单纯的背景类。由于数据量减少了一半,所以这里用了数据增强,但是在增强的过程中,发现label的数据值会发生改变。会出现0和255之间的灰度值。对小面积前景有稍微影响
结果:其实在验证集上的结果是最好的,可以达到0.766,但是在测试集上超级差,也不知道为什么,可以怀疑是测试集和验证集数据分布差距较大,还可能是我们的网络对验证集已经过拟合了 ,OMG !这是一个非常可怕的事情,但是如果测试集和验证集分布式一样的,不知道这样会不会是一个比较好的方法,我觉得这个可以深入尝试一下,还有很有潜力的。
(2) PPM1248与PPM1236+Vnet
这个模块来源于PSPnet,感觉应该好呢,结果在验证集上有所提升,但是在测试集上表现并不是很好,但是最好的结果也是在PPM1236上面产生的。验证集和测试集差距较大,这一点真让人头疼。
(3) 作为3个二类分割(3个Vnet)
这个思路是通过联合策略来解决数据不平衡问题的,将3个前景分别提出来,每个都是只有一类前景和背景组成,但是解果并不理想,PED分的不清晰,噪点太多,这个会大大影响分数,可能原因:由于REA和PED,SRF面积差距较大,应该用不同网络来分割。
(4) Ensemble
我能说这是一个很牛逼的方法吗,几个结果进行整合产生一个更好的结果,这个在很多比赛中都会用到,也是我学到的最主要的一个方法。最后Ensemble后可得到0.7145的结果。
总结
其实在整个过程中,我发现有价值的就是:
1.softmax-CE+Dice
今天中午还在想怎么解决Dice系数隐藏的没有梯度的问题(如果是一类前景没有出现,那么在整个Loss中这个前景的Dice Loss就会一直是1,并没有进行梯度回传,也就是权重值也不会往这个方向修改)加入softmax-CE后,就是如果出现前面所述问题时就变成优化交叉熵了,也就是总有一个Loss在work.
2.只训练有前景图片的策略
我觉得这个策略可以尝试尝试,或者是因为标的金标准不好,导致在测试集上很差。
3.二类分割策略
这个策略或许会在以后分割过程中对多类分割进行分解,是一个好的方法。
待解决问题:
- 各类Dice+CE独立如果做到?
- 验证集和测试集差距为什么这么大?