639. CZII - CryoET Object Identification | czii-cryo-et-object-identification
首先,我们感谢竞赛主办方和 Kaggle 工作人员组织本次竞赛。下面,我们介绍团队 I Cryo Everyteim 的解决方案。
我们的最终提交由四个 3D U-Net 模型汤(Model Soups)组成,这些模型使用不同的模型大小、参数和训练数据进行训练,以确保强大的模型互补性。所有 3D U-Net 均使用 (128, 128, 128) 的 patch 大小进行训练,但使用 (160, 384, 384) 的 patch 大小进行推理,重叠率为 25%,并使用高斯重建来处理边界伪影。此外,我们采用了几何测试时增强 (TTA),包括翻转和转置。
我们的模型最初基于主办方的示例笔记本和 @fnands 的笔记本。我们使用了 MONAI 库中的 3D U-Net 架构,训练 patch 大小为 (128, 128, 128)。
模型深度为 3 层,步长为 (2, 2, 1)。我们从一个简单的模型开始:
"channels": (32, 64, 128, 128)
"strides": (2, 2, 1)
"num_res_units": 1
这个单一模型配合我们的推理策略在公共排行榜上达到了 0.744 的分数。
后来,我们训练了更复杂的 U-Nets,配置如下:
"channels": (32, 64, 128, 256),
"strides": (2, 2, 1),
"num_res_units": 2,
上述配置的模型 alone 达到了 0.759 的 LB 分数。
"channels": (32, 96, 256, 384),
"strides": (2, 2, 1),
"num_res_units": 2,
我们还在模型中应用了 0.2 或 0.3 的 Dropout。
模型在六个经过高斯去噪的合成断层扫描图(tomograms)上进行了预训练——具体是 'TS_0', 'TS_1', 'TS_10', 'TS_11', 'TS_12', 和 'TS_13' 断层扫描图。
@sersasj 注:应用高斯去噪是因为它在视觉上改善了 WBP 断层扫描图的粒子可视化,且易于实现。我假设使用更先进的去噪器可以获得更好的结果,但尝试编写去噪模型代码消耗了太多的 Kaggle 配额,所以我放弃了。
预训练不仅减少了模型学习粒子所需的时间,还将 LB 分数提高了约 0.01。
合成数据预训练和微调都使用了以下变换:
Compose([
RandCropByLabelClassesd(
keys=["image", "label"],
label_key="label",
spatial_size=[128, 128, 128],
num_classes=7, # 背景及所有 6 个类别
num_samples=16,
),
RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=0),
RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=1),
RandFlipd(keys=["image", "label"], prob=0.5, spatial_axis=2),
])
我们使用了 MONAI 的 DiceCELoss,并使用 AdamW 优化模型,采用了 plateau 学习率降低策略,初始学习率为 1e-3。
我们还 experimented 了指数移动平均 (EMA),结果显示良好。在竞赛的最后 3 天,我们使用其他类型的断层扫描图训练模型:"denoised" (去噪), "ctfdeconvolved" (CTF 反卷积), "isonetcorrected" (IsoNet 校正)。在整个竞赛的几乎全部时间里,除了训练中的几何数据增强(翻转和旋转)外,我们没有发现任何其他能提高 LB 的策略;尽管如此,使用其他断层扫描图类型进行训练确实产生了良好的结果。
我们主要依赖 k-fold 模型的折外预测。具体来说,我们实施了 7 折交叉验证方法,即在除一个断层扫描图之外的所有断层扫描图上训练,该断层扫描图用作验证集。此过程重复七次,每个折一次作为验证集。这帮助我们获得了与公共排行榜分数相关性很好的分数,通常高出 0.01 到 0.02 分。
我们遇到的一个限制是,在测试模型汤的集成时无法应用此验证策略。在这种情况下,我们不得不依赖泄露数据分数。虽然这种方法与排行榜分数的相关性不那么强,但大多数时候它允许我们对不同集成的性能进行排序,并比较 TTA 策略。
在推理期间,我们使用 MONAI 的 sliding_window_inference,重叠率为 25% 并使用高斯重建,以更准确地处理边界预测;这将公共 LB 提高了约 0.002。最大的发现之一是尽可能大地进行推理 patch;我们使用了 (160, 384, 384) 的窗口大小,与 (128, 128, 128) 的大小相比,将我们的分数提高了约 0.01。(感谢 @iamparadox 发现这一点)
我们还尝试了结合不同大小的预测,例如 (160, 384, 384) + (136, 248, 248),但推理时间长得多,而收益不确定。因此,我们放弃了这种方法,转而创建更多的集成并采用更多的 TTA。
对于后处理,我们通过在 logits 级别结合模型预测而不是直接平均概率来改进粒子检测。
然后我们使用分水岭分割 (watershed segmentation) refined 粒子识别,这有助于分离接触或重叠的粒子。分水岭过程使用特定于粒子的确定性阈值创建二进制掩码,计算距离变换以测量粒子分离,使用局部最大值作为标记识别 distinct 粒子,最后应用分水岭分割来确定粒子边界。我们从使用 skimage 切换到 cucim 和 cupy 以减少推理时间。
我们还对每个粒子使用了特定的 blob 阈值大小,以减少预测中的假阳性数量。
此外,我们使用了沿 X 和 Y 轴的翻转以及转置 TTA。
集成一直是我们团队的主要想法之一。当团队在截止日期前 2 周完全组建时,我们的 LB 分数都在 0.73 左右,位于排行榜第 50 名左右。当时,我 (@sersasj) 有一个得分为 0.682 的 YOLO 和一个得分为 0.692 的 U-Net,集成后 LB 达到 0.732。团队其余成员只有一个得分为 0.739 的 3D U-Net。所以很明显,我们将集成所有内容并取得惊人的结果;可惜,并没有成功。
尽管如此,我们从这次经历中学到了宝贵的教训。我的 3D U-Net 比得分为 0.739 的 U-Net 小约 30 倍,但当使用团队的惊人推理技术时证明非常有效:更大的 patches、blob 阈值、logits 级别集成和分水岭处理。在实施预训练和额外训练后,它达到了 0.744 的排行榜分数。
得益于我们的团队合作(特别是 @sirapoabchaikunsaeng 和 @iamparadox),我们成功训练了几个源自 0.744 模型的 U-Net 变体,通过修改参数、实施 EMA (指数移动平均)、 Incorporating 更多数据以及应用上述技术。
通过这样做,我们拥有了各种相互互补的 U-Nets,但我们无法全部使用它们。为了管理“使用”我们拥有的所有模型,@itsuki9180 提出了一种称为模型汤 (model soup) 的技术想法和代码,这本质上是对来自相同预训练权重的多个模型的权重进行平均。
我们将此应用于我们 k-fold 训练中的模型。
我们的最终集成包括: