535. RSNA Screening Mammography Breast Cancer Detection | rsna-breast-cancer-detection
更新 2023年4月10日
消融研究:尽管在特定折数上有很大改进(见下文),但软正标签技巧并没有比标准标签平滑技术表现出明显的性能提升。使用外部数据集在本地 OOF 验证和私有排行榜上将 F1 分数提高了约 0.02(使用完全相同的训练管道和超参数)。
| 外部数据 | 损失函数 | OOF F1 | LB | PL |
|---|---|---|---|---|
| x | label smoothing=0.1 | 0.4921 | 0.60 | 0.53 |
| x | soft positive label=0.8 | 0.4853 | 0.60 | 0.53 |
| ✓ | label smoothing = 0.1 | 0.5161 | 0.58 | 0.56 |
| ✓ | soft positive label = 0.9 | 0.5182 | 0.61 | 0.55 |
首先,我要感谢 Kaggle 和比赛主办方为我们提供了这样一个精彩的挑战,目标宏大且数据质量高。感谢所有参与者和 Kaggler 们积极且富有成效的讨论和代码分享。我的解决方案正是建立在你们分享的每一个片段之上。我学到了很多,对此我深表感激。
我也对获得第一名感到非常高兴和惊讶。这是我的第一枚金牌,也是我第一次写解决方案总结。这对我来说是一段很棒的旅程。
关于解决方案,我使用了一个非常简单的管道,只需几行即可描述:
现在我想分享一些实验和我对这些实验的想法。其中许多可以在其他优秀 Kagglers 的讨论中找到。许多似乎显而易见。希望这能帮助一些新来者在未来入门。请注意,这只是我个人的观点/想法,实验和知识非常有限。感谢您的讨论,如果有不对的地方请随时指正。
进行 ROI 裁剪是因为它有效地帮助在固定分辨率下保留更多的纹理/细节。我使用 YOLOX-nano 416x416 作为 ROI 检测器。与基于规则的方法相比,DL 检测器的优势在于获得的边界框更小,纵横比更稳定,且专注于乳腺区域。
conf_thres 和高 iou_thres。只有 3 张漏检图像(均包含噪点)和超过 100 张有 2 个框的图像(几乎重叠)。我手动选择并标注了其中 99 张。因此,我总共有 571 张标注图像。| 模型大小 | 图像大小 | 插值 | AP_new_val | AP_remek_val |
|---|---|---|---|---|
| nano (选择) | 416 | LINEAR | 96.26 | 94.21 |
| nano | 416 | AREA | 94.09 | 91.60 |
| nano | 640 | LINEAR | 95.85 | 88.40 |
| nano | 768 | LINEAR | 96.22 | 82.09 |
| nano | 1024 | LINEAR | 94.92 | 89.40 |
| tiny | 416 | LINEAR | 94.23 | 90.20 |
| tiny | 640 | LINEAR | 94.95 | 89.84 |
| tiny | 768 | AREA | 96.21 | 68.03 |
| tiny | 1024 | AREA | 93.69 | 73.70 |
| s | 416 | LINEAR | 95.03 | 0.86 |
| s | 640 | LINEAR | 96.10 | 70.80 |
| s | 768 | LINEAR | 96.79 | 78.70 |
所有实验中 AP@0.5 均为 1.0。我们看到两个验证集之间的 AP@0.5-0.95 存在巨大差距。原因如下:
这些问题是否导致了巨大的差距,特别是对于更强的模型和更大的图像尺寸?所有这些努力只是为了确保一个“尽可能好”的 ROI 检测模型。我认为 @remekkinas 的数据集足以训练良好的 YOLOX 模型,它们在隐藏测试集上也能表现同样出色。
在 YOLOX 漏检的情况下,使用稍微修改自 此 notebook 的简单 Otsu 阈值处理 + findCountours() 来寻找乳腺边界框作为后备方案。或者,如果两者都漏掉了乳腺框,就直接使用整个图像而不进行任何裁剪。
对大数组的操作很耗时,所以我尝试尽可能将计算任务转移到 GPU 上。
我的最终解决方案使用了外部数据集,但我大部分时间(直到“还剩 7 天”)都坚持仅使用竞赛数据。因此,我的大部分实验仅基于竞赛数据完成:基于 patient_id 进行 StratifiedGroupKFold 的 5 折分割。最终解决方案使用的训练超参数几乎继承自这些早期实验。
比赛的 pF1 分数对我来说并不稳定且难以追踪。因此,我主要基于多个指标来追踪我的实验:{ PR_AUC, ROC_AUC, best_PF1 (binarized), best_threshold },而不仅仅是一个。
我在所有实验中都坚持使用这个数据增强管道,完全没有调整:
A.Compose([
# 裁剪, 改编自 A.RandomSizedCrop()
custom_augs.CustomRandomSizedCropNoResize(scale=(0.5, 1.0), ratio=(0.5, 0.8), p=0.4),
# 翻转
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
# 缩小
A.OneOf([
A.Downscale(scale_min=0.75, scale_max=0.95, interpolation=dict(upscale=cv2.INTER_LINEAR, downscale=cv2.INTER_AREA), p=0.1),
A.Downscale(scale_min=0.75, scale_max=0.95, interpolation=dict(upscale=cv2.INTER_LANCZOS4, downscale=cv2.INTER_AREA), p=0.1),
A.Downscale(scale_min=0.75, scale_max=0.95, interpolation=dict(upscale=cv2.INTER_LINEAR, downscale=cv2.INTER_LINEAR), p=0.8),
], p=0.125),
# 对比度
A.OneOf([
A.RandomToneCurve(scale=0.3, p=0.5),
A.RandomBrightnessContrast(brightness_limit=(-0.1, 0.2), contrast_limit=(-0.4, 0.5), brightness_by_max=True, always_apply=False, p=0