349. Understanding Clouds from Satellite Images | understanding_cloud_organization
大家好,
恭喜获奖者!
我的解决方案代码在这里。
以下是解释说明。
| 排名 | 分数 | 百分位 |
|---|---|---|
| 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 进行缩放并四舍五入为整数,这样我就可以保存为