617. LEAP - Atmospheric Physics using AI (ClimSim) | leap-atmospheric-physics-ai-climsim
感谢 Learning the Earth with Artificial Intelligence and Physics (LEAP) NSF 科学技术中心和 Kaggle 举办这场有趣的竞赛,这场竞赛的交叉验证 (CV)、公共排行榜 (LB) 和私人排行榜 (PB) 都非常稳定。
考虑到我的英语不是特别好,这篇文章是在 chatgpt 的辅助翻译下写的。我会检查并进行修正。
推理代码以证明无泄漏:LEAP_11th_PB0.78491
业务背景: https://www.kaggle.com/competitions/leap-atmospheric-physics-ai-climsim/overview数据背景: https://www.kaggle.com/competitions/leap-atmospheric-physics-ai-climsim/data我的最终提交由 6 个模型(具有 5 种不同的架构)集成在一起(重要)。所有模型都使用残差结构。所有模型都在 0001-02 到 0008-01 的完整数据集(低分辨率)上进行训练,并在从 0008-02 到 0009-01 采样的约 170 万行数据上进行验证。输入处理同时使用了标准化、对数变换和嵌入。模型经过了多阶段的精心训练(重要)。模型集成的权重是使用基于 0008-02 到 0009-01 数据的爬山算法确定的。
| 模型架构 | 块数量 | 嵌入维度 | 参数数量 | CV | 文件名 |
|---|---|---|---|---|---|
| bi-LSTM + MLP | 7 | 8 | 5070534 | 0.71969 | v4_1 |
| bi-LSTM + MLP | 17 | 16 | 49089054 | 0.72703 | v4_1 |
| bi-LSTM + MLP + BN | 7 | 8 | 5238534 | 0.72493 | v4_8 |
| bi-GRU + MLP + BN | 9 | 8 | 5286134 | 0.72536 | v5_1 |
| bi-RNN + MLP + BN | 17 | 8 | 4511734 | 0.71692 | v8_1 |
| 1D-CNN + BN | 11 | 8 | 16854334 | 0.71459 | v6 |
| 集成 (Ensemble) | 0.73472 (PB: 78491) |
根据我的对抗验证实验,年份之间的数据存在显著差异 (AUC=1)。根据组织者的信息,理论上应该有十亿条数据(但 HuggingFace 上只有约 8000 万条)。因此,可以推测测试集来自后几年的数据。考虑到上述信息,我使用 0001-02 到 0008-01 的数据进行训练,使用 0008-02 到 0009-01 的数据进行验证。也许这就是为什么我能够攀升 PB 排名并进入金牌区的原因。
原始输入有 556 列。我删除了只有 1 个值的 66 列,剩下 490 列。对于每一列数据,我执行两个操作:一个是直接标准化它 (X - x_mean) / x_std,另一个是取绝对值后应用对数然后标准化 (CV +0.003)。(log_X - log_x_mean) / log_x_std 所以我模型的输入形状是 (980,)
对于模型的 980 个输入中的每一个,都分配了一个嵌入,初始化范围为 [-0.05, 0.05]。这个初始化范围至关重要,因为其他初始化方法可能会导致性能较差。
通过填充和重塑,输入最终变为 (bs, 60, 25*emb_dim)。
对于 bi-LSTM + MLP + BN,bi-GRU + MLP + BN,bi-RNN + MLP + BN,模型结构都按以下方式排列,唯一不同的是编码层。
pre_seq = seq # (bs, 60, 25*emb_dim)
for i in range(len(self.encoder_layers)):
encoder_layer = self.encoder_layers[i]
seq, _ = encoder_layer(seq) # (bs, 60, 25*emb_dim*2)
ffn = self.mlp[i]
seq = ffn(seq) # (bs, 60, 25*emb_dim)
seq = seq.contiguous().view(bs, -1) # (bs, 60*25*emb_dim)
seq = self.mlp_bn[i](seq) # (bs, 60*25*emb_dim)
seq = seq.contiguous().view(bs, 60, -1) # (bs, 60, 25*emb_dim)
seq = F.gelu(seq)
seq = seq + pre_seq # (bs, 60*25*emb_dim)
pre_seq = seq
对于 1D-CNN + BN,模型结构如下
pre_x = x
for i in range(len(self.cnns)):
x = self.cnns[i](x) + pre_x
pre_x = x
模型的完整代码可以在这里的 'model' 文件夹中找到。https://www.kaggle.com/datasets/uesugierii/leap-final?select=model
在训练过程中,发现直接在完整数据集(低分辨率)上训练会导致分数较低。经过 EDA 后发现,训练不稳定的主要原因是异常值。
为了解决这个问题,我采用了两种独立的方法来缓解:
np.clip(x, -10, 10), np.clip(y, -10, 10)),首先在较小的范围内拟合(15 个 epoch,学习率 1e-3),然后在原始数据上拟合(15 个 epoch,学习率 1e-4)。这背后的理由是首先让模型学习并适应相对正常的天气条件,然后再推广到更极端的天气变化。为了在最后获得轻微的性能提升,我会在极大的批量大小 (10240) 和非常低的学习率 (1e-5) 下训练模型几个 epoch。一些模型能够实现进一步的增强 (CV +0.004)。