感谢主办方 @jerrylin96 和官方 Kaggle 团队组织了这场有趣的竞赛!我们团队从中受益匪浅!
我很高兴分享我们团队的解决方案。完整代码可在 GitHub 上获取:https://github.com/ChunhanLi/2nd-kaggle-LEAP
摘要
我们在大气预报方面没有广泛的领域知识;我们 simply 将竞赛任务框架化为一个 1D seq2seq 多目标回归任务。我们训练了各种模型结构并 meticulously 调整了它们,最终基于验证集分数使用爬山算法进行模型集成。
解决方案中的四个最高优先级关键点总结如下:
- 数据大小在本竞赛中至关重要。 使用整个 低分辨率数据集 可以显著提升性能。
- 采用了 SmoothL1 损失函数、辅助差分损失和余弦退火学习率调度器进行模型优化。
- 在训练流程中引入了分组微调方法。
- 团队专注于开发多样的模型结构并进行集成。
解决方案
数据与交叉验证
训练数据
训练数据对于本竞赛至关重要。根据这个 GitHub 仓库,Kaggle 数据是从这个 低分辨率数据集 中采样的。利用整个低分辨率数据集可以在本竞赛中将性能提升近 0.01。
交叉验证
我们的模型使用前 7 年和第 8 年上半年(1 月至 6 月)的数据进行训练,总计约 7500 万个数据点。我们将 stride_sample 参数设置为 7,并使用第 8 年 7 月至 12 月和第 9 年 1 月的数据作为保留验证数据集。该验证集与排行榜分数显示出完美的相关性。
模型优化
Smooth L1 损失
Smooth L1 损失是一种主要用于回归任务的稳健损失函数,结合了 L2 和 L1 损失的优点。它比 L2 对异常值不那么敏感,并避免了 L1 在零处的不可微性。函数定义如下:
这种方法有助于稳定训练过程,并通常在噪声数据情况下提高性能。
辅助差分损失 (Auxiliary Diff Loss)
我们使用由 @zui0711 提出的辅助'Diff Loss'来增强学习。该损失计算目标相邻层级之间真实值和预测值之间的差异,使用 Smooth L1 损失来量化误差。实现方法如下:
with torch.no_grad():
outputs = model(inputs)
loss = criterion(outputs, labels)
for i in range(6):
output_diff = outputs[:, 8+60*i+1:8+60*(i+1)] - outputs[:, 8+60*i:8+60*(i+1)-1]
label_diff = labels[:, 8+60*i+1:8+60*(i+1)] - labels[:, 8+60*i:8+60*(i+1)-1]
loss += criterion(output_diff, label_diff) / 6
余弦退火调度器 (Cosine Annealing Scheduler)
余弦退火调度器以余弦曲线调整学习率,帮助模型逃离局部最小值并改善收敛。我们在第 3 和第 9 个 epoch 实施了学习率衰减。
分组微调 (Group Fine-tune)
在多目标学习任务期间,不同的学习目标可能会以复杂的方式相互作用,相互促进或抑制。我们的实验发现,虽然不同的目标组最初相互促进,但在训练后期开始相互干扰,这可能是由于复杂的语义约束。
受 2021 VPP 竞赛顶级解决方案 的启发,我们将 368 个特征分为七组,其中六组是沿大气柱不同指标的测量序列,一组由八个独特的单一目标组成。在完成 364 个完整输出的训练过程后,我们再次对这些组进行了微调。这使得具有不同架构的每个模型都能获得 0.0005 到 0.0015 的提升。由于时间和资源限制,我们只对每个组微调了一个 epoch。@max2020
后处理
获得原始模型预测后,我们使用标准差和均值对其进行反归一化。遵循社区 讨论,我们根据其线性关系调整了 ptend_q0002 的某些变量。最后,我们应用官方示例提交文件中的权重值来处理预测。
模型结构
Forcewithme 的模型
表 1
| 模型 ID | 私榜 (PB) | 图表 | 实验 ID |
|---|---|---|---|
| forcewithme_reslstm_cv0.789_lb0.783 | 0.78275 | Figure 3(a) | 18 |
| forcewithme_gf_reslstm_cv0.790_lb0.785 | 0.7840 | Figure 3(a) | 32 |
| forcewithme_gf_cnnlstm_cv0.789_lb0.787 | 0.7826 | Figure 3(b) | 39 |
| forcewithme_gf_lstmmamba_cv0.7885_lb0.7853 | 0.7814 | Figure 3(c) | 40 |
| forcewithme_gf_LstmMambaMixed_cv0.7886_lb0.7858 | 0.7821 | Figure 3(d) | - |
| forcewithme_gf037_1LSTM1mamba-5_state16_cv0.7896_LBunknown | 0.7830 | Figure 3(d) | 37 |
| forcewithme_gf038_2LSTM1mamba-3_state64_cv0.7897_LB0.787 | 0.7836 | Figure 3(d) | 38 |
最终的集成策略包含 6 个 ForcewithMe 的模型。这 6 个模型、私榜分数、相应的架构以及表 2 中相应的"exp id"都在上表中。模型架构易于理解,并可通过相应的图表和代码实现。以下是一些细节和见解:
所有模型都在其模型 ID 中显示了本地分数和公共排行榜 (LB) 分数,这直接对应于文件名、模型名称和提交文件(无扩展名)。表格补充了私榜分数和模型架构的详细信息。
所有模型主要构建自 LSTM 作为主要组件。这是因为我们发现 LSTM 在本竞赛中显著优于其他架构,如 CNN、MHSA、NN 和 GRU。
受 ResNet 和 Transformer 的启发,我所有的模型都结合了残差连接。我们相信残差使模型收敛更快且表现更好。
图 3(a) 描绘了一个简单的 ResLSTM 结构,令人惊讶的是,它在所有模型中取得了最高的私榜分数。此外,我的另一个提交花了两周多的时间才在本地分数和公共排行榜上击败这个残差 LSTM 模型。此外,ResLSTM 在私榜上仍然更好。exp32 与 exp 18 具有相同的架构。前者恢复了后者的权重并应用了分组微调。
图 3(b) 说明了一个模型,结合了小核卷积、大核卷积和 LSTM 作为编码器,编码结果concatenated 后 fed 进入 LSTM 骨干网络。该设计利用了相邻大气层之间的假定关系,旨在建模局部信息和位置关系。虽然它在离线和私榜上的表现不如纯 resLSTM 模型,但它在公共排行榜上得分更高,并在集成期间提供了增益。
其余四个模型将 LSTM 与 MAMBA 相结合。虽然 LSTM 通常有更多的层,但在模型
forcewithme_gf037_1LSTM1mamba-5_state16_cv0.7896_LBunknown中,MAMBA 占据了与 LSTM 相同的层数。在每个块中混合 LSTM 和 Mamba (3d) 的模型在离线和公共排行榜上都取得了非常好的分数。
尽管单个基于 MAMBA 的模型没有超过纯 LSTM 结构,但它们在最终集成中发挥了重要作用。
"mamba-ssm"包中有两个版本的 MAMBA 可用:MAMBA 和 MAMBA-2。我们 exclusively 使用了 MAMBA。
MAMBA 的默认参数为:
d_model=512,d_state=16,d_conv=4, expand=2。除了d_model外,参数设置遵循官方仓库。模型
forcewithme_gf037_1LSTM1mamba-5_state16_cv0.7896_LBunknown每个块中有 1 个 LSTM 和 1 个 MAMBA,它有 5 个块,mamba 使用默认参数设置。而模型forcewithme_gf_LstmMambaMixed_cv0.7886_lb0.7858和forcewithme_gf038_2LSTM1mamba-3_state64每个块中有 2 个 LSTM 和 1 个 mamba,它们有 3 个块。模型
forcewithme_gf_LstmMambaMixed_cv0.7886_lb0.7858和forcewithme_gf038_2LSTM1mamba-3_state64的区别仅在于后者将d_state设置为64。它们共享图 3(d),因为它们几乎相同。关于 MAMBA 的安装和使用,请参考官方仓库:https://github.com/state-spaces/mamba?tab=readme-ov-file。它根据 Apache-2.0 许可,允许免费使用,包括商业目的,只要满足许可要求。
Max2020 的模型
在 Max2020 部分,模型 14、15、21 和 22 都是基于 @forcewithme 的模型的改进,集成了带有跳跃连接的 LSTM。模型 22 是我们团队表现最好的单个模型,在本地评分、排行榜评分和私榜评分中提供了最佳结果。其架构如图 4 所示。关于学习率调度,使用了余弦衰减学习率,衰减发生在第 3 和第 9 个 epoch。采用的损失函数是 beta 为 0.5 的 Smooth L1 损失。表 2 包含了我五个模型的详细性能。
Joseph Zhou 的模型
Joseph 模型的结构主要包括使用多层 Res-ConvLSTM 块和 TimeDistributed 全连接层。输入大小为 [bs, 60, 25],输出大小为 [bs, 368],输入的最后一维包括 16 个序列特征和 9 个标量特征。经过多层 Res-ConvLSTM 块和全连接层后,结果大小为 [bs, 60, 14],最后一维包括 6 个序列标签和 8 个标量标签。对于 [bs, 60, 8] 的标量标签部分,我们只是在第二轴上取平均以获得 [bs, 8] 的形状。对于 [bs, 60, 6] 的序列标签部分,我们将其重塑为 [bs, 360] 的形状。最后,我们连接这两部分以获得输出。此外,在其中一個模型中实现了反向和移位类型的增强。想法是在数据加载器中随机反向或移位序列特征和序列标签。
Adam 的模型
Adam 模型的结构如下:Inputs -> Position encoding -> 1DCNN -> 3-4 layers LSTM -> 1 layer transformer -> Outputs。大多数模型使用了所有低分辨率数据集,其他模型仅使用采样数据。由采样数据训练的模型可以为集成贡献一点。对于损失,Adam 使用了前面提到的 SmoothL1 损失和辅助差分损失。对于调度器,Adam 使用了 ReduceLROnPlateau 调度器,factor 为 0.2,patience 为 2。
Adam 最好的单个模型 LB 为 0.78594,PB 为 0.78141。Adam 模型的集成 LB 为 0.79050,PB 为 0.78575。
Zuiye 的模型
Zuiye 的模型主要基于两种架构。第一种由 2 个 LSTM 层后跟一个 MultiheadAttention 层组成。另一种由 3 个具有不同核大小的并行卷积层组成,然后是 2 个 LSTM 层,后跟一个 MultiheadAttention 层,就像第一种架构一样。Zuiye 最好的单个模型获得 LB 0.78696 / PB 0.78205,Zuiye 自己模型的集成(带有爬山法)获得 LB 0.79050 / PB 0.78614。
模型集成
我们使用爬山法来搜索每个模型的混合权重。爬山法的步骤如下:@hookman
- 将最好的折外预测作为 best_ensemble。这将是我们的基线。
- 使用公式
new_ensemble = w * best_ensemble + (1-w) * new_oof迭代地将 best_ensemble 与不同权重的不同模型混合。 - 检查新集成的 r2 分数。选择最好的新集成替换 best_ensemble 作为我们的新基线。
- 重复直到 r2 分数无法再增加或达到阈值。
最佳模型的权重如下表所示:
表 2
| 实验 ID | 权重 | CV | LB | PB |
|---|---|---|---|---|
| forcewithme_exp32 | 0.166556 | 0.790 | 0.7865 | 0.78398 |
| forcewithme_exp37 | 0.158625 | 0.7896 | 0.78618 | 0.78293 |
| forcewithme_exp38 | 0.139194 | 0.7897 | 0.78719 | 0.78362 |
| max_exp22 | 0.120125 | 0.7908 | 0.78793 | 0.78434 |
| Jo_exp912 | 0.111971 | 0.78935 | 0.78528 | 0.78150 |
| max_exp21 | 0.104738 | 0.7904 | 0.78752 | 0.78425 |
| forcewithme_exp39 | 0.098977 | 0.789 | 0.78699 | 0.78257 |
| max_exp14 | 0.093088 | 0.7905 | 0.78641 | 0.78214 |
| max_exp10 | 0.092157 | 0.7888 | 0.78619 | 0.78213 |
| forcewithme_exp40 | 0.082941 | 0.7885 | 0.7853 | 0.78261 |
| max_exp015 | 0.052500 | 0.7905 | 0.78695 | 0.78244 |
| adam_exp197 | 0.048994 | 0.7855 | 0.78269 | 0.777 |
| adam_exp200 | -0.047132 | 0.7836 | 0.78010 | 0.77434 |
| adam_exp195 | -0.049875 | 0.78569 | 0.78334 | 0.77753 |
| Jo_exp907 | -0.083779 | 0.7855 | 0.78289 | 0.77873 |
| forcewithme_exp18 | -0.089079 | 0.7890 | 0.7863 | 0.78272 |
| 集成 | 1.0 | 0.7955 | 0.79211 | 0.78856 |
值得注意的是,我们已在 Google Drive 上提供了所有模型的参数权重文件。使用这些文件进行集成提交会导致 LB 和 PB 分数略高,幅度为 0.0002。差异源于两个主要问题:
首先,jo_exp907.pt 模型文件丢失,模型必须在竞赛后重新运行,这导致与原始文件存在一些差异。其次,在竞赛期间,forcewithme_exp18 下使用了错误的模型文件(对应于 forcewithme_reslstm_cv0.789_lb0.783 文件夹)。现在已更正。这两点导致了我们最终结果的非常微小的差异。虽然我们认为这种差异不会影响我们整体方法的可复现性,但我们在此提及以避免任何混淆。