返回列表

Finally GM & 1st time won prize money! And 3rd place solution.

349. Understanding Clouds from Satellite Images | understanding_cloud_organization

开始: 2019-08-16 结束: 2019-11-18 气象预报 数据算法赛
终于成为GM & 第一次赢得奖金!以及第3名的解决方案

终于成为GM & 第一次赢得奖金!以及第3名的解决方案

作者: Xuan Cao (Grandmaster) | 比赛排名: 第3名

更新:代码现已发布在 这里

感谢马克斯·普朗克气象研究所和 Kaggle 主办了如此有趣的比赛。祝贺所有的获奖者。

我解决方案的关键在于训练了两个分割模型:seg1 使用 BCE loss 在所有数据上训练,seg2 仅在非空图像上使用 soft DICE loss 训练。我认为这之所以有效,是因为本次比赛基本上包含两个任务:1) 检测空图像;2) 为非空图像预测准确的掩码。这两个分割模型分别解决了这两个任务。

我是如何想到这个方法的

我以使用 BCE loss 的 resnet34-FPN 开始了这场比赛 (seg1)。该模型在 LB 上达到了约 0.608,主要贡献来自于捕捉空掩码:它捕捉了约 80% 的空掩码。我尝试了很多方法来改进非空部分,比如使用 BCE 和 DICE 的组合 loss,但同时提高 neg-dice(空掩码的 dice 分数)和 pos-dice(非空掩码的 dice 分数)很难。

为了准确预测非空掩码,我决定为非空图像训练 4 个独立的分割模型,然后将它们集成在一起。由于所有训练图像都是非空的,我们可以直接使用 soft DICE loss,模型将专注于预测准确的掩码。我使用了完全相同的网络结构 resnet34-FPN (seg2)。然后我简单地用 'seg2' 的预测替换了 seg1 模型的所有非空预测。仅 1 折的这个 2 阶段分割流程,没有 TTA,没有最小尺寸移除器,没有分类器,没有阈值调整(均为 0.5)就可以达到 LB 0.652。在加入 resnet34 分类器(0.5 阈值)后,我得到了 LB 0.655。

后来,我通过实现 pos-only soft DICE loss,成功在一个模型中训练了所有 4 个类别。代码如下:

def dice_only_pos(logits, labels, labels_fc):
    # logits -> 像素级预测
    # labels -> 像素级标签
    # labels_fc -> 图像/通道级标签
    pos_idx = (labels_fc > 0.5)
    neg_idx = (labels_fc < 0.5)
    loss = SoftDiceLoss()(logits[pos_idx], labels[pos_idx])
    return loss

这个 loss 只计算非空通道,忽略所有空通道。

总之,流程如下:

  • seg1: 使用 BCE loss 训练的多标签分割模型
  • seg2: 使用 pos-only soft DICE loss 训练的多标签分割模型
  • cls: 使用 BCE loss 训练的多标签分类器。

最终提交通过以下步骤实现:

  1. 使用 seg1 获取预测
  2. seg2 的预测替换 seg1 的非空掩码
  3. 使用 cls 移除更多的空掩码

像素级(分割)和图像级(分类器)阈值均为 0.5。

2 阶段分割的基线结果

模型摘要:

  • 网络: Resnet34-FPN
  • 图像大小: 384x576
  • Batch size: 16
  • 优化器: Adam
  • 调度器: seg1 使用 reduceLR,seg2 使用 warmRestart。
  • 增强: H/V flip, ShiftScalerRotate 和 GridDistortion
  • TTA: 原图, 水平翻转, 垂直翻转

结果:

  • 1-fold: 0.664
  • 5-fold + TTA3: 0.669
  • 5-fold + TTA3 + classifier: 0.670。

TTA1 表示仅原图;TTA3 表示原图 + H/V 翻转。

我剩下的工作只是尝试不同的 backbone 以找到最好的一个。我的最终模型是: