639. CZII - CryoET Object Identification | czii-cryo-et-object-identification
首先,我要衷心感谢比赛组织者举办了这场激动人心的挑战。得益于他们的努力,我有机会学习很多并提高自己的技能。我也感谢 Kaggle 社区提供的 insightful 讨论和宝贵资源。
特别是,我发现 @hengck23 的讨论和笔记本非常有帮助。他们的见解和贡献对于塑造我在这场比赛中的方法起到了重要作用。
sliding_window_inference 将输入体积划分为固定大小的子体积,并使用 10 个不同的模型进行推理。每个模型预测每种粒子类型的地图,指示粒子的位置。
我使用了基于 这个笔记本 的 2.5D UNet,以及 MONAI 的 3D UNet 和 SegResNet。对于 2.5D UNet,使用了 timm 的 EfficientNet-B2、EfficientNetV2-B2、ConvNeXt-Nano 和 ResNet34d 作为编码器。虽然 3D UNet 和 SegResNet 最初仅使用训练数据集难以 achieving 良好的性能,但在后来描述的模拟数据预训练后,它们达到了与 2.5D UNet 相似的准确度。
为了提高模型多样性,我总共训练了 10 个模型,在预训练策略、数据增强技术和其他超参数上略有不同。对于最终提交,我使用了在整个训练数据集上训练的模型。
作为预处理步骤,我首先移除了异常值,然后应用了 min-max 归一化。输入体积被裁剪为 64×128×128 的固定大小。
对于训练标签,我在每个粒子位置周围生成了二进制掩膜。具体来说,我将半径 × 0.5 到 1 内的区域设置为 1,所有其他区域设置为 0。我为每个粒子分别创建了这些掩膜。
最初,我尝试了 BCE 和 Focal Loss,但这些损失函数导致收敛极慢,可能是由于严重的类别不平衡。然后我尝试了 Dice Loss 和 Tversky Loss,这显著加快了训练速度。然而,这些损失函数导致模型的预测变得过于二值化,仅输出 0 或 1 的极端值。
由于我的流程通过平均预测地图然后应用阈值进行二值化来集成预测地图,因此这种预测值是不理想的。为了解决这个问题,我使用了 这篇论文 中提出的 FocalTversky++ loss。通过使用这个损失,模型输出的预测地图反映了其置信度。
我使用 polnet 生成了自己的模拟数据,并用它来预训练某些模型。为了增强模型区分粒子的能力,我设计的模拟数据包含了与本次竞赛目标粒子形状相似的粒子。
对于推理,我使用了 MONAI 的 sliding_window_inference,重叠率为 0.25。由于子体积边缘附近的预测往往不太稳定,我丢弃了最外层 8% 的预测以提高可靠性。
我觉得这次比赛的关键挑战之一是实现快速推理。为了优化速度,我首先在提交前的单独笔记本中将模型转换为 TensorRT。在推理期间,我加载了预先转换的 TensorRT 模型,并利用两个 T4 GPU 进行并行处理。
一旦获得集成的预测地图,我就使用特定于粒子的阈值对其进行二值化。这些阈值最初是通过交叉验证估计的,后来根据 leaderboard 进行了微调。
二值化后,我对二进制地图执行连通分量分析,并提取每个连通分量的质心作为粒子位置。