Task3: 进阶上分——赛题解析与新baseline解读#AI夏令营 #Datawhale #Datawhale AI 夏令营

Part1 精读赛题——确定隐含条件和提交数据格式

任务和主题

AI极端降水预报:提供历史时段伏羲气象大模型未来72小时逐小时的多个气象要素以及对应时段的ERA5降水数据,输出给定时段的基于伏羲气象大模型要素作为输入的AI极端降水预测。

比赛数据


数据为原始数据的标准分数Zscore,Zscore = (x - μ)/ σ 。ERA5降水, μ: 0.19359495,σ:0.6458292; FuXi降水, μ: 0.13014507,σ: 0.4056911。

1.ERA5

比赛目标数据来自欧洲中期天气预报中心(ECMWF)的再分析数据ERA5,使用了ERA5的子集,1个地面变量,时间间隔1小时,空间分辨率0.25度,覆盖区域(N18 ~ N32, E103 ~ E123)。

2.FuXi

比赛输入数据来自伏羲气象大模型的输出,伏羲大模型是复旦大学发布的数据驱动的气象大模型,数据分辨率0.25度,时间间隔1小时,包含地面和高空气压层多个气象要素,数据的输入格式为(1, 72, 24, H, W), 维度分别表示(batch, 时间, 特征或者通道, 纵向网格数, 横向网格数);我们需要的输出格式为(1, 72, H, W), 所以在定义网络的时候要特别注意这里

伏羲气象大模型的介绍详见:FuXi: a cascade machine learning forecasting system for 15-day global weather forecast | npj Climate and Atmospheric Science

  下载数据后, 我们会发现数据都是.nc格式的cdf数据, 需要我们使用xarray包来进行读取, (上文TASK2有提到过,根据baseline中的数据加载函数), 并且根据feature数据的时间戳来取对应的数据,需要注意的是为了避免在gt数据中找不到某些时间戳,我们需要对数据进行清洗在改进后的baseline中, dataset加载数据时, 会捕获这个异常并返回batch中的上一条数据(batch为1时即返回上一条batch).

Part2 速通新baseline——与原始baseline对比发现实验提升细节

  1. 首先在数据集加载中, 如同上文提到的, 如果尝试加载全部数据以后肯定会遇到报feature中的时间戳在gt上找不到的异常, dataset中的捕获异常就可以避免这个问题, 同时发现是哪部分数据缺失了

  2. 加载数据时, 原baseline中只定义了训练的dataloader, 新的baseline中定义了验证集的dataloader, 方便我们在每个epoch训练时查看当前epoch模型在验证集的表现, 判断模型效果

  3. from torch.utils.data import Dataset, DataLoader, random_split

    # Split the dataset into training and validation sets

    train_size = int(0.8 * len(my_data))

    val_size = len(my_data) - train_size

    train_dataset, val_dataset = torch.utils.data.random_split(my_data, [train_size, val_size])

    # Create data loaders for training and validation sets

    train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=1, shuffle=True)

    val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=1, shuffle=False)

  4. 模型训练时, 是首先从一个随机的数据通过逐步训练,更新参数,逐步变成拟合程度最好的模型, 因此如果模型的初始化合适的话, 模型会很快收敛, 变成拟合程度好的新模型. 本次新增baseline中, 增加了xvaier初始化 https://paperswithcode.com/method/xavier-initialization

  5. 新增了查看验证集loss的过程, 帮助我们判断哪些模型会是拟合程度更好的模型

  6. 一些超参数的调整,如学习率,权重衰减,训练周期epoch等

  并且原始baseline只是使用了单层的卷积神经网络,进阶baseline对模型架构进行了加深处理,使用了4个卷积层,并使用了BatchNormalization,和Relu激活函数。

import torch

import torch.nn as nn

# 实验1 加深模型

class EnhancedModel(nn.Module):

    def __init__(self, num_in_ch, num_out_ch):

        super(EnhancedModel, self).__init__()

        self.conv1 = nn.Conv2d(num_in_ch, 64, kernel_size=3, padding=1)

        self.batchnorm = nn.BatchNorm2d(64)

        self.activation = nn.ReLU()

        self.conv2 = nn.Conv2d(64, 64, kernel_size=3, padding=1)

        self.conv3 = nn.Conv2d(64, 64, kernel_size=3, padding=1)

        self.conv4 = nn.Conv2d(64, num_out_ch, kernel_size=3, padding=1)

   

    def forward(self, x):

        B, S, C, W, H = tuple(x.shape)

        x = x.reshape(B, -1, W, H)

        out = self.conv1(x)

        out = self.activation(out)

        out = self.conv2(out)

        out = self.activation(out)

        out = self.conv3(out)

        out = self.activation(out)

        out = self.conv4(out)

        out = self.activation(out)

        out = out.reshape(B, S, W, H)

        return out

   

# define model

in_varibales = 24

in_times = len(fcst_steps)

out_varibales = 1

out_times = len(fcst_steps)

input_size = in_times * in_varibales

output_size = out_times * out_varibales

model = EnhancedModel(input_size, output_size).cuda()

Part3 发散思路——简单谈谈上分的技巧

1.从数据角度

  本次数据的大部分是接近于0的值, 小部分会出现极值, 但是就是这部分极值反而是评分的关键。因此, 我们在使用数据时, 要想办法提高极值数据对于模型的贡献, 降低接近于0的值这部分数据对于模型的贡献。此外,越多的训练数据往往对于我们的模型会有更理想的拟合能力, 数据决定了模型的上限。

2.从模型角度

  本次baseline主要使用的是卷积神经网络的模型架构,在这个模型架构的基础上,我们可以对模型进行加深。详细参考上图代码

3.从损失函数角度

刚开始的baseline使用的是MSELoss,进阶baseline提供了另一种损失函数SmoothL1Loss。

我查阅相关数据后,有如下说明

MSELoss 是一种非常直观的损失函数,它计算的是预测值和真实值之间差的平方的均值。具体公式如下:

[
\text{MSE} = \frac{1}{N}\sum_{i=1}^{N}(y_i - \hat{y}_i)^2
]

其中:
- \( y_i \) 是第 \( i \) 个样本的真实值。
- \( \hat{y}_i \) 是第 \( i \) 个样本的预测值。
- \( N \) 是样本的数量。

MSELoss 的优点在于它对大的误差非常敏感,因为误差被平方了。这使得模型更加倾向于减小较大的预测误差。然而,这也意味着如果数据集中存在一些极端值(即异常值),MSELoss 可能会导致模型过分关注这些异常值,而忽略其他样本。

Smooth L1 Loss,也称为 Huber Loss,是一种结合了 MSE 和 MAE (Mean Absolute Error) 的损失函数。它在误差较小时使用 MSE 的形式,而在误差较大时则使用 MAE 的形式。这种损失函数的设计目的是为了减少异常值的影响,同时保持对误差的敏感性。

Smooth L1 Loss 的定义如下:

\[
\text{SmoothL1Loss}(\delta) = \begin{cases}
0.5 (y - \hat{y})^2 & \text{if } |y - \hat{y}| < \delta \\
\delta (|y - \hat{y}| - 0.5 \delta) & \text{otherwise}
\end{cases}
\]

其中:
- \( \delta \) 是一个超参数,用于控制损失函数从 MSE 到 MAE 的转变点。

Smooth L1 Loss 的优点在于它对异常值的敏感度较低,因为它在误差较大时使用绝对值而不是平方。这有助于模型更加稳健,不过它也可能导致模型对较大的误差不够敏感。

 比较

1. 对大误差的敏感度:
   - MSELoss 对大误差非常敏感,这意味着它会强烈惩罚模型的大误差。
   - Smooth L1 Loss 对大误差的惩罚较小,这使得模型更不容易受到异常值的影响。

2. 对异常值的鲁棒性:
   - MSELoss 对异常值非常敏感,可能会导致模型过分关注这些值。
   - Smooth L1 Loss 更加鲁棒,因为它在误差较大时采用 MAE 形式,降低了异常值的影响。

3. 适用场景:
   - 如果数据集中存在异常值,或者你希望模型对异常值不太敏感,那么 Smooth L1 Loss 可能更适合。
   - 如果数据集相对干净,没有太多异常值,或者你希望模型能够更好地捕捉较大的误差,那么 MSELoss 可能更为合适。

  而在我们的具体需求情况下,由于数据包含大量接近零的值和少量极值,而这些极值又是评分的关键,因此可能需要一种损失函数来降低对接近零值的敏感度,同时对高值敏感, 加更大的惩罚项,对极值保持较高的敏感度。在这种情况下,Smooth L1 Loss 可能是一个更好的选择,因为它在一定程度上减少了对异常值的敏感度,同时仍然保持了对大误差的一定敏感度。

4.从epoch角度

  进阶baseline训练了多个epochs,并打印了每个epoch验证集上的Validation Loss

5.其他

学习率(比如使用学习率衰减或Cosine Annealing等策略)、优化器、优化器的schedual、训练的周期(在验证集上的性能不再提升时停止训练,防止过拟合)、验证集和训练集划分比例等等...超参数的调整(使用网格搜索、随机搜索或贝叶斯优化等方法进行超参数调优)只能通过大量的实验才能找到合适的部分

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值