第一名解决方案 - 通过血管 ROI 掩膜实现位置感知的动脉瘤检测
作者: tomoon33 (Grandmaster)
发布日期: 2025-10-15
竞赛: RSNA Intracranial Aneurysm Detection
第一名解决方案
通过血管 ROI 掩膜实现位置感知的动脉瘤检测
感谢 RSNA、组织者、贡献的放射科医生和机构,以及举办这次具有影响力挑战赛的 Kaggle 团队。这篇文档总结了我的第一名解决方案。我的方法的核心是一个稳健的由粗到细的流程,它利用血管分割来指导基于感兴趣区域 (ROI) 的分类器,从而产生位置感知的预测。
解决方案概览
-
高层级流程
- 预处理: 将 DICOM 序列转换并标准化为 NIfTI 体积。
- 血管分割与 ROI 提取: 使用由粗到细的 nnU-Net 方法。一个快速的低分辨率模型首先找到一个候选区域。这使得更详细的高分辨率模型可以仅关注此 ROI,从而提高准确性和速度。
- ROI 分类: 一个 3D 分类模型,使用详细的血管掩膜作为输入,预测 13 个解剖位置的概率以及整体动脉瘤的存在情况。
-
关键设计原则
- 由粗到细的效率: 一个快速的低分辨率模型首先扫描整个体积以找到候选区域。这使得更详细的高分辨率模型可以仅关注此 ROI。这提高了准确性和速度。
- 利用分割作为结构引导: 通过向分类模型提供显式的血管掩膜,我给了它一张详细的血管结构图。这有助于模型专注于血管所在的区域,即动脉瘤所在的位置。
数据准备
- 由于数据质量问题(如方向异常、损坏的 DICOM 文件和不合理的切片间距),我排除了大约 60 个序列。
- 我使用了多标签分层的 5 折交叉验证。
流程
1. 预处理
- 过滤切片: 在每个序列中,我只保留了匹配大多数
Rows × Cols 和 PixelSpacing 配置的图像,并过滤掉具有异常切片间距的切片,以确保一致性。
- 转换 DICOM 为 NIfTI: 我使用
dcm2niix 进行转换。如果失败,我先运行 gdcmconv --raw 作为回退,然后再重试转换 [1]。
- 标准化方向: 所有体积都使用 nnU-Net 的
SimpleITKIOWithReorient 重新定向为一致的生理解剖方向。
- 归一化强度: 我应用了 nnU-Net 标准的每体积 z-score 归一化来标准化图像强度。
2. nnU-Net 分割 + ROI 提取(由粗到细)
此阶段使用三个 nnU-Net v2 [2] 模型序列(nnUNetResEncUNetMPlans,3d_fullres 配置)首先定位粗略的 ROI,然后在其中生成详细的血管分割。
-
模型 1:粗略血管定位
- 间距: (1.0, 1.0, 1.0) mm
- 类别: 3 个血管组(后循环 + 基底动脉 / 大脑中动脉 / 其他)
- 损失: Dice + 交叉熵
- 目的: 执行快速、低分辨率扫描,以高效地为高分辨率模型找到单个 ROI 候选者。此模型还支持后面描述的可选方向校正步骤。
-
模型 2:精细分割(平衡)
- 间距: (0.80, 0.45, 0.44) mm
- 损失: Dice + 交叉熵 + SkeletonRecall (权重=1) [3]
- 目的: 生成精确的血管分割。SkeletonRecall 损失改善了标准损失可能遗漏的细血管的连通性。
-
模型 3:精细分割(召回优先)
- 间距: (0.80, 0.45, 0.44) mm
- 损失: Tversky + 交叉熵 + SkeletonRecall (权重=3)
- 目的: 通过优先考虑召回率来补充模型 2,使其对检测难以发现的血管段更敏感。
-
增强策略
- 我为精细模型(2 和 3)禁用了左右镜像,以保留解剖不对称性。
- 我使用了更强的强度和几何增强 [4]。
- 我添加了低分辨率模拟变换,使模型对厚切片扫描具有鲁棒性。
-
推理过程(两阶段)
- 阶段 1(粗略扫描): 我使用滑动窗口(重叠=0.2)运行模型 1 并二值化输出以获得前景掩膜。然后我对掩膜应用 DBSCAN 聚类以去除分散的假阳性。最大聚类的质心用于裁剪固定大小的 ROI (140×140×140 mm)。
- 阶段 2(精细推理): 我仅在粗略 ROI 内以更高的重叠 (0.3) 运行模型 2 和 3。模型 2 的血管分割用于计算紧密的边界框,然后重新裁剪并添加边距以创建分类器的最终 ROI。
此阶段的详细分割结果作为掩膜传递给分类模型。
3. ROI 分类(13 个位置 + 动脉瘤存在)
一旦准备好 ROI 和血管掩膜,3D 分类模型就会预测最终概率。
-
模型架构
- 输入尺寸: 模型接收大小为 128 × 256 × 256 体素的 ROI 体积。
- 骨干网络: 模型的核心是一个针对血管分割任务预训练的 nnU-Net。这种方法比标准的 2.5D 或 3D timm 骨干网络更准确且训练更快。
- 解码器简化: 为了提高效率,我简化了解码器,去除了其最后计算量大的块。这对性能没有负面影响。
- 辅助检测任务: 为了帮助模型学习动脉瘤的特定特征,我添加了一个辅助任务,该任务使用解码器特征在每个标注动脉瘤的位置重建一个小二进制球体(5 像素半径)。
- 特定位置预测头: 为了预测 13 个特定位置的概率,我使用以下过程:
- 每位置特征池化: "血管区域掩膜池化"层使用血管掩膜从解码器的特征图中提取对应于 13 个解剖位置中每一个的特征向量。(注意:实际上,我使用来自两个精细分割模型的掩膜应用此池化,并连接结果以获得更完整的特征。)
- 特征融合: 这 13 个特征向量与来自编码器的全局特征向量(通过全局平均池化)相结合。
- 位置间建模: 组合后的特征被送入"位置感知 Transformer"以模拟不同血管位置之间的关系。
- 分类: 最后,一个 MLP 头预测每个位置的概率。
- “动脉瘤存在”预测头: 对于整体存在预测,我在整个血管结构(所有血管掩膜的并集)上池化特征,并将其与编码器的全局特征相结合。这个聚合的特征向量被传递给一个单独的 MLP 头。
- 输出设计: 我将 14 个标签中的每一个都视为独立的二分类问题。这种设计有助于解决严重的类别不平衡问题,因为任何单个位置的阳性病例都非常罕见。
-
训练细节
- 损失函数:
- 13 个位置:
BCEWithLogitsLoss。
- 动脉瘤存在:
BCEWithLogitsLoss。
- 辅助球体分割: 平衡 BCE [5] 和 Focal-Tversky++ 损失 [6, 7] 的组合。这种组合非常适合高度稀疏的目标,并有助于防止 Dice 类损失可能发生的过度自信。
- 损失权重: 最终损失是三个组件的加权和。我将 13 个位置损失的权重设为 0.1,动脉瘤存在损失的权重设为 0.05,辅助球体分割损失的权重设为 1.0。主要目标是优先学习动脉瘤的精确位置,因此球体分割任务的权重最高。我发现分类损失的权重过高会导致过拟合,因此这种平衡很重要。
- 数据增强
- 强度变换: 高斯噪声、高斯平滑、强度偏移/缩放、对比度调整、高斯锐化和强度反转。
- 几何变换: 随机翻转(z, y, x 轴)、小旋转 (±10°)、缩放/剪切 (±10%)、轻微网格失真和模拟低分辨率变换。
- 优化器和调度: 我使用了学习率为 1e-4 的 AdamW 优化器,有效批量大小为 8(通过梯度累积实现)。使用了带有预热期的标准余弦退火调度。
- EMA 权重: 我使用模型权重的指数移动平均 (EMA) 进行推理。
-
推理
- 集成: 最终预测是 5 个交叉验证折中 4 个折的模型的平均值。
- 测试时增强 (TTA): 我对原始体积和左右翻转版本的预测进行了平均。
4. 其他细节
- 故障安全机制: 如果在分割或 ROI 提取步骤中发生异常,管道将不会尝试预测。相反,它会回退到一组预确定的概率。对于每个类别,此概率是我交叉验证集中折外预测的平均值。
- 可选方向校正: 我实现了一种修复方向错误扫描的方法。它分析了粗略分割中三个血管组的空间排列。通过将这些组的相对位置与其预期的解剖位置进行比较,它估计了正确的轴排列。这在训练集上完美运行,修复了所有识别出的方向问题。然而,它对排行榜分数没有可测量的影响,可能是因为测试集中不包含此类方向错误。
处理时间
-
训练
- 以下训练时间是在单个 NVIDIA RTX 4090 上测量的。
- 96×192×192 输入尺寸主要用于更快的实验和调优。
| 模型 |
输入尺寸 |
Epochs |
训练时间 |
| nnU-Net (模型 2) |
64×192×192 |
1000 |
14 小时 |
| ROI 分类器 |
96×192×192 |
30 |
6 小时 |
| ROI 分类器 |
128×256×256 |
30 |
12 小时 |
-
推理
- 推理时间是在使用两个 T4 GPU 的 Kaggle notebook 上测量的。
- 报告的时间是 100 个样本的平均值。
| 步骤 |
每个序列的时间 |
| 预处理 |
4.03 ± 3.78 秒 |
| 血管分割 |
10.65 ± 4.10 秒 |
| ROI 分类 |
3.33 ± 0.09 秒 |
消融实验
为了验证我的 ROI 分类模型中关键组件的有效性,我进行了消融实验。请注意,这是一个简化的评估;超参数(如 epoch 数量和学习率)未针对每个实验重新调整。为了提高效率,这些实验在折 0、1 和 2 上运行,使用减小的输入尺寸 96×192×192。
| 模型 |
输入尺寸 |
AUC (动脉瘤存在) |
AUC (13 个位置) |
分数 |
| 最终模型 (全分辨率) |
128×256×256 |
0.915 |
0.916 |
0.916 |
| 最终模型 |
96×192×192 |
0.907 |
0.898 |
0.902 |
| 无位置感知 Transformer |
96×192×192 |
0.899 |
0.894 |
0.896 |
| 使用 Dice 代替 FocalTversky++ |
96×192×192 |
0.902 |
0.896 |
0.899 |
| 将所有损失权重设为 1.0 |
96×192×192 |
0.890 |
0.877 |
0.884 |
| 无骨干网络预训练 |
96×192×192 |
0.777 |
0.811 |
0.794 |
| 无分割模型 3 |
96×192×192 |
0.899 |
0.883 |
0.891 |
| 无辅助分割损失 |
96×192×192 |
0.880 |
0.871 |
0.876 |
结果显示了几个关键点:
- 在血管分割任务上预训练骨干网络是最重要的因素。它极大地提高了分数并帮助模型训练得更快。这对运行许多实验非常有帮助。
- 位置感知 Transformer 和 FocalTversky++ 损失起初似乎有帮助,但它们对分数的最终贡献很小。这可能是因为其他改进和调优产生了更大的整体效果。
设计历程
我的最终设计是多次迭代的结果:
- 我最初尝试了一个单一的端到端 3D 分类器,它具有用于血管分割和动脉瘤定位的辅助头。虽然它可以检测动脉瘤的存在,但无法准确预测 13 个特定位置。
- 然后我观察到,用于血管分割的标准 nnU-Net 训练容易,并且在所有模态上泛化良好。这导致我改为两阶段、血管优先的流程,其中分割作为后续分类任务的强大引导。
- 我还尝试了一个更简单的模型,它接受 2 通道输入:图像体积与单个二进制血管掩膜连接。为了获得特定标签的预测,我会向模型提供相应的掩膜(例如,一个位置的掩膜,或“动脉瘤存在”的并集掩膜)。虽然模型本身很简单,但这种方法需要为单个患者序列运行 14 次单独的前向传播才能获得所有预测,这在计算上过于昂贵。
- 这导致了我最终的方法,使用带有区域掩膜池化的单个骨干网络传递,这提供了准确性和计算效率的良好平衡。
参考文献
[1] https://www.kaggle.com/competitions/rsna-intracranial-aneurysm-detection/discussion/598083
[2] Isensee, F., Jaeger, P. F., Kohl, S. A., Petersen, J., & Maier-Hein, K. H. (2021). nnU-Net: a self-configuring method for deep learning-based biomedical image segmentation. Nature methods, 18(2), 203-211.
[3] Kirchhoff, Yannick, et al. "Skeleton recall loss for connectivity conserving and resource efficient segmentation of thin tubular structures." European Conference on Computer Vision. Cham: Springer Nature Switzerland, 2024.
[4] https://www.kaggle.com/competitions/byu-locating-bacterial-flagellar-motors-2025/writeups/mic-dkfz-2nd-place-solution-3d-nnu-net-blob-regres
[5] https://www.kaggle.com/competitions/czii-cryo-et-object-identification/writeups/yu4u-tattaka-4th-place-solution-source-codes-submi
[6] Yeung, Michael, et al. "Calibrating the dice loss to handle neural network overconfidence for biomedical image segmentation." Journal of Digital Imaging 36.2 (2023): 739-752.
[7] https://www.kaggle.com/competitions/czii-cryo-et-object-identification/writeups/tomoon33-6th-place-solution