Kaggle竞赛实战:用EyePacs数据集训练你的第一个糖尿病视网膜病变AI模型(附完整代码)
2026/5/29 2:16:44 网站建设 项目流程

Kaggle竞赛实战:用EyePacs数据集训练糖尿病视网膜病变AI模型

在医疗AI领域,糖尿病视网膜病变(DR)检测一直是最具挑战性的计算机视觉任务之一。2019年Kaggle竞赛提供的EyePacs数据集为开发者提供了绝佳的实战机会——35126张标注图像、五个病变等级分类任务,以及真实世界中的各种图像质量问题。本文将带你从零开始,完整实现一个能在Kaggle排行榜上获得竞争力的DR检测模型。

1. 环境准备与数据获取

1.1 Kaggle API配置

首先需要设置Kaggle API以便直接下载数据集:

pip install kaggle mkdir ~/.kaggle cp kaggle.json ~/.kaggle/ chmod 600 ~/.kaggle/kaggle.json

然后下载EyePacs数据集:

kaggle competitions download -c diabetic-retinopathy-detection unzip diabetic-retinopathy-detection.zip -d eyepacs_data

1.2 基础依赖安装

推荐使用PyTorch环境:

pip install torch torchvision pandas numpy opencv-python albumentations scikit-learn

2. 数据探索与预处理

2.1 数据分布分析

EyePacs数据集存在严重的类别不平衡问题:

病变等级样本数量占比
02581073.5%
124437.0%
2529215.1%
38732.5%
47082.0%

2.2 图像预处理技巧

黑边裁剪算法

import cv2 def crop_black_borders(image, threshold=10): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, threshold, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: cnt = max(contours, key=cv2.contourArea) x,y,w,h = cv2.boundingRect(cnt) return image[y:y+h, x:x+w] return image

CLAHE增强

def apply_clahe(image, clip_limit=2.0, grid_size=(8,8)): lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB) l, a, b = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size) cl = clahe.apply(l) limg = cv2.merge((cl,a,b)) return cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)

注意:EyePacs数据集中约15%的图像存在严重质量问题(失焦、曝光异常),建议在预处理阶段过滤掉这些样本

3. 模型架构与训练策略

3.1 改进的ResNet架构

针对眼底图像特点,我们对标准ResNet做了以下改进:

  1. 输入层调整:将第一个7x7卷积改为3个3x3卷积,保留细节
  2. 注意力机制:在最后两个残差块后添加CBAM注意力模块
  3. 多尺度特征融合:使用FPN结构整合不同层级的特征
import torch.nn as nn from torchvision.models import resnet50 class DRResNet(nn.Module): def __init__(self, num_classes=5): super().__init__() base = resnet50(pretrained=True) self.features = nn.Sequential(*list(base.children())[:-2]) self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.classifier = nn.Linear(2048, num_classes) def forward(self, x): x = self.features(x) x = self.avgpool(x) x = torch.flatten(x, 1) return self.classifier(x)

3.2 解决类别不平衡的技巧

  1. 加权损失函数
class_counts = [25810, 2443, 5292, 873, 708] weights = 1. / torch.tensor(class_counts, dtype=torch.float) weights = weights / weights.sum() criterion = nn.CrossEntropyLoss(weight=weights)
  1. 分层采样
from sklearn.model_selection import StratifiedKFold skf = StratifiedKFold(n_splits=5) for train_idx, val_idx in skf.split(X, y): train_sampler = SubsetRandomSampler(train_idx) val_sampler = SubsetRandomSampler(val_idx)

4. 竞赛优化技巧

4.1 测试时增强(TTA)

def predict_with_tta(model, image, n_aug=5): transforms = [ A.HorizontalFlip(p=1), A.VerticalFlip(p=1), A.Rotate(limit=45, p=1), A.RandomBrightnessContrast(p=1) ] preds = [] with torch.no_grad(): preds.append(model(image)) for t in random.sample(transforms, n_aug-1): augmented = t(image=image)['image'] preds.append(model(augmented)) return torch.mean(torch.stack(preds), dim=0)

4.2 模型集成策略

模型类型输入尺寸增强方式验证准确率
ResNet50512x512CLAHE+裁剪0.812
EfficientNetB5768x768仅中心裁剪0.798
ViT-Small384x384多尺度裁剪0.805

加权集成代码

ensemble_pred = 0.5*resnet_pred + 0.3*effnet_pred + 0.2*vit_pred

5. 提交与结果分析

5.1 Kaggle提交格式

submission = pd.DataFrame({ 'id_code': test_ids, 'diagnosis': predictions }) submission.to_csv('submission.csv', index=False)

5.2 常见错误分析

  1. 标签噪声问题:约8%的训练样本存在标注不一致
  2. 图像质量问题:建议过滤掉模糊度>0.3的图像
  3. 评估指标理解:Kaggle使用二次加权kappa评分

提示:在最终提交前,建议在本地验证集上计算kappa分数,确保与公开排行榜趋势一致

6. 进阶优化方向

  1. 病变区域定位:添加辅助分割头预测出血点/渗出物位置
  2. 多任务学习:同时预测病变等级和黄斑水肿风险
  3. 自监督预训练:利用未标注数据先进行对比学习预训练
# 自监督预训练示例 ssl_model = SimCLR(backbone='resnet50') ssl_trainer = pl.Trainer(max_epochs=100) ssl_trainer.fit(ssl_model, unlabeled_dataloader)

在实际比赛中,我们发现将512x512图像输入到集成模型中,配合适度的TTA增强,能在保持推理速度的同时获得0.85+的kappa分数。对于关键医疗应用,建议额外增加不确定性估计模块,过滤低置信度预测。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询