信息速览
INFOBOX
| 数据集名称 | APTOS 2019 Blindness Detection |
| 英文全称 | Asia Pacific Tele-Ophthalmology Society 2019 Blindness Detection |
| 别名 / 简称 | APTOS 2019、APTOS-2019 BD、APTOS Blindness Detection |
| 疾病分类 | 9B71.0 糖尿病视网膜病变 |
| SNOMED CT | 422034002 Diabetic retinopathy / 399067008 Moderate non-proliferative diabetic retinopathy / 420815004 Severe non-proliferative diabetic retinopathy / 315051004 Proliferative diabetic retinopathy |
| 数据模态 | 影像(彩色眼底照片,fundus photography) |
| AI 任务类型 | 图像分类(5 级 DR 严重程度分级)、二分类(可转诊 DR 检测)、迁移学习基准 |
| 样本总数 | 3,662 张训练图像(标注)+ 1,928 张公开测试图像(无标签)+ ~13,000 张私有测试图像(无标签),合计 ~18,590 张 |
| 数据大小 | ~10.22 GB(竞赛公开数据集) |
| 数据格式 | PNG(图像)/ CSV(标签) |
| 许可证 | Kaggle 竞赛规则(Subject to Competition Rules,仅限非商业学术研究用途) |
| 访问级别 | 竞赛专用(需接受竞赛规则后下载,测试集标签未公开) |
| DUO 标签 | NPUNCU |
| 语言 | 英文(标签 CSV) |
| 首发日期 | 2019-06-28(Kaggle 竞赛开赛) |
| 最后更新 | 2019-09-08(竞赛结束,数据集未再更新) |
| 发布机构 | Asia Pacific Tele-Ophthalmology Society(亚太眼科学会)+ Aravind Eye Hospital(印度 Aravind 眼科医院) |
| 官方主页 | https://kaggle.com/competitions/aptos2019-blindness-detection |
| 下载地址 | https://kaggle.com/c/aptos2019-blindness-detection/data(需 Kaggle 账号 + 接受竞赛规则) |
| DOI | 无独立 DOI(引用 Kaggle 竞赛页面) |
| 引用次数 | 1,500+(Google Scholar 估算,截至 2026-08) |
| AI 就绪度评分 | ⭐⭐⭐⭐(4/5)— ICDR 标准五级分级 + Kaggle 竞赛标准化评测 + 活跃社区基准;扣分项:单标注者无 QC、268 张重复图像未修正、无患者级元数据、许可证限制商业使用 |
| 页面状态 | published |
§0 E-E-A-T 信任声明与免责声明
医学审核者:[千方病案医学编辑部]交叉审核:§2 医学背景(ICD-11 映射、ICDR 严重程度分级、临床任务定义、金标准描述)、§7 偏倚分析。
数据工程审核者:[千方病案医学编辑部交叉审核] 医疗 AI 数据工程师,审核范围:§4 DAIMS 数据字典、§5 数据划分策略、§6 预处理 Pipeline 和坑点。
审核日期:2026-08-04
医疗免责声明:本页面提供的医学信息仅供研究和教育目的,不构成医疗建议、诊断或治疗方案。数据集的医学描述基于公开发表的文献,未经逐一临床验证。任何基于该数据集训练的 AI 模型在应用于临床决策前,必须经过独立的临床验证和监管审批。
技术免责声明:本页面的代码示例、预处理建议和基准性能数据基于公开资料整理,不保证在特定环境下的准确性和适用性。使用者应自行验证代码安全性和数据预处理流程的正确性。千方病案医数集不对因使用本页面信息而导致的任何直接或间接损失承担责任。
数据使用合规:使用本页面描述的数据集前,请务必阅读并遵守数据集原始许可协议。APTOS 2019 受 Kaggle 竞赛规则约束,仅限非商业学术研究用途,禁止再分发。DUO 标签仅供参考,具体使用限制以数据集官方协议为准。
§1 数据集概览
§1.0 📌 30 秒速览
APTOS 2019 是亚太眼科学会(APTOS)与印度 Aravind 眼科医院于 2019 年通过 Kaggle 竞赛发布的糖尿病视网膜病变(DR)眼底影像数据集,包含 3,662 张标注训练图像和约 18,590 张总图像,由印度农村社区筛查中采集的真实临床照片组成,按国际临床糖尿病视网膜病变严重程度分级标准(ICDRSS)分为 5 级。
它的独特价值在于真实反映了医疗资源匮乏地区视网膜图像的非标准化采集状态——多相机型号、多采集环境、图像质量参差不齐、标注噪声显著,使其成为评估 DR AI 模型在真实世界部署中鲁棒性的高标准试金石。这与 EyePACS(美国多站点)和 MESSIDOR(法国控制环境)形成互补。竞赛吸引了 15,357 名参赛者,冠军 QWK 达 0.936。
你可以用它来:训练一个在印度农村人群上部署的 DR 筛查模型、研究类标签噪声和类不平衡对模型性能的影响、或者评估跨地域(美国→印度)域迁移的性能衰减。
§1.1 摘要
APTOS 2019 Blindness Detection 数据集由亚太眼科学会(APTOS)联合印度 Aravind 眼科医院构建,旨在通过 Kaggle 竞赛推动 DR 自动检测技术在发展中国家的应用。数据源自 Aravind 医院技术人员在印度泰米尔纳德邦农村地区开展的眼底筛查项目,使用多种型号的眼底相机在不同环境条件下采集。3,662 张训练图像由训练有素的眼科医生按 ICDRSS 五级分级标准标注:0-无 DR(1,805 张,49.3%)、1-轻度(370 张,10.1%)、2-中度(999 张,27.3%)、3-重度(193 张,5.3%)、4-增殖性(295 张,8.1%)。图像分辨率高度异质(474×358 至 4288×2848),格式为 PNG,总计约 10.22 GB。竞赛采用二次加权 Kappa(QWK)作为评测指标,私有测试集约 13,000 张图像。
§1.2 战略价值分析
真实世界临床噪声的代表性地集:与 MESSIDOR 的法国控制环境采集或 IDRiD 的单一相机型号不同,APTOS 2019 的图像来自印度农村多个筛查点、多种眼底相机、不同操作人员,产生了分辨率 9 倍差异、曝光/对焦/伪影等质量参差不齐的真实临床数据。这种"野外"特性使其成为测试 AI 模型域鲁棒性和部署可靠性的首选基准——在 APTOS 上表现好的模型,更可能在真实临床环境中保持性能。约 25% 的图像因质量问题不可分级,进一步放大了数据集对鲁棒性算法的需求。
发展中国家 DR 筛查的 AI 落地催化剂:APTOS 2019 竞赛直接服务于 Aravind 眼科医院的农村筛查项目——该院自 2013 年起与 Google/Verily 合作开发 ARDA(Automated Retinal Disease Assessment)算法,2019 年获 CE 认证后在泰米尔纳德邦 71 个视觉中心部署,截至 2023 年已筛查超过 60 万名患者,对重度 NPDR/PDR 的敏感度和特异度均超过 96%,漏诊率为 0%。APTOS 数据集的公开发布使全球研究者得以参与这一影响数百万糖尿病患者的公共卫生项目,推动了 DR AI 从实验室到大规模临床部署的转化。
§1.3 同类数据集横向对比
| 数据集 | 样本量 | 地域 | 标注者 | 分级标准 | 散瞳 | 相机 FOV | 许可证 | 核心差异化 |
|---|---|---|---|---|---|---|---|---|
| APTOS 2019 | 3,662(训练) | 印度农村 | 单标注者 | ICDR 5 级 | 未公开 | 多种 | 竞赛规则(非商业) | 真实世界印度农村筛查 |
| EyePACS | 88,702 | 美国 | 单标注者 | ICDR 5 级 | 混合 | 多种 45° | 竞赛规则(非商业) | 最大规模公开 DR 数据集 |
| MESSIDOR | 1,200 | 法国 | 多专家 | 量化阈值 4 级 | 67% 散瞳 | Topcon 45° | 非商业研究 | 量化分级标准 + 控制环境 |
| IDRiD | 516 | 印度 | 多专家 | ICDR 5 级 | 100% 散瞳 | Kowa 50° | CC BY-NC 4.0 | 病灶级像素标注 |
| DDR | 13,673 | 中国 | 眼科医生 | ICDR 5 级 | 未公开 | 多种 45° | 研究用途 | 像素级 + 边界框标注 |
| Kaggle DR 2015 | 88,702 | 美国 | 单标注者 | ICDR 5 级 | 混合 | 多种 | 竞赛规则 | APTOS 前身竞赛 |
§1.4 版本演进时间轴
| 时间 | 事件 |
|---|---|
| 2013 | Aravind 眼科医院与 Google 开始合作开发 DR 自动检测算法 |
| 2016 | Gulshan et al. JAMA 发表,使用扩展版 EyePACS(128,175 张)训练 Inception-v3,在 Aravind 和 Sankara Netralaya 验证 |
| 2019-02 | Google/Verily 的 ARDA 系统获 CE 认证,在 Aravind 眼科医院部署 |
| 2019-06-28 | APTOS 2019 Blindness Detection Kaggle 竞赛开赛 |
| 2019-09-08 | 竞赛结束,2,928 支队伍参赛,冠军 QWK=0.936 |
| 2019-09 | 第 4 届 APTOS 研讨会(印度),获奖方案展示 |
| 2023 | ARDA 在 Aravind 筛查 60 万+患者后,Ophthalmology 发表上市后临床性能报告 |
§1.5 典型 AI 应用场景
- DR 严重程度自动分级:训练 5 级分类模型(0-4),支持农村筛查点技术人员快速分诊
- 可转诊 DR 检测(二分类):将 0-1 归为"不可转诊"、2-4 归为"可转诊",减少不必要的眼科转诊
- 域迁移鲁棒性评估:用 EyePACS(美国)预训练 → APTOS(印度)微调,评估跨地域/跨相机/跨人群的性能衰减
- 标签噪声鲁棒训练:利用 APTOS 已知的 268 张重复/冲突标签图像研究噪声鲁棒损失函数
- 低算力端侧部署:在资源受限的农村筛查设备上部署轻量级 DR 检测模型
§2 医学背景
§2.1 ICD-11 编码映射
| 数据集标签 | ICD-11 编码 | 中文疾病名 |
|---|---|---|
| 0 - No DR | (正常/无病变) | 无糖尿病视网膜病变 |
| 1 - Mild NPDR | 9B71.0.Z | 轻度非增殖性糖尿病视网膜病变 |
| 2 - Moderate NPDR | 9B71.0.Z | 中度非增殖性糖尿病视网膜病变 |
| 3 - Severe NPDR | 9B71.0.Z | 重度非增殖性糖尿病视网膜病变 |
| 4 - Proliferative DR | 9B71.0.Z | 增殖性糖尿病视网膜病变 |
说明:ICD-11 中糖尿病视网膜病变统一归入 9B71.0,未按严重程度细分。严重程度分级采用国际临床糖尿病视网膜病变严重程度分级标准(ICDRSS),由美国眼科学会(AAO)于 2002 年提出,是国际通用的临床分级标准。
§2.1b SNOMED CT 映射
| 数据集标签 | SNOMED CT 代码 | SNOMED CT 术语 |
|---|---|---|
| 0 - No DR | 162059005 | No diabetic retinopathy (finding) |
| 1 - Mild NPDR | 399061005 | Mild non-proliferative diabetic retinopathy (disorder) |
| 2 - Moderate NPDR | 399067008 | Moderate non-proliferative diabetic retinopathy (disorder) |
| 3 - Severe NPDR | 420815004 | Severe non-proliferative diabetic retinopathy (disorder) |
| 4 - Proliferative DR | 315051004 | Proliferative diabetic retinopathy (disorder) |
§2.2 疾病简介与流行病学
糖尿病视网膜病变(DR)是糖尿病最常见的微血管并发症之一,是全球工作年龄成年人致盲的首要原因。根据国际糖尿病联盟(IDF)数据,2021 年全球糖尿病患者达 5.37 亿,预计 2045 年将达 7.83 亿;糖尿病患者中 DR 患病率约 34.6%。印度拥有超过 2.12 亿糖尿病患者(占全球 25%),每百万人仅约 15 名眼科医生,农村地区医疗资源严重匮乏。DR 早期无症状,但通过定期眼底筛查和及时治疗可将失明风险降低 95% 以上——这正是 AI 自动筛查在发展中国家的核心价值。
§2.3 临床任务定义
| 任务类型 | 定义 | 临床意义 |
|---|---|---|
| DR 严重程度分级 | 将眼底图像分为 5 级(0-4),按 ICDRSS 标准 | 支持分诊决策:哪些患者需转诊眼科 |
| 可转诊 DR 检测 | 二分类:0-1 不可转诊 vs 2-4 可转诊 | 减少不必要的眼科转诊,节约医疗资源 |
| 不可分级图像识别 | 识别因质量过差无法诊断的图像 | 自动请求重新拍摄,避免漏诊 |
§2.4 患者人群特征
| 维度 | 特征 |
|---|---|
| 数据来源 | Aravind 眼科医院农村社区筛查项目,泰米尔纳德邦,印度 |
| 采集时间 | 未公开具体起止时间,描述为"长时间跨度"采集 |
| 年龄分布 | 未公开(数据集不含患者人口统计数据) |
| 性别比例 | 未公开 |
| 种族分布 | 印度人群(主要为南亚裔) |
| 就医类型 | 社区筛查(非医院门诊)——技术人员携带眼底相机到农村筛查点 |
§2.5 临床意义
DR 是可预防性失明中最可预防的疾病之一——早期发现、及时激光治疗可将严重视力损失风险降低 95%。但在印度农村,糖尿病患者往往无法获得定期眼科检查:眼科医生缺口超过 10 万人,农村地区 70% 人口缺乏专科医疗服务。APTOS 2019 数据集直接服务于解决这一公共卫生挑战——Aravind 眼科医院的模式是技术人员到农村筛查点拍摄眼底照片,AI 系统自动分级并在数分钟内返回结果,仅将可转诊患者转诊至眼科专科。这种"AI 赋能农村筛查"模式已被证明可行:ARDA 系统在 60 万患者筛查中对重度 NPDR/PDR 的敏感度达 97.0%、特异度 96.4%、漏诊率 0%。
§2.6 金标准 / 参考标准
| 数据划分 | 标注方式 | 标注者 | 金标准性质 |
|---|---|---|---|
| 训练集(3,662 张) | 人工分级 | Aravind 眼科医院训练有素的眼科医生 | 参考标准(单标注者,无共识/裁决) |
| 公开测试集(1,928 张) | 无标签 | — | — |
| 私有测试集(~13,000 张) | 人工分级(标签未公开) | 眼科医生 | 参考标准(用于竞赛最终评分) |
标注质量控制说明:APTOS 2019 采用单标注者协议,未报告标注者间一致性(inter-rater agreement)。竞赛论坛中参赛者发现 268 张重复图像,其中 64 张标注不一致(如同一图像分别标为 3 级和 4 级),表明标注噪声显著。一项独立研究(Shafqat et al., 2021)估计约 25% 的图像不可分级。这是 APTOS 数据集的核心局限,也是其"真实世界噪声"特性的体现。
§3 数据集规格
§3.0 版本抉择矩阵
| 你的需求 | 推荐版本 | 大小 | 理由 |
|---|---|---|---|
| 竞赛复现 / 标准基准 | 竞赛公开版(train + public test) | ~10.22 GB | 唯一官方版本,3,662 张标注训练图像 + 1,928 张公开测试图像 |
| 快速原型 / 资源有限 | 社区预处理版(224×224 resize) | ~250 MB | Kaggle 上由社区上传的 224×224 缩放版,适合快速实验 |
| HuggingFace 集成 | HF bumbledeep/aptos | ~250 MB | 仅含训练集 3,662 张,已 resize 为 224×224,Parquet 格式 |
| 竞赛获奖方案复现 | 竞赛版 + EyePACS 2015 预训练 | ~10.22 GB + 35 GB | 几乎所有获奖方案均先用 Kaggle DR 2015(EyePACS)预训练再用 APTOS 微调 |
§3.1 模态详细说明
APTOS 2019 包含彩色眼底照片(color fundus photographs),通过眼底相机(fundus camera)拍摄视网膜后极部,捕捉视盘、黄斑、血管弓及周围视网膜区域。眼底照片是 DR 筛查的金标准成像方式——非侵入性、快速(数秒/眼)、成本低、可由技术人员操作。图像以黄斑为中心(macula-centered),45° 视场角。由于来自多个筛查点、多种相机型号,图像在分辨率、色彩、亮度、对比度方面高度异质。
§3.2 样本数量统计
| 数据子集 | 图像数量 | 是否标注 | 说明 |
|---|---|---|---|
| 训练集 | 3,662 | ✅ 有标签(0-4) | 公开可下载 |
| 公开测试集 | 1,928 | ❌ 无标签 | 公开可下载,用于竞赛提交格式参考 |
| 私有测试集 | ~13,000 | ✅ 有标签(不公开) | 仅用于竞赛最终评分,标签从未公开 |
| 合计 | ~18,590 | — | 竞赛总数据量约 10.22 GB(公开部分) |
§3.3 数据格式
| 文件 | 格式 | 说明 |
|---|---|---|
| train_images/ | PNG | 3,662 张彩色眼底照片,分辨率 474×358 至 4288×2848 |
| test_images/ | PNG | 1,928 张公开测试图像(无标签) |
| train.csv | CSV | 两列:id_code(12 字符 hex)、diagnosis(0-4 整数) |
| test.csv | CSV | 一列:id_code |
| sample_submission.csv | CSV | 提交格式参考 |
§3.4 存储大小
| 版本 | 压缩后大小 | 解压后大小 |
|---|---|---|
| 竞赛公开版(train.zip + test.zip) | ~10.22 GB | ~10.22 GB(PNG 已压缩) |
| 社区 224×224 缩放版 | ~250 MB | ~250 MB |
§3.5 标注方式
┌─────────────────────────────────────────────────────────────────┐
│ APTOS 2019 标注流程 │
│ │
│ [Aravind 技术员] │
│ │ │
│ ▼ │
│ 农村社区筛查点拍摄 │
│ (多种眼底相机 / 不同环境 / 长时间跨度) │
│ │ │
│ ▼ │
│ 眼底照片采集 (PNG, 异质分辨率) │
│ │ │
│ ▼ │
│ [眼科医生] │
│ │ │
│ ▼ │
│ 按 ICDRSS 标准分级 (0-4) │
│ • 0 = 无 DR (无微动脉瘤) │
│ • 1 = 轻度 (仅微动脉瘤) │
│ • 2 = 中度 (微动脉瘤 + 出血/硬性渗出/棉绒斑) │
│ • 3 = 重度 (满足 4 项中任 1 项:广泛出血/微动脉瘤/静脉串珠/IRMA) │
│ • 4 = 增殖性 (新生血管/玻璃体出血/视网膜前出血) │
│ │ │
│ ▼ │
│ 单标注者 → 无共识/裁决 → 已知标注噪声 │
│ (268 张重复图像中 64 张标注冲突) │
│ │ │
│ ▼ │
│ train.csv (id_code, diagnosis) │
└─────────────────────────────────────────────────────────────────┘
§3.6 图像质量分布
| 质量维度 | 特征 | 影响占比(估计) |
|---|---|---|
| 分辨率异质 | 474×358 至 4288×2848(9 倍差异) | 100%(全部图像) |
| 暗边/黑框 | 圆形视场外的黑色背景 | 大部分图像 |
| 对焦不良 | 模糊/失焦 | ~15-20% |
| 曝光问题 | 过暗/过亮 | ~10-15% |
| 伪影/噪声 | 镜头灰尘、运动伪影 | ~10% |
| 不可分级 | 质量过差无法诊断 | ~25%(参考 EyePACS 研究) |
§3.7 类别分布
| 等级 | 诊断 | 图像数 | 占比 | 不可转诊/可转诊 |
|---|---|---|---|---|
| 0 | 无 DR | 1,805 | 49.3% | 不可转诊 |
| 1 | 轻度 DR | 370 | 10.1% | 不可转诊 |
| 2 | 中度 DR | 999 | 27.3% | 可转诊 |
| 3 | 重度 DR | 193 | 5.3% | 可转诊 |
| 4 | 增殖性 DR | 295 | 8.1% | 可转诊 |
| — | 合计 | 3,662 | 100% | — |
不平衡分析:No DR(1,805)vs Severe DR(193)比例为 9.3:1。不可转诊(0-1)占 59.4%,可转诊(2-4)占 40.6%。这种分布反映了真实筛查场景中大部分受筛查者无 DR 或仅有轻度的流行病学特征。
§3.8 数据集来源与溯源链
Aravind 眼科医院 (泰米尔纳德邦, 印度)
│
├── 农村社区筛查点 (多地点, 多相机, 多操作员)
│ │
│ └── 眼底照片采集 → 原始 DICOM → 转存 PNG
│
├── Aravind 眼科医生标注 (ICDRSS 5 级)
│
├── Kaggle 竞赛平台发布 (2019-06-28)
│ │
│ ├── train.zip (3,662 张 + labels)
│ ├── test.zip (1,928 张, 无标签)
│ └── 私有测试集 (~13,000 张, 标签不公开)
│
└── 社区衍生
├── 224×224 resize 版 (Kaggle Dataset)
├── HuggingFace bumbledeep/aptos
└── APTOS-C 清理版 (去重去噪, 社区维护)
§3.9 竞赛评测指标
APTOS 2019 竞赛采用**二次加权 Kappa(Quadratic Weighted Kappa, QWK)**作为评测指标:
-
QWK 衡量两个评分者(人类标注 vs 模型预测)之间的一致性
-
取值范围 [-1, 1]:0 = 随机一致,1 = 完全一致,<0 = 差于随机
-
使用二次权重:$w_{ij} = \frac{(i-j)^2}{(k-1)^2}$,对相邻级别的轻微不一致给予小惩罚,对跨级别的严重不一致给予大惩罚
-
适合有序分类(ordinal classification)任务——DR 分级 0-4 有明确的严重程度排序
§4 数据结构详解
§4.1 目录结构
aptos2019-blindness-detection/
├── train.csv # 训练标签 (id_code, diagnosis)
├── test.csv # 测试图像 ID (id_code)
├── sample_submission.csv # 提交格式参考
├── train_images/ # 训练图像目录
│ ├── 000c1434d8d7.png # 12 字符 hex 命名
│ ├── 001639a390f0.png
│ ├── ...
│ └── ffd3f4de1c4c.png # 共 3,662 张
├── test_images/ # 公开测试图像目录
│ ├── 4e4dcca36ceb4.png
│ ├── ...
│ └── e7d2c2c3b30f.png # 共 1,928 张
└── [私有测试集] # ~13,000 张, 不公开
§4.2 DAIMS 标准化数据字典
| 字段名 | 类型 | 描述 | 示例值 | 必填 |
|---|---|---|---|---|
id_code |
string (12 char hex) | 图像唯一标识符 | 000c1434d8d7 |
✅ |
diagnosis |
integer (0-4) | DR 严重程度分级(ICDRSS) | 2 |
✅ |
image |
PNG | 眼底照片(异质分辨率) | 000c1434d8d7.png |
✅ |
image_width |
integer | 图像宽度(像素) | 2134 | — |
image_height |
integer | 图像高度(像素) | 1600 | — |
laterality |
enum | 左眼/右眼(未公开) | — | — |
patient_id |
string | 患者标识符(未公开) | — | — |
age |
float | 患者年龄(未公开) | — | — |
sex |
enum | 患者性别(未公开) | — | — |
camera_model |
string | 眼底相机型号(未公开) | — | — |
diabetes_duration |
float | 糖尿病病程(未公开) | — | — |
hba1c |
float | 糖化血红蛋白(未公开) | — | — |
说明:APTOS 2019 仅公开
id_code、diagnosis和image三个字段。所有患者级元数据(年龄、性别、病史、相机型号等)均未公开——这是竞赛数据集的常见做法,但也意味着无法进行人口统计学公平性分析。
§4.3 已知数据质量问题
| 问题类型 | 详情 | 影响 | 社区处理建议 |
|---|---|---|---|
| 重复图像 | 268 张训练集内重复图像 | 模型可能过拟合重复样本 | 去重或保留其一 |
| 冲突标签 | 64 张重复图像标注不一致(如同一图分别标为 3 和 4) | 标签噪声直接损害训练 | 去除冲突样本或取较严重级别 |
| 训练-测试泄漏 | 训练集和测试集之间存在重复图像 | 测试集不再是真正未见数据 | 竞赛方未修正 |
| 不可分级图像 | ~25% 图像因质量问题无法诊断 | 模型被迫对不可分级图像进行预测 | 预处理阶段过滤或训练质量评估模块 |
| 单标注者 | 无标注者间一致性报告 | 无法量化标签可信度 | 无法通过后处理修复 |
| 测试标签未公开 | 竞赛结束后未释放私有测试集标签 | 无法进行独立外部验证 | 使用 train.csv 自行划分 |
§5 数据划分与使用建议
§5.1 官方划分方案
| 划分 | 图像数 | 标签 | 用途 |
|---|---|---|---|
| 训练集 | 3,662 | ✅ 公开 | 模型训练 |
| 公开测试集 | 1,928 | ❌ 无标签 | 竞赛提交格式参考 |
| 私有测试集 | ~13,000 | ✅ 不公开 | 竞赛最终评分 |
关键限制:私有测试集标签在竞赛结束后从未公开,研究者无法复现竞赛排行榜成绩。实际使用中,几乎所有研究都从 3,662 张训练图像中自行划分训练/验证/测试集。
§5.2 推荐划分策略
┌─────────────────────────────────────────────────────────────┐
│ 推荐划分:分层 5-Fold 交叉验证 │
│ │
│ 3,662 张训练图像 │
│ │ │
│ ▼ │
│ StratifiedKFold(n_splits=5, shuffle=True, random_state=42) │
│ │ │
│ ├── Fold 0: 2,929 train / 733 val │
│ ├── Fold 1: 2,929 train / 733 val │
│ ├── Fold 2: 2,929 train / 733 val │
│ ├── Fold 3: 2,929 train / 733 val │
│ └── Fold 4: 2,929 train / 733 val │
│ │
│ 分层依据:diagnosis (0-4) 保持原始比例 │
│ 评估指标:QWK (quadratic weighted kappa) │
│ 阈值优化:在验证集上搜索最优连续值→离散值的截断阈值 │
└─────────────────────────────────────────────────────────────┘
§5.3 自定义划分方案
| 划分策略 | 训练 | 验证 | 测试 | 适用场景 |
|---|---|---|---|---|
| 80/10/10 分层划分 | 2,929 | 366 | 367 | 快速原型 |
| 5-Fold 分层交叉验证 | 2,929 | 733 | — | 稳健评估(推荐) |
| 去重后 80/10/10 | ~2,700 | ~330 | ~330 | 去除 268 张重复后划分 |
| 去重去噪后 5-Fold | ~2,500 | ~620 | — | 去除重复 + 冲突标签后 |
§5.4 数据泄漏风险
| 风险类型 | 详情 | 缓解措施 |
|---|---|---|
| 图像级重复 | 268 张训练集内重复 | 去重后再划分 |
| 患者级泄漏 | 同一患者双眼可能分别进入训练/验证集 | 无法验证(无 patient_id),但应注意此风险 |
| 训练-测试重复 | 竞赛方确认训练集和测试集有重复 | 使用公开数据时无法避免 |
| EyePACS 预训练泄漏 | 多数获奖方案用 EyePACS 预训练,但 EyePACS 与 APTOS 无图像重叠 | 无需处理 |
§5.5 外部验证数据集
| 数据集 | 地域 | 规模 | 用途 |
|---|---|---|---|
| EyePACS (Kaggle DR 2015) | 美国 | 88,702 | 预训练 + 跨域验证 |
| MESSIDOR-2 | 法国 | 1,748 | 外部验证 |
| IDRiD | 印度 | 516 | 同地域验证(含病灶标注) |
| DDR | 中国 | 13,673 | 跨地域验证 |
| RFMiD | 法国 | 3,200 | 多疾病验证 |
§6 AI 就绪指南
§6.0 云端快速启动
<details>
<summary>📦 快速启动代码(点击展开)</summary>
"""
APTOS 2019 快速启动
依赖: pip install kaggle opencv-python torch torchvision scikit-learn
"""
import os
import cv2
import numpy as np
import pandas as pd
from pathlib import Path
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import cohen_kappa_score
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, models
# 1. 下载数据(需 Kaggle API Token)
# kaggle competitions download -c aptos2019-blindness-detection
# unzip aptos2019-blindness-detection.zip -d aptos_data/
DATA_DIR = Path("aptos_data")
TRAIN_CSV = DATA_DIR / "train.csv"
TRAIN_IMG_DIR = DATA_DIR / "train_images"
# 2. 加载标签
df = pd.read_csv(TRAIN_CSV)
print(f"训练集: {len(df)} 张图像")
print(f"类别分布:\n{df[''''''''''''''''''''''''''''''''diagnosis''''''''''''''''''''''''''''''''].value_counts().sort_index()}")
# 3. 去重(可选,基于已知的 268 张重复图像列表)
# 参考: https://www.kaggle.com/maxwell110/duplicated-list-csv-file
# 4. 分层 5-Fold 划分
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
df[''''''''''''''''''''''''''''''''fold''''''''''''''''''''''''''''''''] = -1
for fold, (_, val_idx) in enumerate(skf.split(df, df[''''''''''''''''''''''''''''''''diagnosis''''''''''''''''''''''''''''''''])):
df.loc[val_idx, ''''''''''''''''''''''''''''''''fold''''''''''''''''''''''''''''''''] = fold
# 5. 图像预处理:圆形裁剪 + Ben Graham 增强
def crop_black_border(img, tol=7):
"""裁剪眼底照片的黑色边框"""
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
mask = gray > tol
if mask.sum() == 0:
return img
coords = np.argwhere(mask)
y0, x0 = coords.min(axis=0)
y1, x1 = coords.max(axis=0)
return img[y0:y1, x0:x1]
def ben_graham_preprocess(img, sigma=10):
"""Ben Graham 增强:减去高斯模糊"""
return cv2.addWeighted(img, 4, cv2.GaussianBlur(img, (0, 0), sigma), -4, 128)
def load_and_preprocess(img_path, target_size=384):
img = cv2.imread(str(img_path))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = crop_black_border(img)
img = ben_graham_preprocess(img)
img = cv2.resize(img, (target_size, target_size))
return img
# 6. PyTorch Dataset
class APTOSDataset(Dataset):
def __init__(self, df, img_dir, transform=None, target_size=384):
self.df = df.reset_index(drop=True)
self.img_dir = Path(img_dir)
self.transform = transform
self.target_size = target_size
def __len__(self):
return len(self.df)
def __getitem__(self, idx):
row = self.df.iloc[idx]
img_path = self.img_dir / f"{row[''''''''''''''''''''''''''''''''id_code'''''''''''''''''''''''''''''''']}.png"
img = load_and_preprocess(img_path, self.target_size)
if self.transform:
augmented = self.transform(image=img)
img = augmented[''''''''''''''''''''''''''''''''image'''''''''''''''''''''''''''''''']
img = torch.from_numpy(img).permute(2, 0, 1).float() / 255.0
img = transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)(img)
label = int(row[''''''''''''''''''''''''''''''''diagnosis''''''''''''''''''''''''''''''''])
return img, label
# 7. 训练一个 EfficientNet-B4 基线
def train_one_fold(df, fold, device=''''''''''''''''''''''''''''''''cuda''''''''''''''''''''''''''''''''):
train_df = df[df[''''''''''''''''''''''''''''''''fold''''''''''''''''''''''''''''''''] != fold].reset_index(drop=True)
val_df = df[df[''''''''''''''''''''''''''''''''fold''''''''''''''''''''''''''''''''] == fold].reset_index(drop=True)
train_ds = APTOSDataset(train_df, TRAIN_IMG_DIR)
val_ds = APTOSDataset(val_df, TRAIN_IMG_DIR)
train_loader = DataLoader(train_ds, batch_size=32, shuffle=True, num_workers=4)
val_loader = DataLoader(val_ds, batch_size=64, shuffle=False, num_workers=4)
model = models.efficientnet_b4(pretrained=True)
model.classifier = torch.nn.Linear(model.classifier[1].in_features, 1) # 回归输出
model = model.to(device)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-2)
scheduler = torch.optim.lr_scheduler.OneCycleLR(
optimizer, max_lr=1e-3, epochs=20, steps_per_epoch=len(train_loader)
)
criterion = torch.nn.SmoothL1Loss() # 回归损失
best_kappa = 0
for epoch in range(20):
model.train()
for images, labels in train_loader:
images, labels = images.to(device), labels.float().to(device)
optimizer.zero_grad()
outputs = model(images).squeeze()
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
scheduler.step()
# 验证
model.eval()
preds, truths = [], []
with torch.no_grad():
for images, labels in val_loader:
images = images.to(device)
outputs = model(images).squeeze().cpu().numpy()
preds.extend(outputs)
truths.extend(labels.numpy())
# 优化阈值
preds = np.array(preds)
truths = np.array(truths)
# 简单四舍五入到 0-4
preds_clipped = np.clip(np.round(preds), 0, 4).astype(int)
kappa = cohen_kappa_score(truths, preds_clipped, weights=''''''''''''''''''''''''''''''''quadratic'''''''''''''''''''''''''''''''')
print(f"Epoch {epoch+1}: QWK = {kappa:.4f}")
if kappa > best_kappa:
best_kappa = kappa
torch.save(model.state_dict(), f''''''''''''''''''''''''''''''''aptos_fold{fold}_best.pth'''''''''''''''''''''''''''''''')
print(f"Fold {fold} Best QWK: {best_kappa:.4f}")
return best_kappa
# 运行 5-Fold 交叉验证
# device = ''''''''''''''''''''''''''''''''cuda'''''''''''''''''''''''''''''''' if torch.cuda.is_available() else ''''''''''''''''''''''''''''''''cpu''''''''''''''''''''''''''''''''
# kappas = [train_one_fold(df, fold, device) for fold in range(5)]
# print(f"5-Fold Mean QWK: {np.mean(kappas):.4f} ± {np.std(kappas):.4f}")
</details>
§6.1 预处理 Pipeline
<details>
<summary>🔧 预处理详解(点击展开)</summary>
"""
APTOS 2019 预处理 Pipeline
竞赛获奖方案通用预处理策略
"""
import cv2
import numpy as np
class APTOSPreprocessor:
"""APTOS 2019 图像预处理管道"""
def __init__(self, target_size=384, ben_graham_sigma=10,
crop_black=True, circle_crop=True):
self.target_size = target_size
self.ben_graham_sigma = ben_graham_sigma
self.crop_black = crop_black
self.circle_crop = circle_crop
def __call__(self, img):
# Step 1: 裁剪黑色边框
if self.crop_black:
img = self._crop_black_border(img)
# Step 2: 圆形裁剪(去除四角黑色区域)
if self.circle_crop:
img = self._circle_crop(img)
# Step 3: Ben Graham 增强(提高病灶对比度)
img = self._ben_graham(img)
# Step 4: Resize 到目标尺寸
img = cv2.resize(img, (self.target_size, self.target_size))
return img
def _crop_black_border(self, img, tol=7):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
mask = gray > tol
if mask.sum() == 0:
return img
coords = np.argwhere(mask)
y0, x0 = coords.min(axis=0)
y1, x1 = coords.max(axis=0)
return img[y0:y1, x0:x1]
def _circle_crop(self, img):
height, width = img.shape[:2]
center = (width // 2, height // 2)
radius = min(center[0], center[1])
mask = np.zeros((height, width), dtype=np.uint8)
cv2.circle(mask, center, radius, 255, -1)
img = cv2.bitwise_and(img, img, mask=mask)
return img
def _ben_graham(self, img):
"""Ben Graham (Kaggle DR 2015 冠军) 增强:
output = 4 * input - 4 * GaussianBlur(input) + 128
增强微血管、微动脉瘤等细微病灶的对比度
"""
return cv2.addWeighted(
img, 4,
cv2.GaussianBlur(img, (0, 0), self.ben_graham_sigma),
-4, 128
)
# 数据增强策略(竞赛获奖方案通用)
TRAIN_AUGMENTATION = {
''''''''''''''''''''''''''''''''flip'''''''''''''''''''''''''''''''': {''''''''''''''''''''''''''''''''p'''''''''''''''''''''''''''''''': 0.5}, # 水平翻转
''''''''''''''''''''''''''''''''flip_vert'''''''''''''''''''''''''''''''': {''''''''''''''''''''''''''''''''p'''''''''''''''''''''''''''''''': 0.5}, # 垂直翻转
''''''''''''''''''''''''''''''''rotate'''''''''''''''''''''''''''''''': {''''''''''''''''''''''''''''''''limit'''''''''''''''''''''''''''''''': 360, ''''''''''''''''''''''''''''''''p'''''''''''''''''''''''''''''''': 0.7}, # 任意角度旋转
''''''''''''''''''''''''''''''''brightness'''''''''''''''''''''''''''''''': {''''''''''''''''''''''''''''''''limit'''''''''''''''''''''''''''''''': 0.2, ''''''''''''''''''''''''''''''''p'''''''''''''''''''''''''''''''': 0.5},
''''''''''''''''''''''''''''''''contrast'''''''''''''''''''''''''''''''': {''''''''''''''''''''''''''''''''limit'''''''''''''''''''''''''''''''': 0.2, ''''''''''''''''''''''''''''''''p'''''''''''''''''''''''''''''''': 0.5},
''''''''''''''''''''''''''''''''zoom_crop'''''''''''''''''''''''''''''''': {''''''''''''''''''''''''''''''''scale'''''''''''''''''''''''''''''''': (1.0, 1.4), ''''''''''''''''''''''''''''''''p'''''''''''''''''''''''''''''''': 0.5}, # 中心裁剪缩放
}
# 推荐输入尺寸
RECOMMENDED_SIZES = {
''''''''''''''''''''''''''''''''EfficientNet-B0'''''''''''''''''''''''''''''''': 224,
''''''''''''''''''''''''''''''''EfficientNet-B3'''''''''''''''''''''''''''''''': 300,
''''''''''''''''''''''''''''''''EfficientNet-B4'''''''''''''''''''''''''''''''': 380,
''''''''''''''''''''''''''''''''EfficientNet-B5'''''''''''''''''''''''''''''''': 456,
''''''''''''''''''''''''''''''''EfficientNet-B6'''''''''''''''''''''''''''''''': 528,
''''''''''''''''''''''''''''''''EfficientNet-B7'''''''''''''''''''''''''''''''': 600,
}
</details>
§6.2 PyTorch 训练模板
<details>
<summary>⚡ 训练模板 + 阈值优化(点击展开)</summary>
"""
APTOS 2019 训练模板
关键设计:回归输出 + 阈值优化(竞赛获奖方案标准做法)
"""
import numpy as np
from scipy.optimize import minimize
from sklearn.metrics import cohen_kappa_score
def optimize_thresholds(preds_continuous, labels, n_classes=5):
"""
在验证集上搜索最优连续值→离散值的截断阈值
竞赛获奖方案的关键技巧之一
"""
def loss(thresholds):
thresholds = sorted(thresholds)
discrete = np.digitize(preds_continuous, thresholds)
return -cohen_kappa_score(labels, discrete, weights=''''''''''''''''''''''''''''''''quadratic'''''''''''''''''''''''''''''''')
# 初始阈值 [0.5, 1.5, 2.5, 3.5]
init = [0.5, 1.5, 2.5, 3.5]
result = minimize(loss, init, method=''''''''''''''''''''''''''''''''Nelder-Mead'''''''''''''''''''''''''''''''')
return sorted(result.x)
def predict_with_thresholds(preds_continuous, thresholds):
"""使用优化后的阈值将连续预测转为离散分级"""
return np.digitize(preds_continuous, thresholds)
# 完整训练循环(带阈值优化)
class APTOSTrainer:
def __init__(self, model, device, lr=1e-3, wd=1e-2):
self.model = model.to(device)
self.device = device
self.criterion = torch.nn.SmoothL1Loss() # 回归损失
self.optimizer = torch.optim.AdamW(
model.parameters(), lr=lr, weight_decay=wd
)
def train_epoch(self, train_loader):
self.model.train()
total_loss = 0
for images, labels in train_loader:
images = images.to(self.device)
labels = labels.float().to(self.device)
self.optimizer.zero_grad()
outputs = self.model(images).squeeze()
loss = self.criterion(outputs, labels)
loss.backward()
self.optimizer.step()
total_loss += loss.item()
return total_loss / len(train_loader)
def validate(self, val_loader):
self.model.eval()
preds, labels = [], []
with torch.no_grad():
for images, targets in val_loader:
images = images.to(self.device)
outputs = self.model(images).squeeze().cpu().numpy()
preds.extend(outputs)
labels.extend(targets.numpy())
preds = np.array(preds)
labels = np.array(labels)
# 优化阈值
thresholds = optimize_thresholds(preds, labels)
discrete_preds = predict_with_thresholds(preds, thresholds)
kappa = cohen_kappa_score(labels, discrete_preds, weights=''''''''''''''''''''''''''''''''quadratic'''''''''''''''''''''''''''''''')
return kappa, thresholds
# 关键训练策略(来自竞赛获奖方案):
# 1. 用 EyePACS 2015 数据预训练,再用 APTOS 微调
# 2. 回归输出(1 个神经元)而非分类输出(5 个神经元)
# 3. SmoothL1Loss 而非 CrossEntropy
# 4. OneCycleLR 学习率调度
# 5. 5-Fold 交叉验证 + 集成
# 6. 阈值优化在验证集上进行
# 7. TTA (Test-Time Augmentation): 8 方向二面体增强
# 8. 伪标签:用高置信度预测的测试集标签扩充训练集
</details>
§6.3 坑点与解决方案
| # | 坑点 | 影响 | 解决方案 |
|---|---|---|---|
| 1 | 268 张重复图像 + 64 张冲突标签 | 过拟合 + 标签噪声 | 预处理阶段去重,冲突标签取较严重级别或删除 |
| 2 | 极端类不平衡(9.3:1) | 少数类(Severe DR)召回率低 | 加权采样 / Focal Loss / 过采样少数类 / 回归输出 |
| 3 | 异质分辨率(9 倍差异) | 直接 resize 丢失细节 | 先裁剪黑色边框再 resize,或使用多尺度训练 |
| 4 | ~25% 不可分级图像 | 模型对噪声图像产生高置信度错误预测 | 训练质量评估模块先过滤不可分级图像 |
| 5 | 训练集过小(3,662 张) | 大模型容易过拟合 | 用 EyePACS 2015(88K 张)预训练 + 强数据增强 |
| 6 | 测试集标签不公开 | 无法复现竞赛排行榜 | 从训练集自行划分,报告 5-Fold CV |
| 7 | 分类 vs 回归选择 | 5 分类 softmax 忽略有序性 | 用回归输出(1 神经元)+ 阈值优化,竞赛获奖方案的标准做法 |
| 8 | 竞赛规则禁止再分发 | 无法在 HuggingFace 等平台公开完整数据 | 社区有 resize 版和 HF 子集,但需注意许可 |
§6.4 数据增强策略
| 策略 | 推荐参数 | 理由 |
|---|---|---|
| 水平翻转 | p=0.5 | 眼底图像左右对称性合理 |
| 垂直翻转 | p=0.5 | 竞赛获奖方案验证有效 |
| 任意角度旋转 | limit=360, p=0.7 | 眼底图像无固定方向 |
| 亮度调整 | limit=0.2, p=0.5 | 模拟不同相机/环境曝光 |
| 对比度调整 | limit=0.2, p=0.5 | 模拟不同相机色彩响应 |
| 中心裁剪缩放 | scale=(1.0, 1.4), p=0.5 | 模拟不同视场和距离 |
| Cutout | num_holes=8, p=0.5 | 正则化,防止过拟合 |
§6.5 模型推荐
| 模型 | 输入尺寸 | 参数量 | 推荐场景 |
|---|---|---|---|
| EfficientNet-B0 | 224 | 5.3M | 快速原型 / 资源受限 |
| EfficientNet-B3 | 300 | 12M | 平衡精度与速度 |
| EfficientNet-B4 | 380 | 19M | 竞赛获奖方案首选 |
| EfficientNet-B5 | 456 | 30M | 高精度(需更大 GPU) |
| EfficientNet-B7 | 600 | 66M | 最高精度(竞赛集成组件) |
| ResNet-50 | 384 | 25M | 经典基线 |
| Vision Transformer | 384 | 86M | 2025 年 SOTA(二分类 99.3%) |
§6.6 计算需求
| 配置 | 最小要求 | 推荐配置 |
|---|---|---|
| GPU | 8GB VRAM(EfficientNet-B0, 224px) | 16GB+ VRAM(EfficientNet-B4, 380px) |
| RAM | 16GB | 32GB+ |
| 存储 | 15GB(数据 + 模型) | 50GB+(含预训练数据) |
| 训练时间 | ~2 小时/fold(B0, 224px, 20 epochs) | ~6 小时/fold(B4, 380px, 20 epochs) |
§6.7 评估指标代码
"""
APTOS 2019 评估指标
"""
import numpy as np
from sklearn.metrics import cohen_kappa_score, classification_report, confusion_matrix
def quadratic_weighted_kappa(y_true, y_pred):
"""竞赛官方评测指标"""
return cohen_kappa_score(y_true, y_pred, weights=''''''''''''''''''''''''''''''''quadratic'''''''''''''''''''''''''''''''')
def evaluate_aptos(y_true, y_pred, class_names=None):
"""完整评估报告"""
if class_names is None:
class_names = [''''''''''''''''''''''''''''''''No DR'''''''''''''''''''''''''''''''', ''''''''''''''''''''''''''''''''Mild'''''''''''''''''''''''''''''''', ''''''''''''''''''''''''''''''''Moderate'''''''''''''''''''''''''''''''', ''''''''''''''''''''''''''''''''Severe'''''''''''''''''''''''''''''''', ''''''''''''''''''''''''''''''''Proliferative'''''''''''''''''''''''''''''''']
print(f"QWK: {quadratic_weighted_kappa(y_true, y_pred):.4f}")
print(f"\n分类报告:")
print(classification_report(y_true, y_pred, target_names=class_names))
print(f"\n混淆矩阵:")
print(confusion_matrix(y_true, y_pred))
# 按类别计算准确率
cm = confusion_matrix(y_true, y_pred)
per_class_acc = cm.diagonal() / cm.sum(axis=1)
for i, name in enumerate(class_names):
print(f" {name}: {per_class_acc[i]:.2%}")
def binary_referable_dr(y_true, y_pred):
"""二分类可转诊 DR 评估(0-1 vs 2-4)"""
y_true_bin = (y_true >= 2).astype(int)
y_pred_bin = (y_pred >= 2).astype(int)
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
print(f"可转诊 DR 检测:")
print(f" Accuracy: {accuracy_score(y_true_bin, y_pred_bin):.4f}")
print(f" Precision: {precision_score(y_true_bin, y_pred_bin):.4f}")
print(f" Recall: {recall_score(y_true_bin, y_pred_bin):.4f}")
print(f" F1: {f1_score(y_true_bin, y_pred_bin):.4f}")
§7 质量评估与局限性
§7.1 已知偏倚
| # | 偏倚类型 | 详情 | 影响 |
|---|---|---|---|
| 1 | 选择偏倚 | 数据来自 Aravind 农村筛查项目,非随机抽样 | 模型可能不适用于城市或非印度人群 |
| 2 | 地域偏倚 | 仅印度泰米尔纳德邦农村 | 跨地域部署需域迁移 |
| 3 | 类别不平衡偏倚 | No DR 49.3% vs Severe DR 5.3% | 模型倾向于预测 No DR,少数类召回率低 |
| 4 | 标注噪声偏倚 | 单标注者 + 64 张冲突标签 | 标签可信度受限,无法量化标注者间一致性 |
| 5 | 图像质量偏倚 | ~25% 不可分级图像 | 模型可能对不可分级图像产生虚假高置信度预测 |
| 6 | 设备异质性偏倚 | 多种相机型号,分辨率 9 倍差异 | 模型可能对特定相机型号/分辨率偏倚 |
| 7 | 无人口统计元数据 | 年龄、性别、糖尿病病程等未公开 | 无法进行公平性审计 |
§7.2 标注质量评估
| 维度 | 评估 | 说明 |
|---|---|---|
| 标注者数量 | 单标注者 | 无共识机制,无标注者间一致性 |
| 标注者资质 | Aravind 眼科医院训练有素的眼科医生 | 资质可信 |
| 重复图像冲突 | 64/268 张冲突(23.9%) | 标注噪声显著 |
| 不可分级图像 | ~25%(估计) | 未被过滤或标注 |
| 独立质量评估 | 无 | 无第三方质量审计 |
§7.3 泛化能力评估
| 验证维度 | 评估 | 说明 |
|---|---|---|
| 跨地域泛化 | ❓ 未系统评估 | 印度→美国/中国/欧洲需独立验证 |
| 跨相机泛化 | ❓ 无法评估 | 相机型号未公开 |
| 跨人群泛化 | ❓ 无法评估 | 人口统计数据未公开 |
| 时间稳定性 | ❓ 无法评估 | 采集时间未公开 |
| 二分类 vs 五分类 | 二分类表现远好于五分类 | 五分类是主要挑战 |
§7.4 技术局限性
| 局限性 | 详情 | 缓解方向 |
|---|---|---|
| 训练集过小 | 3,662 张(vs EyePACS 88K) | 迁移学习 / 数据增强 / 半监督 |
| 无病灶级标注 | 仅图像级分级标签 | 结合 IDRiD 像素级标注数据集 |
| 无患者级信息 | 无法按患者分组 | 无法避免患者级泄漏 |
| 测试标签不公开 | 无法独立复现竞赛 | 使用 train.csv 自行划分 |
| 许可证限制 | 仅限非商业学术研究 | 商业化需另获授权 |
§7.5 DAIMS 24 项数据就绪度评估表
| # | DAIMS 评估项 | 状态 | 说明 |
|---|---|---|---|
| 1 | 数据集动机与目的 | ✅ | DR 自动筛查,服务印度农村公共卫生 |
| 2 | 数据集组成 | ✅ | 3,662 张训练 + 1,928 公开测试 + ~13K 私有测试 |
| 3 | 数据采集协议 | ⚠️ | 简述为"多诊所多相机长时间采集",具体协议未公开 |
| 4 | 标注者资质 | ⚠️ | “训练有素的眼科医生”,具体资质/数量未公开 |
| 5 | 标注者间一致性 | ❌ | 未报告,单标注者协议 |
| 6 | 标注工具与流程 | ⚠️ | ICDRSS 标准分级,具体工具/流程未描述 |
| 7 | 标注质量控制 | ❌ | 无 QC 流程,268 张重复中 64 张冲突 |
| 8 | 数据清洗 | ❌ | 已知问题未修正 |
| 9 | 去标识化 | ✅ | 图像去标识化,无患者标识符 |
| 10 | 伦理审查 | ⚠️ | 未公开 IRB/伦理批准信息 |
| 11 | 数据格式 | ✅ | PNG(图像)+ CSV(标签),标准格式 |
| 12 | 元数据完整性 | ❌ | 仅 id_code + diagnosis,无人口统计/临床元数据 |
| 13 | 数据划分 | ⚠️ | 竞赛官方 train/test 划分,但测试标签不公开 |
| 14 | 类别分布文档 | ✅ | 五级分布完整公开 |
| 15 | 已知偏差文档 | ✅ | 竞赛描述明确提及图像噪声和标注噪声 |
| 16 | 数据版本管理 | ⚠️ | 单一版本,竞赛后未更新 |
| 17 | 许可证 | ⚠️ | 竞赛规则(非商业学术研究),非标准开放许可 |
| 18 | 数据访问 | ✅ | Kaggle 注册后可下载 |
| 19 | 更新频率 | ❌ | 一次性发布,未更新 |
| 20 | 引用与 DOI | ⚠️ | 无独立 DOI,引用 Kaggle 竞赛页面 |
| 21 | 机器可读元数据 | ❌ | 无 Croissant / schema.org 元数据 |
| 22 | 使用案例文档 | ✅ | 竞赛描述明确 DR 自动检测筛查 |
| 23 | 外部验证 | ❌ | 无官方外部验证 |
| 24 | 公平性审计 | ❌ | 无人口统计数据,无法审计 |
DAIMS 评分:10/24(41.7%,⭐⭐⭐ 3/5)
评估总结:APTOS 2019 的核心优势在于真实世界临床噪声代表性和竞赛标准评测,但单标注者无 QC、无患者元数据、已知数据质量问题未修正、许可证限制等因素显著降低了数据就绪度。作为竞赛基准数据集价值极高,但作为独立研究数据集需配合外部数据集(EyePACS 预训练、IDRiD 病灶标注)使用。
§7.6 外部验证矩阵
| 训练数据 | 验证数据 | 地域迁移 | 报告 QWK | 来源 |
|---|---|---|---|---|
| APTOS train (5-Fold CV) | APTOS val | 无 | 0.83-0.93 | 竞赛获奖方案 |
| EyePACS → APTOS | APTOS test | 美国→印度 | 0.80-0.85 | 多篇迁移学习研究 |
| APTOS → MESSIDOR-2 | MESSIDOR-2 | 印度→法国 | 未系统报告 | — |
| APTOS + EyePACS → IDRiD | IDRiD | 印度→印度 | 未系统报告 | — |
| APTOS → DDR | DDR | 印度→中国 | 未系统报告 | — |
§8 基准性能与生态
§8.1 竞赛排行榜(Kaggle APTOS 2019 Blindness Detection)
| 排名 | 团队/方案 | Private LB QWK | 核心方法 |
|---|---|---|---|
| 🥇 1 | Guanshuo Xu | 0.936129 | InceptionNet + ResNet 集成 + 伪标签 + 阈值优化 |
| 🥈 2 | ods.ai Eye of Private LB | 0.934310 | EfficientNet B3/B4/B5 + EyePACS 预训练 + 伪标签 |
| 🥉 3 | — | ~0.934 | — |
| 4 | Best Over Fitting | 0.933720 | EfficientNet B7+B5 平均 + Dihedral TTA |
| 10+ | DrHB (Gold) | 0.927 | EfficientNet-B4 + 5-Fold + 回归 + OneCycleLR |
| — | 典型 Silver | 0.915-0.925 | EfficientNet B3-B5 + 预训练 + TTA |
| — | 典型 Bronze | 0.905-0.915 | EfficientNet B3-B4 + 预训练 |
| — | 中位数 | ~0.80 | 基础 CNN + 少量增强 |
竞赛统计:15,357 名注册者 / 3,507 活跃参赛者 / 2,928 支队伍 / 71,433 次提交 / $50,000 总奖金
§8.2 学术 SOTA 基准
| 方法 | 年份 | 任务 | 指标 | 备注 |
|---|---|---|---|---|
| ViT (Vision Transformer) | 2025 | 二分类 | ACC 99.3%, AUC 0.999 | 计算资源需求高 |
| EfficientNet-B0 + 增强 | 2025 | 二分类 | ACC 98.9%, AUC 99.4% | 轻量高效 |
| EfficientNet-B0 + 增强 | 2025 | 五分类 | ACC 84.6%, AUC 94.1% | 类平衡增强 |
| EfficientNetB3 + SE Block | 2025 | 五分类 | ACC 88.4%, Kappa 0.88 | 通道注意力 |
| Self-paced Progressive | 2025 | 四分类 | AUC 0.9907 | 多尺度渐进训练 |
| 竞赛冠军(Xu) | 2019 | 五分类 | QWK 0.936 | 集成 + 伪标签 + 阈值优化 |
| DenseNet + ResNet 集成 | 2019 | 五分类 | QWK 0.904 | EyePACS 预训练 |
| InceptionV3 | 2019 | 五分类 | ACC 90.9% | ImageNet 预训练 |
§8.3 评测协议
| 协议 | 划分方式 | 评估指标 | 说明 |
|---|---|---|---|
| 竞赛标准 | 3,662 train / ~13K private test | QWK | 私有测试集不公开,无法复现 |
| 5-Fold CV | StratifiedKFold(5) | QWK (mean ± std) | 社区标准做法 |
| 80/10/10 | 分层划分 | QWK + ACC + F1 | 快速评估 |
| 跨域验证 | EyePACS train → APTOS test | QWK | 评估域迁移 |
§8.4 相关数据集生态
| 数据集 | 关系 | 互补价值 |
|---|---|---|
| EyePACS (Kaggle DR 2015) | 预训练数据 | 88K 张大规模预训练,几乎所有 APTOS 获奖方案均使用 |
| IDRiD | 同地域补充 | 印度数据,含病灶级像素标注,516 张 |
| MESSIDOR-2 | 外部验证 | 法国数据,1,748 张,控制环境 |
| DDR | 跨地域验证 | 中国数据,13K 张,含像素级标注 |
| RFMiD | 多疾病扩展 | 法国数据,3,200 张,45 种视网膜疾病 |
| EyePACS (Gulshan JAMA) | 临床部署 | Google/Verily ARDA 的训练数据(128K 张,54 名医生) |
§8.5 生态快照
┌──────────────────┐
│ APTOS 2019 │
│ 3,662 张 (印度) │
└────────┬─────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ EyePACS 2015 │ │ IDRiD │ │ MESSIDOR-2 │
│ 88K (美国) │ │ 516 (印度) │ │ 1,748 (法国) │
│ 预训练来源 │ │ 病灶级标注 │ │ 外部验证 │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└─────────────────┼─────────────────┘
│
▼
┌──────────────────┐
│ Aravind + Google │
│ ARDA 临床部署 │
│ 60 万+患者筛查 │
│ Sens 97%, Spec │
│ 96.4%, 漏诊 0% │
└──────────────────┘
§8.6 社区影响
| 维度 | 数据 |
|---|---|
| Kaggle 参赛者 | 15,357 注册 / 3,507 活跃 |
| 提交次数 | 71,433 |
| 学术引用 | 1,500+(估算,截至 2026-08) |
| 竞赛奖金 | $50,000 |
| 社区预处理版 | 多个 Kaggle Dataset + HuggingFace 版本 |
| 临床部署规模 | 60 万+患者(ARDA @ Aravind) |
| GitHub 相关仓库 | 100+(竞赛方案 + 研究) |
§9 相关资源与引用
§9.1 引用格式
BibTeX:
@misc{aptos2019,
title={APTOS 2019 Blindness Detection},
author={Karthik and Maggie and Sohier Dane},
year={2019},
howpublished={Kaggle Competition},
url={https://kaggle.com/competitions/aptos2019-blindness-detection},
note={Asia Pacific Tele-Ophthalmology Society (APTOS) \& Aravind Eye Hospital}
}
文本引用:
Karthik, Maggie, and Sohier Dane. “APTOS 2019 Blindness Detection.” Kaggle Competition, 2019. https://kaggle.com/competitions/aptos2019-blindness-detection
§9.2 官方资源
§9.3 社区资源
§9.4 相关关键论文
| 论文 | 年份 | 关键贡献 |
|---|---|---|
| Gulshan et al., JAMA | 2016 | Google DR AI 里程碑,使用扩展 EyePACS 训练,Aravind 验证 |
| ARDA 上市后研究, Ophthalmology | 2025 | Aravind 60 万患者临床性能报告(Sens 97%, Spec 96.4%) |
| Ahmed & Bhuiyan, arXiv | 2025 | EfficientNet-B0 二分类 98.9% / 五分类 84.6% |
| Dixit & Jha, Med Eng Phys | 2025 | EfficientNetB3+SE 五分类 88.4% / Kappa 0.88 |
| Al-Tayeb et al., REEPE | 2025 | ViT 二分类 99.3% / AUC 0.999 |
| Zhou et al., Scientific Reports | 2025 | Self-paced progressive 多尺度 AUC 0.9907 |
§9.5 变更日志
| 日期 | 事件 |
|---|---|
| 2019-06-28 | 竞赛开赛,数据集发布 |
| 2019-09-08 | 竞赛结束,数据集未再更新 |
§10 AI 使用声明卡
§10.1 AI 使用声明
本 Wikipedia 条目由 AI 辅助生成并经人工审核。数据集技术参数基于 Kaggle 竞赛官方页面、竞赛讨论论坛、社区开源代码及已发表学术论文整理。医学背景信息基于 ICD-11、SNOMED CT 和公开发表的流行病学文献。所有数据均来自公开来源,未经临床验证。
§10.2 使用限制
- 本数据集仅限非商业学术研究用途,受 Kaggle 竞赛规则约束
- 测试集标签未公开,无法复现竞赛排行榜成绩
- 数据集未更新(2019 年发布后无后续版本)
- 数据集不可再分发——需通过 Kaggle 官方渠道下载
§10.3 推荐引用格式
使用本数据集时请引用:
Karthik, Maggie, and Sohier Dane. “APTOS 2019 Blindness Detection.” Kaggle Competition, 2019. https://kaggle.com/competitions/aptos2019-blindness-detection
§10.4 人工校验表
| 校验项 | 状态 |
|---|---|
| H1 标题格式 | ✅ |
| INFOBOX 24 行完整 | ✅ |
| §0 E-E-A-T 三段免责声明 | ✅ |
| §1 30 秒速览 + 摘要 + 战略价值 + 对比表 + 时间轴 + 应用场景 | ✅ |
| §2 ICD-11 + SNOMED CT + 临床任务 + 人群 + 金标准 | ✅ |
| §3 版本矩阵 + 模态 + 统计 + 格式 + 标注流程 + 类别分布 + 溯源链 | ✅ |
| §4 目录树 + DAIMS 字典 + 质量问题 | ✅ |
| §5 官方划分 + 推荐划分 + 自定义 + 泄漏风险 + 外部验证 | ✅ |
| §6 快速启动 + 预处理 + 训练 + 坑点 + 增强 + 模型 + 计算 + 评估 | ✅ |
| §7 偏倚 + 标注质量 + 泛化 + 局限 + DAIMS 24 项 + 外部验证矩阵 | ✅ |
| §8 排行榜 + SOTA + 协议 + 相关数据集 + 生态图 + 社区影响 | ✅ |
| §9 引用 + 资源 + 论文 + 变更日志 | ✅ |
| §10 AI 声明 + 限制 + 引用格式 + 校验表 | ✅ |
| §C 单一 JSON-LD @graph 块 | ✅ |
| G3 内容纯净度(无注释/占位符/未定稿状态) | ✅ |
