Aptos2019数据集实战指南:从数据预处理到模型训练全流程解析

1次阅读
没有评论

共计 2657 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

数据集背景

Aptos2019 数据集是 2019 年 APTOS(Asia Pacific Tele-Ophthalmology Society)糖尿病视网膜病变检测竞赛使用的数据集,包含数千张眼底图像,每张图像由专业医师标注为 0 - 4 五个等级(无病变到增殖性视网膜病变)。该数据集对早期筛查糖尿病引起的视力损伤具有重要意义。

Aptos2019 数据集实战指南:从数据预处理到模型训练全流程解析

  • 数据结构 :原始数据为 JPEG 格式的眼底照片,伴随 CSV 文件记录图像文件名与诊断标签
  • 挑战性 :图像分辨率差异大(从几百到几千像素不等)、类别分布不均衡(轻度病例居多)
  • 医学特性 :需保留微动脉瘤、出血点等关键病变特征,常规增强方法可能破坏病理特征

数据预处理

  1. 环境准备

    import pandas as pd
    import cv2
    from PIL import Image
    import numpy as np

  2. 标准化图像尺寸 (统一到 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)

  3. 标签处理 (转 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 模型训练示例

  1. 自定义 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)

  2. 训练循环核心代码

    # 使用 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()

超参数优化建议

  1. 批处理大小 :医学图像建议 8 -32,过大易丢失细节特征
  2. 学习率
  3. 主干网络:1e- 5 到 1e-4
  4. 新增层:1e- 4 到 1e-3
  5. epoch 数量 :早停法(patience=5)配合验证集监控
  6. 优化器选择 :AdamW 通常比 SGD 表现更好

延伸思考

  1. 如何设计适用于多中心医疗数据的标准化流程?
  2. 在数据量有限的情况下,哪些自监督学习方法可以提升模型性能?
  3. 如何将病变定位(如出血点检测)与分级任务结合?

通过本教程的完整实践,读者应该能够建立基线模型并达到 0.7 以上的 kappa 分数。建议后续尝试:
– 使用 Grad-CAM 可视化模型关注区域
– 测试 Vision Transformer 架构的表现
– 探索多模态融合(如结合患者临床数据)

正文完
 0
评论(没有评论)