kaggle糖尿病视网膜病变失明检测top5解决方案

news/2025/2/3 22:38:09/

比赛背景

想象一下,在失明发生之前就能够发现病变。数以百万计的人患有糖尿病性视网膜病变,这是导致老年人失明的主要原因。印度的Aravind眼科医院希望在农村地区的人们中发现并预防这种疾病,而那里的医疗筛查很难进行。目前,Aravind技术人员前往这些农村地区拍摄图像,然后依靠训练有素的医生对图像进行检查并提供诊断。因此kaggle举办了场比赛来加快疾病筛查。(本人排名:top6%,151/2987)

数据状况

图像为在各种成像条件下使用眼底摄影拍摄的大量视网膜图像。并由临床医生对每幅糖尿病视网膜病变的严重程度进行了0到4分的评分。

在这里插入图片描述

类别有5类,分别为:

0 - No DR
1 - Mild
2 - Moderate
3 - Severe
4 - Proliferative DR

各个类别下的图片数目为:{0: 1805, 1: 370, 2: 999, 3: 193, 4: 295},如下图:

在这里插入图片描述

补充数据:https://www.kaggle.com/tanlikesmath/diabetic-retinopathy-resized,此数据来自于2015年的比赛:https://www.kaggle.com/c/diabetic-retinopathy-detection/

1st解决方案

验证策略

在早期阶段,作者使用2015年的数据(训练和测试数据)作为训练集,并用2019年的训练数据作为验证集,但是验证结果与LB相差比较大。因此作者将2015年和2019年的数据作为训练集,依靠LB结果来验证结果。

预处理

作者认为图像质量已经非常好了,不需要进行预处理,只是进行resize。

模型与输入大小

作者使用了集成学习的思想,使用了8个模型进行分类,并表示如果比赛还有两个星期的话,还会使用EfficientNets。作者使用的模型及输入大小如下:

2 x inception_resnet_v2, input size 512
2 x inception_v4, input size 512
2 x seresnext50, input size 512
2 x seresnext101, input size 384

作者观察了2015年的比赛发现更大的输入能取得更好的结果,但是作者发现输入大小超过384之后并没有带来多大性能提升。

损失函数

作者只使用了nn.SmoothL1Loss()作为损失函数,来简化集成学习过程。

数据增强

contrast_range=0.2,
brightness_range=20.,
hue_range=10.,
saturation_range=20.,
blur_and_sharpen=True,
rotate_range=180.,
scale_range=0.2,
shear_range=0.2,
shift_range=0.2,
do_mirror=True,

池化

对于最后一个池化层,作者发现广义平均池化(generalized mean pooling,https://arxiv.org/pdf/1711.02512.pdf) 效果比原始的平均池化效果好,代码地址:https://github.com/filipradenovic/cnnimageretrieval-pytorch。

from torch.nn.parameter import Parameter
def gem(x, p=3, eps=1e-6):return F.avg_pool2d(x.clamp(min=eps).pow(p), (x.size(-2), x.size(-1))).pow(1./p)
class GeM(nn.Module):def __init__(self, p=3, eps=1e-6):super(GeM,self).__init__()self.p = Parameter(torch.ones(1)*p)self.eps = epsdef forward(self, x):return gem(x, p=self.p, eps=self.eps)       def __repr__(self):return self.__class__.__name__ + '(' + 'p=' + '{:.4f}'.format(self.p.data.tolist()[0]) + ', ' + 'eps=' + str(self.eps) + ')'
model = se_resnet50(num_classes=1000, pretrained='imagenet')
model.avg_pool = GeM()

训练和测试

训练过程可以分为两个阶段。

  1. 单独训练这8个模型通过public LB来验证。而为了得到更稳定的结果,作者将模型进行成对评估(每种模型都有2个,使用不同的随机种子)。作者减少超参数的自由度来减轻过拟合问题,比如,为了确定训练的最佳epoch数目,以5为步长来增加训练epoch数目。以下是第1阶段训练后的优化结果:
inceptionresnetv2 public: 0.831 private: 0.927
inception_v4 public: 0.826 private: 0.924
seresnext50 public: 0.826 private: 0.931
seresnext101 public: 0.819 private: 0.923 (the 2nd best result, missing the best)
ensemble public: 0.844 private: 0.934
  1. 将public测试数据添加伪标签,再使用另外两个数据集(Idrid和Messidor),将它们添加到训练集中。

2nd解决方案

数据

使用2015年的数据对模型进行预训练,public LB只有0.73~0.75.

使用2019年数据训练,2015年数据进行测试。

模型

作者使用了se-resnet50,se-resnet101,densenet,效果都不行,唯一效果好的网络是efficient-net,因此作者集成了efficient-net b3, b4, b5。

  • b3图像尺寸:300
  • b4图像尺寸:460
  • b5图像尺寸:456

预处理

作者截取掉了图像中黑色的区域,然后只是对图像进行resize。

数据增强

作者使用了有生以来最多的数据增强操作:Blur, Flip, RandomBrightnessContrast, ShiftScaleRotate, ElasticTransform, Transpose, GridDistortion, HueSaturationValue, CLAHE, CoarseDropout。它们都来自于albumentations库。

训练

使用2015年的数据进行预训练模型(b3训练大概80轮,b5训练大概15轮),使用2019年的数据进行训练(b3训练大概50轮,b5训练大概15轮),选取表现最好的模型,然后把这两个模型的结果求均值。作者也使用了TTA。

秘方

作者对测试数据进行伪标签标注,然后使用训练数据+带伪标签的测试数据进行fine-tune网络,结果得到了巨大提升,因此作者进行了多次伪标签操作,同样,对2015年的测试数据也打上伪标签来增加训练数据。

(第3名解决方案截止本文发表时,还没有公布)

4th解决方案

预处理

截取掉黑色部分信息(训练和测试都采用),代码来自于这里:

def crop_image_from_gray(img,tol=7):if img.ndim ==2:mask = img>tolreturn img[np.ix_(mask.any(1),mask.any(0))]elif img.ndim==3:gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)mask = gray_img>tolcheck_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]if (check_shape == 0): # image is too dark so that we crop out everything,return img # return original imageelse:img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]#         print(img1.shape,img2.shape,img3.shape)img = np.stack([img1,img2,img3],axis=-1)#         print(img.shape)return img

数据增强

使用Dihedral, RandomCrop, Rotation, Contrast, Brightness, Cutout, PerspectiveTransform, Clahe。

模型

作者发现在大模型上使用高分辨率图像更容易过拟合,因此作者使用小模型配高分辨率图像或者大模型配低分辨率图像:

  • EfficientNet-B7 (224x224) LB 0.840
  • EfficientNet-B6 (240x240) LB 0.832
  • EfficientNet-B5 (256x256) LB 0.831
  • EfficientNet-B4 (320x320) LB 0.826
  • EfficientNet-B3 (352x352) *LB Don’t Know
  • EfficientNet-B2 (376x376) LB 0.828

使用5折交叉验证和TTA(8张图片,四个边角图片,然后再翻转)。

训练过程

在2015年所有数据(训练集和测试集)上预训练模型,轮数25轮,不进行验证,然后在2019年数据上进行5折交叉验证。

预测过程

使用5个模型+TTA(8张边角图片),只预处理图片一次来节省时间。

5th解决方案

模型

  • efficientnet-b0
  • efficientnet-b1
  • efficientnet-b2
  • efficientnet-b3

数据预处理和增强

  • 截取掉黑色背景
  • 图像大小:384 x 384
  • 使用Fliplr, Flipud, Randomrotate(0, 360), zoom(1.0, 1.35)和自行设计的透视变换方法。

训练策略

  • 五折交叉验证
  • 不在2015年数据上预训练并在2019年数据上微调,而是将2015年和2019年数据结合起来训练模型,在2015年private test和2019年验证数据上进行验证。
  • lr_schedule:Adam优化器,lrs=[5e-4, 1e-4, 1e-5, 1e-6],训练25轮,在[10, 16, 22]轮进行学习率衰减。
  • 2*TTA
  • threshold:[0.5, 1.5, 2.5, 3.5]

伪标签

  • 作者认为伪标签是赢得比赛的关键,因为不知道2019年private test数据集的分布,所以将三份数据集(2015年数据,2019年训练数据和2019年public数据)结合起来训练模型,使模型能够识别这三种不同的数据分布。
  • 作者没有使用2019年的public数据做伪标签样本,而是选择更高置信度的样本
  • 伪标签降低了本地mse损失,提高了qwk值(二次加权Kappa)。

本人解决方法

2015年数据+2019年数据作为训练验证集,模型使用efficient-net b5,图像大小256,优化器使用了前段时间刚出的RAdam和Ranger。

小贴士

TTA

Test Time Augmentation,测试时增强,这里会为原始图像造出多个不同版本,包括不同区域裁剪和更改缩放程度等,并将它们输入到模型中;然后对多个版本进行计算得到平均输出,作为图像的最终输出分数。这种做法在AlexNet的论文中就已经有了。在fast ai中可以通过以下方式实现:

preds, target = learn.TTA()

伪标签(pseudo label)

对于public test数据,使用训练数据训练出的模型对它进行预测,对于置信度高的样本,我们将预测结果作为它的“标签”——伪标签(又称软标签,soft label),然后将伪标签数据添加到训练数据中。

QWK(二次加权Kappa)

比赛使用QWK来评估结果,对于眼底图像识别,class=0为健康,class=4为疾病晚期非常严重,所以对于把class=0预测成4的行为所造成的惩罚应该远远大于把class=0预测成class=1的行为,使用quadratic的话将0预测成4所造成的惩罚就等于16倍的将0预测成1的惩罚。


http://www.ppmy.cn/news/882332.html

相关文章

视网膜血管分割方法整理

Project introduction 眼底血管分割是一个成熟的分割主题任务,在网络上已经有很多的解决方案这里我只是记录一下我的解决方案,眼底血管有明显的形态学特征,但是血管的粗细不等给分割造成了难度,同时也会存在其他血管结构和视神经…

源自视网膜细胞的poisson disk distribution

在渲染中我们在做各种up sampling的时候,会常常使用poisson disk distribution。 常常来说,我们就知道这个东东效果很好,就作为一个“黑盒”工具来使用,和高斯blur有点像,反正就用了。 那这个poisson disk distributi…

那些TensorFlow上好玩的和黑科技

那些TensorFlow上好玩的和黑科技 Google于2017年2月16日(北京时间)凌晨2点在美国加利福尼亚州山景城举办了首届TensorFlow开发者峰会。Google现场宣布全球领先的深度学习开源框架TensorFlow正式对外发布V1.0版本,并保证Google的本次发布版本的…

数字视网膜演化简史

2020-04-01 20:32 导语:一位学者在学术领域开山立派,最显著的一个标志就是某个学术概念能够与该学者划等号 一位学者在学术领域开山立派,最显著的一个标志就是某个学术概念能够与该学者划等号,例如当提起相对论必然会联想到爱因…

视网膜分辨率_了解像素密度,分辨率和视网膜显示

视网膜分辨率 Digital content creators are abuzz about “high DPI” and “Retina” displays: how they are changing the nature of the web and complicating the design process. Before telling you how to develop images for these new devices, it makes sense to u…

MySQL表的约束与内置函数

目录 MySQL表的约束 空属性 默认值 列描述comment zerofill 主键 复合主键 自增长 唯一键 外键 MySQL的内置函数 日期函数 字符串函数 ​编辑数学函数 其他函数 MySQL表的约束 MySQL表的约束是用于规定表中数据的完整性和一致性的规则。 约束可以在创建表时定义&…

【Linux初阶】基础IO - 软硬链接 | 初识、理解、应用 文件acm时间

🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【Linux初阶】 ✒️✒️本篇内容:初识软硬链接,软硬链接的区别,理解软硬链接,软硬链接的应用,文…

苹果4s忘记id密码怎么办_大哭!iPhone手机ID密码忘记了怎么办?3种方法轻松解决问题...

123阅读本文前,请您先点击上面的“蓝色字体”,再点击“关注”,这样您就可以继续免费收到文章了。每天都会有分享,都是免费订阅,请您放心关注。 每一个苹果用户都有一个iPhone ID,它的好处不言而喻&…