返回列表

34th Place Solution + Code

349. Understanding Clouds from Satellite Images | understanding_cloud_organization

开始: 2019-08-16 结束: 2019-11-18 气象预报 数据算法赛
第34名解决方案 + 代码

第34名解决方案 + 代码

作者:Karl Hornlund | 排名:34 | 得分:0.66385

大家好,

恭喜获奖者!

我的解决方案代码在这里

以下是解释说明。

摘要

结果

排名 分数 百分位
34 0.66385 前 2.2%

策略

起初,我有一个想法,与这篇最近的论文非常相似。我打算在标记数据上训练模型,然后迭代地为未标记数据创建伪标签并在此基础上进行训练。我认为这是实施该策略的好机会,因为训练数据很少(约5000张图像),所以通过生成更多训练样本可以获得很多收益。而且,因为这不是同步内核竞赛,我可以创建任意大的集成模型。

后来我意识到图像标签的噪声有多大,不太确定伪标签是否能很好地工作。特别是,我注意到模型的验证分数超级嘈杂——使用相同的配置但不同的随机种子会导致严重的指标差异。我想我应该放弃微调单个模型,转而专注于设计一个系统,允许我训练和集成大量模型。

我开发了一些功能,使我能够自动化配置、训练和模型推理。

我训练了一个由约120个模型组成的集成模型,使用了多种编码器/解码器组合。我首先按它们的编码器/解码器组合将它们平均在一起(例如,所有的 efficientnet-b2 FPN 放在一起平均)。然后,我使用加权平均将这些小型集成模型平均在一起。

在比赛还剩大约一周的时候,我看到了 Noisy Student 论文。我在 LB(排行榜)上取得了不错的成绩,想尝试一下伪标签。我下载了约4200张图像,使用与官方数据相同的分辨率和位置,为它们生成伪标签,并训练了一个新的约50个模型的集成。

我只在最后一天及时完成了伪标签模型的训练,只来得及提交几次,并在公共 LB 上达到了 0.67739(第9名)——但实际上在私有 LB 上仅得了 0.66331(约第45名)。我选定的另一个提交是我过去25次提交的加权平均,在公共 LB 上得分为 0.67574,在私有 LB 上得分为 0.66385(第34名)。

我有几个未选定的提交得分在 0.666+(约第18名),有趣的是,其中最好的来自一个仅由 efficientnet-b2-Unet 模型组成的小型集成。

反思

回首过去,我意识到我犯了一个相当大的错误,没有获取适当的指标来进行彻底的本地 CV(交叉验证)。我只记录了阈值为 0.5 时的 Dice 系数,因此我没有充分的信息来为提交选择阈值。

此外,虽然每个模型都在随机80%的数据上训练,并在剩余的20%上进行评估,但这只是在单个模型层面上进行的。我没有保留一个留出集来验证集成模型。因为我们只有约5000个训练样本,我在这里对训练数据有点贪心。

我曾希望通过记录我所有实验的日志,一段时间后我能够识别出哪些随机生成的配置(例如学习率)比其他的更好。结果并非如此!我应该花更多时间微调每个模型,因为随着集成规模的扩大,收益递减规律开始显现。

详情

集成流程

实现见 uco.ensemble.py

每个训练实验都使用一个 YAML 文件进行配置,该文件被加载到字典中。我设置了一个类来随机化这些参数,这样我就可以在工作/睡觉时让它运行,它会循环使用不同的架构、损失函数和其他参数。

在每个训练周期后,模型将在20%的验证集上进行评估。平均 Dice 分数在整个训练过程中被跟踪,当训练完成(在设定的 epoch 数或早停后),只有得分最高的检查点会被保存。我设定了一个平均 Dice 分数截止值,并丢弃低于该分数的模型。

加载保存的检查点,并在测试数据上运行推理。我将每个模型的原始(sigmoid)预测结果保存为 HDF5。我按 250 进行缩放并四舍五入为整数,这样我就可以保存为

同比赛其他方案