竞赛回顾:脊柱疾病智能诊断大赛

先说结果:复赛27/3107,只能说一般般,没有打入前top20,并没有实现自己的目标。但是也是收获了不少经验,做一些总结和分享。

失败的经验:

  1. 尽早开始,尽快搭建自己的整套pipeline,后面再去增加的自己的idea,不断检验自己的idea.
  2. 可以准备一些自己的pipeline模板,这样可以加速开发。
  3. 想办法和大佬合作吧,和大佬一起合作。

贴一张最后决赛的结果:

其中GPU第一队,基本是大佬合集,看个人简介就知道,经常获得冠军的队。也是唯一一个实现map超过0.7的队伍。

自己的实现思路:
Unet关键点检测+resNet分类
要实现的目标:
竞赛回顾:脊柱疾病智能诊断大赛_第1张图片
输入一些dicom医学图像,实现输出关键点的位置和疾病类别分类。
竞赛回顾:脊柱疾病智能诊断大赛_第2张图片

自己实现过的一些思路:

  1. 不区分类别,直接将椎体和椎间盘11个关键点输入Unet,输出的预测热图。

  2. 将椎体5个点输入一个Unet,将椎间盘6个点输入另一个Unet。在将两个输出合并到一起,组合形成结果。
    竞赛回顾:脊柱疾病智能诊断大赛_第3张图片
    竞赛回顾:脊柱疾病智能诊断大赛_第4张图片

  3. 输入的图像有很多突出的点(噪点),使用各向异性滤波来处理(平滑),但是这样处理的话,测试集也需要输入处理。

  4. 把整11个点做成高斯热图来输入,当做整个脊椎的热图,但是没有什么改进。

其中面对的一个问题,可以定位到目标大概位置,但是脊椎有很多相似的结构,导致预测的开头容易出现跳格的现象,所以设想一种改进的Loss,主要利用点之间的距离相同,对距离做一个约束,故把这种距离加入到Loss中,我把他命名为posiLoss,后来在一篇论文中看到了相似的改进。

class posiLoss(nn.Module):
    def __init__(self,alph=50, beta=100):
        super(posiLoss, self).__init__()
        self.alph = alph
        self.beta = beta
        self.criterion_part1 = nn.MSELoss()
        self.sz = 11
        self.topKposi = 5

    def posiLoss(self, pred_heatmap, gt_heatmap):
        n,c,h,w = pred_heatmap.shape
        n_loss = list()
        for n_idx in range(n):
            # print("n:",n)
            pred_posiRation = self.relationPosi(pred_heatmap[n_idx])
            gt_posiRation = self.relationPosi(gt_heatmap[n_idx])
            psoiLossL = torch.Tensor(torch.abs(torch.sub(pred_posiRation, gt_posiRation))).cuda()
            # print("psoiLoss", psoiLossL)
            ret_psoiLoss = torch.sum(torch.topk(psoiLossL, self.topKposi).values)
            # print("ret_psoiLoss", ret_psoiLoss)
            n_loss.append(ret_psoiLoss)
        ret_n_loss = torch.mean(torch.Tensor(n_loss))
        return ret_n_loss

    def relationPosi(self, heatmap):
        # print(heatmap.shape)
        ret = list()
        ret.append(self.criterion_part1(heatmap[0], heatmap[1]))
        for i in range(1, self.sz-1):
            # print("i:",i)
            up = self.criterion_part1(heatmap[i-1], heatmap[i])
            down = self.criterion_part1(heatmap[i+1], heatmap[i])
            # print("down",down)
            ret.append(torch.mean(torch.Tensor((up, down))))
        ret.append(self.criterion_part1(heatmap[self.sz-1], heatmap[self.sz -2]))
        return torch.Tensor(ret)

    def forward(self, pred_heatmap, gt_heatmap):
        mse_loss = self.criterion_part1(pred_heatmap,gt_heatmap)
        # print("mse_loss", mse_loss)
        posiLosss = self.posiLoss(pred_heatmap,gt_heatmap)
        # print("posiLosss",posiLosss)
        return self.alph*mse_loss+self.beta*posiLosss

竞赛回顾:脊柱疾病智能诊断大赛_第5张图片

竞赛回顾:脊柱疾病智能诊断大赛_第6张图片
各种结果中UnetDouble+posiLoss+diffuse会最好。定位精度可以实现0.81,表里未记录。
在这里插入图片描述
一些未曾实现的想法:
6. 3DUnet,因为dicom文件是脊椎切片,是相关联的。
7. 传统方法:有论文显示,使用HOG和SVM来实现定位,准确率也可以很高。
8. 利用脊椎上的亮暗变化规律来定位中心值,因为不同图像之间差距很大,但是有一般的规律。
竞赛回顾:脊柱疾病智能诊断大赛_第7张图片
竞赛回顾:脊柱疾病智能诊断大赛_第8张图片
9.轴状位结合切片,作为输入信息。btw,主要原因是切片标注的数据实在是有点乱,很多标注不一致,希望天池可以做的更严谨一些。

向大佬学习:

GPU冠军方案:
检测网络:Cascade R-CNN(X-101)+ FPN + DCN
分类网络:ResNeSt269

结果:

  1. 思路一:利用关键点生成边界框形式的标注,将赛题任务巧妙地转化为目标检测任务。
  2. 思路二:采用矢状位多帧影像进行三层拼接,充分利用相邻帧信息
  3. 思路三:通过对特征更为明显的腰椎整体和骶骨第一块椎体进行检测,从而实现对检测框的筛选以及位置匹配。
  4. 思路四:增加额外针对轴状位与矢状位拼接图像的分类网络,从而提升目标分类精度。

参考链接:
Spark“数字人体”脊柱疾病智能诊断-GPU赛道-deep thinker-冠军比赛方案

GPU亚军方案:
竞赛回顾:脊柱疾病智能诊断大赛_第9张图片
竞赛回顾:脊柱疾病智能诊断大赛_第10张图片
中间加入FPN,我发现经常拿奖的一些方案都是加入了FPN的结构,来提升对小目标的检测。
由于数据集不平衡,所以在后面使用了加权的Loss,以及模型融合。

一些特点:

一.采用端到端检测网络,充分利用了图像全局与局部的信息。

二.使用定位框损失DIOU-Loss,提高边框定位精度。

三.通过加权分类损失应对类别极度不平衡的情况。

四.高亮抑制方法使得图像更易识别,伪3D数据增广有效地增加了样本多样性。

五.根据任务提出了基于中心加权检测模型融合方法。

六.极快的训练和推理速度,极大地方便方案的落地。

我的开源地址:https://github.com/SkySailing/tianchi_spinalAI_dection_competetion
有用的话,请点一个star,谢谢!!
参考:
Spark"数字人体"AI挑战赛_脊柱疾病智能诊断大赛_GPU赛道亚军比赛攻略_shiontao团队
天池11月之星:北大新星陈**、赵*与天池的参赛故事
天池论坛

你可能感兴趣的:(竞赛项目)