返回列表

[38th Place] Single Stage Single Model Efficientnetv2

513. RSNA 2022 Cervical Spine Fracture Detection | rsna-2022-cervical-spine-fracture-detection

开始: 2022-07-28 结束: 2022-10-27 医学影像分析 数据算法赛
[第38名] 单阶段单模型 Efficientnetv2

[第38名] 单阶段单模型 Efficientnetv2

作者: Yerram Varun (Master) | 比赛排名: 第38名

Pipeline Diagram

感谢 RSNA 和 Kaggle 举办了如此激动人心的比赛,并祝贺所有的获胜者!

这是对 @vslaykovsky此讨论 中分享的流程的修改版本。

交叉验证策略

我使用了 5 折交叉验证策略,按 StudyInstanceUID 分组,并按所有椎骨的骨折情况进行分层(创建了一个连接所有骨折情况的列,如 0_1_0_0_0_1_0,然后用于分层)。

预处理

我使用了窗口化技术来预处理 Dicom 图像,这在以前的 RSNA 解决方案中被使用过。这三个窗口值来源于 这篇 论文。

def window(img, WL=50, WW=350):
    upper, lower = WL+WW//2, WL-WW//2
    X = np.clip(img.copy(), lower, upper)
    X = X - np.min(X)
    X = X / np.max(X)
    X = (X*255.0).astype('uint8')
    return X

def dicom_load(self, siuid, slic):
    path = f"data/train_images/{siuid}/{slic}.dcm"
    img = dicom.dcmread(path)
    img.PhotometricInterpretation = 'YBR_FULL'
    data = img.pixel_array
    slope = img[('0028','1053')].value
    intercept = img[('0028','1052')].value
    data = data*slope + intercept
            
    windowed = np.stack((window(data, WL=80, WW=300),
                        window(data, WL=500, WW=1800),
                        window(data, WL=400, WW=650)
                        ), axis=-1)/255.
    return windowed

训练数据

每个 3 通道切片与 +1/-1 相邻切片连接,创建一个 9 通道输入。这个 9 通道输入预测中间切片的骨折概率和椎骨存在情况。

在推理过程中,这个 3 切片窗口以步长 2 移动,以加快推理速度。

模型

我使用 Timm 库来使用预训练模型,并修改第一层以接受 9 通道输入。

self.model = timm.create_model('tf_efficientnetv2_l', pretrained=True, num_classes=0)
self.model.conv_stem = nn.Conv2d(9, 32, kernel_size=(3, 3), stride=(2, 2), padding='same', bias=False)

哪些方法没有奏效

这是一个很长的列表,但我将范围缩小到 3 种预测 patient_overall(患者整体骨折情况)的方法:

  • 在上述方法中,切片之间的序列信息仅用于 +1/-1 连接。为了利用更多的上下文,我为所有切片生成了嵌入,然后尝试使用 LSTM/Transformer 预测 patient_overall

    可能失败的原因:这个第二阶段模型只有 2k 个数据点可供学习,这可能不够。

  • 从患者扫描中均匀/随机选择固定数量的切片,并训练 3D 分类器。

    可能失败的原因:骨折只能在一些切片中看到,需要过滤出特定的切片。

  • 训练了一个 XGBoost
同比赛其他方案