Datawhale AI 夏令营:从零入门 AI for Science(AI+气象)----Task 2

Task3: 进阶上分——赛题解析与新baseline解读

原任务地址:https://linklearner.com/activity/12/5/17

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

在参与地理科学领域的降水预测竞赛时,深入理解数据特性和评分标准是取得成功的关键。本次竞赛要求参赛者使用伏羲大模型提取的特征数据,并结合ERA5再分析数据集,预测未来降水情况。数据的精确处理、模型的合理构建以及评分标准的明确理解,都是影响最终成绩的重要因素。

  1. 数据来源与类型

    • 输入特征数据(Feature)来自伏羲大模型。
    • 真实降水数据(Ground Truth)基于欧洲中期天气预报中心的ERA5再分析数据的子集。
  2. 数据特性

    • 数据类型:浮点型,具体为float16。
    • 数据值域:最小值约-0.3,最大值可能高达10-50毫米或更高,大部分数据点的值很小。
  3. 数据物理意义

    • ERA5数据表示的是一段时间内的平均降水量。
    • 数据抽样频率:每小时一次,表示一小时内的平均降水量。
    • 单位:毫米每小时。
  4. 数据格式

    • 输入数据格式为(1, 72, 24, H, W),分别代表批次、时间、特征/通道、纵向网格数和横向网格数。
    • 输出数据格式应调整为(1, 72, H, W),去除特征或通道维度。
  5. 数据处理

    • 数据格式:.nc格式的CDF数据,需要使用xarray包来读取。
    • 数据清洗:处理时间戳异常,确保数据完整性。
  6. 评分标准

    • 使用临界成功指数(CSI)进行评分,计算公式为CSI=hitshits+false_alarms+missesCSI=hits+false_alarms+misseshits​。
    • 极端降水定义:24小时累积降水量超过50毫米。
  7. 实验策略

    • 输出数据应使用ReLU激活函数,以确保数据在合理范围内,避免负值。
    • 训练时应避免大部分接近0的值对模型造成的负影响。
    • 训练模型以更准确地预测极端降水值,这些值对评分有重要贡献。
    • 进行数据集清洗,创建新的数据集或根据异常剔除空数据。
  8. 训练效果

    • 使用改进后的baseline和多数据训练后,可以显著提升分数。

综合分析所提供的竞赛资料,我们得出以下结论:竞赛要求参赛者处理和分析特定格式和类型的降水数据,使用特定的数据读取工具,并通过数据清洗确保数据质量。在模型构建时,需要使用ReLU激活函数来限制输出值的范围,同时在训练过程中注意避免大量接近零的值对模型性能的负面影响。此外,极端降水的准确预测对于提高临界成功指数(CSI)评分至关重要。通过改进数据集和训练方法,参赛者可以有效提升模型的预测性能,从而在竞赛中取得更好的成绩。

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

在本次竞赛的降水预测任务中,新baseline的引入带来了显著的改进,这些改进不仅优化了数据处理流程,还提升了模型训练的效率和性能。通过对比新旧baseline,我们可以清晰地看到在数据集加载、模型初始化、训练监控以及超参数调整等方面的具体提升细节。这些改进对于提高模型的泛化能力和预测精度具有重要意义。

  1. 数据集加载改进

    • 原始baseline在加载数据时可能会遇到时间戳异常的问题,即feature数据中的时间戳在ground truth数据中找不到。
    • 新baseline通过捕获异常来解决这个问题,并能识别出数据缺失的部分。
  2. 数据加载器(Dataloader)扩展

    • 原始baseline只定义了训练集的dataloader。
    • 新baseline增加了验证集的dataloader,这使得在每个epoch结束时能够评估模型在验证集上的表现,从而监控模型效果。
  3. 模型初始化

    • 模型训练开始于随机初始化的状态,通过逐步训练更新参数,最终达到较好的拟合程度。
    • 新baseline引入了Xavier初始化方法,这有助于模型更快收敛。Xavier初始化是一种权重初始化方法,可以保持网络各层的激活值和梯度的方差一致,从而加速收敛。
  4. 验证集损失监控

    • 新baseline增加了在训练过程中监控验证集损失的功能,这有助于评估模型的拟合程度,选择最佳的模型参数。
  5. 超参数调整

    • 新baseline对一些关键的超参数进行了调整,包括学习率、权重衰减(正则化项)和训练周期(epoch数)。

总结:

新baseline相较于原始baseline,在数据处理、模型初始化、训练监控和超参数调整方面进行了优化。这些改进有助于提高模型的训练效率和预测性能,从而在竞赛中取得更好的成绩。具体来说:

  • 数据集加载的改进减少了因时间戳不匹配导致的数据丢失问题。
  • 增加验证集dataloader有助于实时监控模型在未见数据上的表现。
  • Xavier初始化方法有助于模型更快地收敛到较好的拟合状态。
  • 验证集损失的监控为选择更好的模型提供了依据。
  • 超参数的调整则进一步优化了模型的训练过程。

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

新baseline的分析显示了在竞赛中对原有方法进行优化的几个关键方面:

  1. 数据集加载的改进

    • 通过捕获异常,新baseline解决了原始baseline中由于时间戳不匹配导致的数据加载问题。这不仅避免了训练过程中的错误,还帮助识别数据缺失的部分,从而确保了数据集的完整性。
  2. 增加验证集dataloader

    • 新baseline扩展了数据加载器的功能,包括了验证集的dataloader。这一改进允许参赛者在每个训练周期结束时评估模型在验证集上的表现,为模型的调优和选择提供了即时反馈。
  3. 模型初始化的优化

    • 引入Xavier初始化方法,新baseline改善了模型权重的初始状态。这种初始化有助于平衡网络中前向传播和反向传播过程中的梯度大小,加速模型的收敛速度。
  4. 验证集损失的监控

    • 新baseline增加了对验证集损失的监控,这为评估模型的泛化能力提供了重要指标。通过观察损失的变化,可以及时发现模型是否过拟合或欠拟合。
  5. 超参数的调整

    • 对学习率、权重衰减和训练周期等超参数的调整,新baseline使模型训练过程更加灵活和高效。合理的超参数设置对于找到最优模型至关重要。

补充分析

  • 数据预处理:新baseline可能还包含了对数据预处理的改进,例如归一化或标准化,这有助于模型更快地学习和更好地泛化。
  • 正则化技术:除了权重衰减,可能还引入了其他正则化技术,如Dropout或L1/L2正则化,以减少模型的复杂度和防止过拟合。
  • 优化算法:新baseline可能采用了不同的优化算法,如Adam或RMSprop,这些算法可能更适合特定类型的数据或模型结构。
  • 早停法(Early Stopping):作为一种避免过拟合的技术,早停法可以在验证集损失不再降低时停止训练,这可能在新baseline中得到应用。

新baseline的这些改进,不仅提高了模型训练的效率,还增强了模型的预测能力和泛化性,对于竞赛中的降水预测任务来说,这些优化是提升成绩的关键。

baselin的修改

在深度学习领域,模型的改进通常旨在增强其特征提取能力、提高泛化性、以及优化计算效率。在您提供的代码中,通过引入PSA(Prioritized Split Attention)模块,对原有的MetNet模型进行了创新性的改进。PSA模块的集成,结合了多尺度特征提取和通道注意力机制,不仅丰富了模型对降水预测中关键特征的识别,还强化了模型对输入数据的自适应性。这种改进使得模型能够更加精准地捕捉到降水模式的细微变化,同时保持了计算上的高效性。以下是对模型各部分的详细分析,以及这些改进如何共同作用于提升模型性能的全面解释。

import torch.nn as nn
import torch


class Model(nn.Module):
    def __init__(self, num_in_ch, num_out_ch):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(num_in_ch, num_out_ch, 3, 1, 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 = out.reshape(B, S, W, H)
        return out


import torch.nn.functional as F


class Encoder(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Encoder, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=1)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = self.pool(x)
        return x


class Decoder(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Decoder, self).__init__()
        self.deconv1 = nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=1)
        self.conv1 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)

    def forward(self, x):
        x = F.relu(self.deconv1(x))
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        return x



class SPCModule(nn.Module):
    def __init__(self, channels, kernel_sizes, groups):
        super(SPCModule, self).__init__()
        self.splits = nn.ModuleList()
        self.kernel_sizes = kernel_sizes
        self.groups = groups
        for i, (kernel_size, group) in enumerate(zip(kernel_sizes, groups)):
            self.splits.append(self._make_split_conv(channels, kernel_size, group))

    def _make_split_conv(self, in_channels, kernel_size, group):
        # 修改后的代码,确保out_channels能够被groups整除
        mid_channels = (in_channels // group) * group
        layers = [
            nn.Conv2d(in_channels, mid_channels, kernel_size, groups=group, padding=kernel_size // 2),
            nn.ReLU(inplace=True),
            nn.Conv2d(mid_channels, mid_channels, 1, groups=group)
        ]
        layers.append(nn.ReLU(inplace=True))
        return nn.Sequential(*layers)

    def forward(self, x):
        split_features = [split_conv(x) for split_conv in self.splits]
        return torch.cat(split_features, dim=1)


class SEWeightModule(nn.Module):
    def __init__(self, channel, reduction=16):
        super(SEWeightModule, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)  # Global Average Pooling
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        avg_out = self.avg_pool(x).view(b, c)  # Squeeze operation
        avg_out = self.fc(avg_out).view(b, c, 1, 1)  # Excitation operation
        out = x * avg_out.expand_as(x)  # Rescale
        return out


class PSAModule(nn.Module):
    def __init__(self, in_channels, kernel_sizes=[3, 5, 7], groups=[1, 4, 8], reduction=16):
        super(PSAModule, self).__init__()
        k = len(kernel_sizes)
        self.spc = SPCModule(in_channels, kernel_sizes, groups)
        self.conv = nn.Conv2d(in_channels * k, in_channels, 1, 1)
        self.se = SEWeightModule(in_channels, reduction)

    def forward(self, x):
        x = self.spc(x)
        x = self.conv(x)
        x = self.se(x)
        return x


class PSA_MetNet(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(PSA_MetNet, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, 128, 3, 1, 1)
        self.PSA = PSAModule(64)
        self.encoder = Encoder(128, 64)  # 确保Encoder的输入通道数为128
        self.decoder = Decoder(64, out_channels)  # 确保Decoder的输入通道数为64

    def forward(self, x):
        B, S, C, W, H = tuple(x.shape)
        x = x.reshape(B, -1, W, H)  # 调整输入数据的形状
        x = self.conv1(x)
        encoded = self.encoder(x)
        y = self.PSA(encoded)
        decoded = self.decoder(y)
        decoded = decoded.reshape(B, S, W, H)  # 调整输出数据的形状
        return decoded

代码定义了几个用于图像处理任务的神经网络模型,特别是针对具有序列数据的降水预测模型。以下是对代码中各个组件的详细分析及改进理由:

基础模型(Model):
  • 这是一个简单的卷积神经网络,包含一个卷积层,用于提取输入数据的基本特征。然而,它没有进一步的特征提取或降维机制。
编码器(Encoder):
  • 编码器由两个卷积层和一个池化层组成,目的是提取特征并降低数据的空间维度。卷积层使用ReLU激活函数引入非线性,而池化层有助于减少参数数量和计算量。
解码器(Decoder):
  • 解码器通过转置卷积层和卷积层逐步恢复数据的空间维度,同时学习如何从编码的特征中重建输出。转置卷积通常用于上采样,而后续的卷积层用于细化特征图。

SPCModule(Split and Convolution Module):
  • SPCModule通过分组卷积和不同大小的卷积核提取多尺度特征。这种方法允许模型学习到不同方向和尺度上的特征,增强了模型的表征能力。
SEWeightModule(Squeeze and Excitation Weighting Module):
  • SE模块是一种通道注意力机制,通过全局平均池化和全连接层学习每个通道的重要性权重。这种机制有助于模型集中注意力于重要的特征通道,忽略无关的特征,从而提高性能。
PSAModule(Prioritized Split Attention Module):
  • PSAModule结合了SPCModule的多尺度特征提取和SEWeightModule的通道注意力机制。这种结合使得模型不仅能够学习到丰富的特征表示,还能够自适应地调整特征的重要性。
PSA_MetNet:
  • PSA_MetNet是MetNet的改进版本,通过集成PSAModule来增强特征提取和加权的能力。这种改进可以提高模型对降水预测中关键特征的识别能力。

PSA_MetNet与MetNet相比,具有以下优势:

  1. 多尺度特征提取:通过SPCModule,模型能够捕捉到不同尺度的特征,这对于理解降水模式中的局部和全局变化非常重要。

  2. 注意力机制:SEWeightModule的引入使得模型能够自适应地强调重要的特征,这有助于提高模型在复杂场景下的泛化能力。

  3. 特征融合:PSAModule通过融合不同尺度的特征和注意力权重,提供了一种更全面的表征,这可能对于提高模型的预测精度有显著效果。

  4. 计算效率:虽然增加了注意力机制可能会增加一些计算负担,但通过合理的设计和优化,可以在不显著增加计算成本的情况下提高模型性能。

  5. 泛化能力:通过综合使用编码器、解码器和PSAModule,模型能够更好地泛化到新的数据上,这对于实际应用中的降水预测尤为重要。

  6. 灵活性和可扩展性:PSA_MetNet的设计允许进一步的定制和扩展,例如通过调整卷积层的参数或添加更多的注意力模块来适应不同的任务需求。

总的来说,这些改进旨在提高模型对降水预测任务的适应性、精度和泛化能力,同时保持计算效率。通过综合考虑特征提取、特征加权和模型结构的设计,PSA_MetNet能够更好地处理复杂的降水预测问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值