共计 2657 个字符,预计需要花费 7 分钟才能阅读完成。
数据集背景
Aptos2019 数据集是 2019 年 APTOS(Asia Pacific Tele-Ophthalmology Society)糖尿病视网膜病变检测竞赛使用的数据集,包含数千张眼底图像,每张图像由专业医师标注为 0 - 4 五个等级(无病变到增殖性视网膜病变)。该数据集对早期筛查糖尿病引起的视力损伤具有重要意义。

- 数据结构 :原始数据为 JPEG 格式的眼底照片,伴随 CSV 文件记录图像文件名与诊断标签
- 挑战性 :图像分辨率差异大(从几百到几千像素不等)、类别分布不均衡(轻度病例居多)
- 医学特性 :需保留微动脉瘤、出血点等关键病变特征,常规增强方法可能破坏病理特征
数据预处理
-
环境准备
import pandas as pd import cv2 from PIL import Image import numpy as np -
标准化图像尺寸 (统一到 512×512 并保持比例):
def resize_with_padding(img, target_size=512): # 计算缩放比例 h, w = img.shape[:2] scale = min(target_size/h, target_size/w) # 等比例缩放 new_h, new_w = int(h*scale), int(w*scale) resized = cv2.resize(img, (new_w, new_h)) # 添加黑边填充 delta_h = target_size - new_h delta_w = target_size - new_w top = delta_h // 2 bottom = delta_h - top left = delta_w // 2 right = delta_w - left return cv2.copyMakeBorder(resized, top, bottom, left, right, cv2.BORDER_CONSTANT, value=0) -
标签处理 (转 one-hot 编码):
from keras.utils import to_categorical # 假设 df 是包含原始标签的 DataFrame labels = to_categorical(df['diagnosis'], num_classes=5)
数据增强策略
医学图像增强需遵循两个原则:不改变病理特征、模拟实际拍摄条件变化。推荐使用 albumentations 库:
import albumentations as A
transform = A.Compose([A.RandomRotate90(p=0.5), # 90 度随机旋转
A.HorizontalFlip(p=0.3), # 水平翻转
A.RandomBrightnessContrast( # 亮度对比度微调
brightness_limit=0.1,
contrast_limit=0.1, p=0.5),
A.CLAHE(clip_limit=2.0, p=0.3), # 限制对比度自适应直方图均衡
A.GaussianBlur(blur_limit=3, p=0.1) # 模拟轻微失焦
])
PyTorch 模型训练示例
-
自定义 Dataset 类
from torch.utils.data import Dataset class RetinaDataset(Dataset): def __init__(self, image_paths, labels, transform=None): self.image_paths = image_paths self.labels = labels self.transform = transform def __getitem__(self, idx): img = Image.open(self.image_paths[idx]) if self.transform: img = self.transform(img) return img, self.labels[idx] def __len__(self): return len(self.image_paths) -
训练循环核心代码
# 使用 EfficientNet 预训练模型 model = torchvision.models.efficientnet_b0(pretrained=True) model.classifier[1] = nn.Linear(1280, 5) # 修改输出层 # 加权交叉熵解决类别不平衡 weights = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0]) criterion = nn.CrossEntropyLoss(weight=weights) # 分层学习率 optimizer = torch.optim.Adam([{'params': model.features.parameters(), 'lr': 1e-4}, {'params': model.classifier.parameters(), 'lr': 1e-3} ])
常见问题与解决方案
- 问题 1:验证集准确率高但实际预测差
- 原因:可能因随机拆分导致测试集与训练集分布不一致
-
解决:使用分层抽样(StratifiedKFold)确保每折数据分布相同
-
问题 2:模型偏向多数类
- 方案 1:采用加权损失函数(如上文代码示例)
- 方案 2:过采样少数类或欠采样多数类
-
方案 3:使用 Focal Loss 抑制易分类样本的梯度
-
问题 3:GPU 内存不足
- 调整 batch_size 到 8 或 16
- 启用混合精度训练(AMP)
from torch.cuda.amp import GradScaler, autocast scaler = GradScaler() with autocast(): outputs = model(inputs) loss = criterion(outputs, labels) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()
超参数优化建议
- 批处理大小 :医学图像建议 8 -32,过大易丢失细节特征
- 学习率 :
- 主干网络:1e- 5 到 1e-4
- 新增层:1e- 4 到 1e-3
- epoch 数量 :早停法(patience=5)配合验证集监控
- 优化器选择 :AdamW 通常比 SGD 表现更好
延伸思考
- 如何设计适用于多中心医疗数据的标准化流程?
- 在数据量有限的情况下,哪些自监督学习方法可以提升模型性能?
- 如何将病变定位(如出血点检测)与分级任务结合?
通过本教程的完整实践,读者应该能够建立基线模型并达到 0.7 以上的 kappa 分数。建议后续尝试:
– 使用 Grad-CAM 可视化模型关注区域
– 测试 Vision Transformer 架构的表现
– 探索多模态融合(如结合患者临床数据)
正文完
