该系列其他文章

Kaggle RSNA 乳腺癌检测比赛复盘(一)—— 赛题介绍和自我总结

Kaggle RSNA 乳腺癌检测比赛复盘(二)—— #4:多图特征融合

Kaggle RSNA 乳腺癌检测比赛复盘(三)—— #6:CAM 的妙用

比赛描述

赛题非常简单:给定某个乳房的一组乳腺 X 影像图片,通过图片鉴别该乳房是否患有乳腺癌,一个常见的图像而分类比赛。

复杂点:某一个乳房会给出至少 2 张图片,分别为两个视角拍摄(CC 和 MLO),而一个病人有两个乳房,因此对一个病人来说,至少有 4 张图片。而标注的标签,都是在乳房级别而不是图像级别。因此,如果当作单图像分类的问题来处理,最后需要做聚合(比如某个乳房的 N 个图像推断出了 N 个结果,那么需要对这 N 个结果做聚合来得到最终的结果)。

评价指标是 pF1,类似于一种概率的 F-Score。实际用下来,还是需要设置合理的 threshold 来涨点,所以感觉还不如就直接用 F-Score。比赛的数据量很大,训练数据有 314G,但类别极不平衡,仅有 %1 左右的正样本。另外,本地验证得分和公榜得分差异也巨大,最后会有一定的 shakeup。

很容易想到这个比赛拉开分差的几个点:

  1. 如何处理不均衡的样本
  2. 如何处理多张图片单个标签的问题
  3. 如何应对最后的 shakeup

个人总结

从公榜 12(🏅️),到私榜被 shake 到了 26 名(🥈),我属于被 shake 得最惨的几号人之一。

先戳痛处:说说金牌怎么就歪成银牌了

那天我很郁闷,梦寐以求的 SOLO 金就这么没了,甚至前一天晚上觉都没睡好。

其实被 shake-down 基本在预料之中,但又完全是有机会避免的。我有几处明知 overfit LB 还一意孤行的点:

  1. 选择了使用百分位数作为 threshold 的提交。

    用百分位数动态选择 threshold 来做判断,是一定会 overfit 的做法。但因为是我最高的公榜提交,因此我还是选择了它。结果当然很糟,公榜 0.63 而私榜只有 0.44。

    但这种做法也不是完全没用,我发现用百分位数 threshold 来测试不同模型在 LB 上的表现效率很高,因为不同模型的 threshold 有可能不同,如果想测试模型的 LB 则可以使用百分位数的 threshold 来避免手动调整 threshold。当然在大多数情况,直接使用 CV 的最佳 threshold 可能是更好。

  2. 没有选择差异性更强的 ensemble 方式。

    我有两个 ensemble 模型完全一致的提交,其唯一不同之处是是否对不同模型的输入做了不同的变化,其中一个做了一个没有,而没有做变化的 LB 得分高出了两个点,因此我也根据 LB 的得分选择了没有变化的提交,最后 PB 的得分正好相反:输入有做变化的高出了 2 个点。

总结下来,几乎就是没有把 Trust CV 贯彻到底,特别是在模型选择的时候。

比赛很难,SOLO 更难,如何保持热情

这次比赛过程中,我在公榜的金牌区呆了很长时间,甚至一度到达第二名。结果我发现好的名次并不能让我更有拼劲,甚至一度想放弃比赛。

最能让我产生动力的因素,是分享。我是抱着学习的初衷参加这次比赛的,在比赛的前一个月,我的名次大概在铜牌银牌之间徘徊,但那时的我并不着急于上分,而是以搜集信息和思考为主,甚至花了大部分时间学习了一下 CUDA 编程,解决了解析 dicom 文件速度过慢的问题,我开源了两个 lib:ExhaustiveWeightedRandomSamplernvjpeg2k-python,分享到 Kaggle 社区后得到的回应也非常不错。

那时的我很快乐,不像是一个孤独的竞争者,要跟其他的参赛者拼个你死我活,而更多的是扮演一个合作者,为了解决一个难题,贡献自己微弱的力量。但那天,一切都变了…

我随意提交的一个单折单模型的分数挺进了公榜的前 20 名,我知道,只要我加上多折的聚合,就一定能到金牌,甚至进入奖金区都不无可能。之后的几天我开始聚合模型提交,而且开始 probing 公榜的 threshold,果不其然,我顺利的到达了第二名,这应该追平了历史的最高名次,但这没有任何意义,只能满足一时的虚荣心。

接下来我开始变得胜负欲非常强,可能是对金牌太过于执着,比赛的目的不再是学习和分享,而是拿到金牌。最后与金牌失之交臂,也算是点醒了我。我知道很多人可能跟我一样,都非常希望获得奖牌。但在 Kaggle 这个社区,分享和学习一定是更有意义的事。

最后再说说我的方案

我用了最简单的方案,即将任务作为单张图片的分类问题,最后提交的时候在单个乳房维度上做一个 max 结果聚合即可。基本就是最常见的方法,而这点也给了我信心,只要处理好各种细节,做好实验管理,即便是最基础的方案也能斩获不错的名次。

因为直接使用了单张图片训练,而标签是跟着单个乳房的,所以势必会训练到很多 False Positive 样本,这也是为什么在结果聚合的时候取了 max 而不是 mean 的原因。

对于 False Positive 这一点,还做了一点改进就是训练 Out of Folds 并获得样本的置信度,然后根据置信度来丢弃一些「高度疑似」FP 的样本。这个操作非常有效,CV 得分提高了 0.03 ~ 0.04 分。

在模型上,Convnext V2 在 CV 上全面碾压了其他模型。

另外在 CV / LB 相关性较小的情况下,以下一些操作可能可以减小 shakeup 的影响:

  1. 使用更重的数据增强,比如 cutout,mixup,mosaic,可能更能防止 shake。
  2. 使用外部数据和更多的训练流程(fine-tune、蒸馏 等)。
  3. 融合不同的方案,尽管某些方案的 CV 提升可能没有甚至降低。