一、赛题描述
基于气象大数据的自动站实况联合预测
风光清洁能源的管理与气象关系密不可分,因为风能和太阳能的发电效率直接依赖于气象条件。风力发电需要精确的风速和风向预测,而太阳能发电则依赖于日照时间和云层覆盖情况的准确预报。优质的气象预测能够帮助能源管理者优化发电计划,提升能源利用效率,降低运行成本,并保障电网稳定性。因此,基于高精度的气象预测进行科学管理是对实现风光清洁能源稳定供应和高效利用具有重要意义。
近年来,随着气象大数据的不断增长,人工智能和深度学习技术在气象预报领域的应用日益增多,一般通过训练模型识别气候模式和趋势,提高对复杂气候系统的理解和预测能力,已发展出高效的数据分析算法和领域大模型。大力发展新能源产业是国家实现能源安全和碳中和等战略目标的重要环节,而对于气象数据的预测具有重要的应用价值,在包括风电、光电在内的多种新能源产业中有着重要地位。本赛题旨在推动气象大数据的应用和气象预报技术的发展,要求参赛者利用提供的全球气象站点观测来构建预测模型,以提高对未来天气状况的预测精度。
温度和风速是关键的气象要素,在气象预报中对温度和风速的准确预测对建模天气状况以及气候变化有着深远的指导意义。在本次比赛中,参赛者需要根据所提供的全球气象自动站点的温度与风速的两年历史观测,结合毗邻站点的重要气象要素训练预测模型,实现未来24小时-72小时、1小时间隔的温度和风速预报。
二、竞赛数据和要求
1.训练数据
- 全球站点气象要素:包含全球范围内个3850自动站,每个自动站提供两年的1小时间隔数据,包含温度与风速绝对值两类气象要素。
- 协变量:毗邻站点的气象要素包含周围3*3数值预报网格中经纬两个方向矢量风速、温度、平均气压的信息,时间点间隔为3小时。
2.测试数据
- 中国站点气象要素:包含中国境内120个自动站,每个自动站提供71个测试窗口的1小时间隔数据,包含温度与风速绝对值两类气象要素。
- 协变量:毗邻站点的气象要素包含周围3*3数值预报网格中经纬两个方向矢量风速、温度、平均气压的信息,时间点间隔为3小时。
3.赛题说明
- 初赛和复赛的训练集:因变量(全球站点温度和风速)使用17544个时间点,使用所有3850个观测站点,协变量(全球ERA5数据)使用全球数据的5848个时间点,使用3850个观测站点。
- 初赛的测试要求:初赛测试集因变量(中国站点温度和风速)使用71个测试窗口,时间点间隔为1小时,使用前60个观测站点,协变量(中国ERA5数据)使用71个测试窗口,时间点间隔为3小时,使用前60个观测站点。赛题要求模型输入长度为7天(即168个时间点),预测未来1天(24个时间点)的温度和风速。
- 复赛的测试要求:复赛初赛测试集因变量(中国站点温度和风速)使用71个测试窗口,时间点间隔为1小时,使用所有120个观测站点;协变量(中国ERA5数据)使用71个测试窗口,时间点间隔为3小时,使用所有120个观测站点。赛题要求模型输入长度为7天(即168个时间点),预测未来3天(72个时间点)的温度和风速。
三、数据结构
在下表中,初赛x=60,复赛x=120,时刻t不公开。
因变量包括两个不同含义的变量:
- 两米高度的温度值(℃)
- 两米高度的风速的绝对值(m/s)
协变量中包含以下四个不同含义的变量,在数据中按照以下顺序排列:
- 十米高度的矢量纬向风速10U,正方向为东方(m/s)
- 十米高度的矢量经向风速10V,正方向为北方(m/s)
- 两米高度的温度值T2M(℃)
- 均一海平面气压MSL(Pa)
1. 训练数据格式
global/global_data.npy (5848, 4, 9, 3850) :协变量,用每个站点的地理位置寻找ERA5数据集中对应周围3*3格点的4个变量的值。第一维代表从时刻t开始每隔3小时共5848个时间点,最后一维代表3850个观测站点,第二维代表 ERA5的4个变量,第三维代表站点周围9个格点。9个格点的顺序为:左上、上、右上、左、中、右、左下、下、右下。
global/temp.npy (17544, 3850, 1):因变量,每个站点的温度观测值,其中第一维代表日从时刻t开始每隔1小时共17544个时间点,第二维代表3850个观测站点,第三维代表温度(℃)。
global/wind.npy (17544, 3850, 1):因变量,每个站点的风速绝对值观测值,其中第一维代表从时刻t开始每隔1小时共17544个时间点,第二维代表3850个观测站点,第三维代表风速(m/s)。
2. 测试数据格式
cenn/cenn_data.npy (71, 56, 4, 9, x):协变量,用每个站点的地理位置寻找ERA5数据集中对应周围3*3格点的4个变量的值。第一维代表71个样本窗口,第二维代表每个样本窗口中全部56个时间点,时间点间隔为3小时,最后一维代表x个观测站点,第二维代表 ERA5的4个变量,第三维代表站点周围9个格点。9个格点的顺序为:左上、上、右上、左、中、右、左下、下、右下。
cenn/temp_lookback.npy (71, 168, x, 1):因变量,每个站点的温度观测值,第一维代表71个样本窗口,第二维代表每个样本中长度为168个点的回溯窗口,时间点间隔为1小时,第三维代表x个观测站点,第四维代表温度(℃)。
cenn/wind_lookback.npy (71, 168, x, 1):因变量,每个站点的风速绝对值观测值,第一维代表71个样本窗口,第二维代表每个样本中长度为168个点的回溯窗口,时间点间隔为1小时,第三维代表x个观测站点,第四维代表风速(m/s)
四、模型建立
本赛题Baseline 来源于《ITRANSFORMER: INVERTED TRANSFORMERS ARE EFFECTIVE FOR TIME SERIES FORECASTING》,该文发表于2024ICLR会议上。文章提出了一种倒置Transformer,旨在解决长时间多变量时序预测问题。
Transformer在自然语言处理和计算机视觉领域取得了巨大成功,并成为遵循缩放定律的基础模型。受许多领域成功应用的启发,具有强大的依赖关系提取能力和提取序列中多层次表示的能力的Transformer在时间序列预测中应用。然而,研究人员最近开始质疑基于Transformer预测模型的有效性,这些预测模型通常将同一时间步的多个变量嵌入到不可区分的通道中,并将注意力集中在这些时间标记上以捕获时间依赖性。考虑到时间点之间的数值关系,但语义关系较少,研究人员发现,简单的线性层,在性能和效率上都超过了复杂的Transformer。
考虑到基于Transformer模型的争议,本文反思了为什么Transformer在时间序列预测中比线性模型表现更差,而在许多其他领域发挥主导作用。本文注意到现有的基于变压器的预测模型结构可能不适合多变量时间序列预测。如图1顶部所示,值得注意的是,由不一致的测量记录的基本上表示完全不同物理含义的同一时间步的点被嵌入到一个具有消除的多元相关性的标记中。而单个时间步形成的标记由于同时存在的时间点所表示的过度局部的接受域和时间不对齐的事件而难以显示有益信息
考虑到将同一时间步的多变量点作为(时间)标记嵌入的潜在风险,本文对时间序列采取了相反的看法,并将每个变量的整个时间序列独立嵌入到(变量)标记中,通过反转,嵌入令牌聚合了序列的全局表示,这些表示可以更加以变量为中心。同时,前馈网络可以熟练地学习任意回溯序列编码的不同变量的泛化表示,并解码以预测未来序列。基于上述动机,本文提出了iTransformer,贡献体现在三个方面:
1.对Transformer的体系结构进行了反思,并指出标准Transformer组件在多变量时间序列上的提取能力尚未得到充分的开发。
2.本文提出了iTransformer,它将独立的时间序列作为标记,通过自关注来捕获多元相关性,并利用层归一化和前馈网络模块来学习更好的序列-全局表示,用于时间序列预测。
3.在实验上,iTransformer在真实数据集上具有较好的性能,并广泛地分析了倒置模块和架构选择,为未来基于Transformer的预测模型的改进指明了一个有希望的方向。
一句话总结:Transformer:一个变量与其他变量在不同时间的相关性,侧重时序关系;iTransformer:同一时间段一个变量与其他变量的相关性,侧重变量关系;
上代码:
4.1 iTransformer:
4.1.1 顶层
import torch
import torch.nn as nn
from layers.Transformer_EncDec import Encoder, EncoderLayer
from layers.SelfAttention_Family import FullAttention, AttentionLayer
from layers.Embed import DataEmbedding_invertedclass Model(nn.Module):"""Paper link: https://arxiv.org/abs/2310.06625"""def __init__(self, configs):super(Model, self).__init__()self.seq_len = configs.seq_lenself.pred_len = configs.pred_lenself.output_attention = configs.output_attention# Embeddingself.enc_embedding = DataEmbedding_inverted(configs.seq_len, configs.d_model, configs.dropout)# Encoderself.encoder = Encoder([EncoderLayer(AttentionLayer(FullAttention(False, attention_dropout=configs.dropout,output_attention=configs.output_attention), configs.d_model, configs.n_heads),configs.d_model,configs.d_ff,dropout=configs.dropout,activation=configs.activation) for l in range(configs.e_layers)],norm_layer=torch.nn.LayerNorm(configs.d_model))# Decoderself.projection = nn.Linear(configs.d_model, configs.pred_len, bias=True)def forecast(self, x_enc):# Normalization from Non-stationary Transformermeans = x_enc.mean(1, keepdim=True).detach()x_enc = x_enc - meansstdev = torch.sqrt(torch.var(x_enc, dim=1, keepdim=True, unbiased=False) + 1e-5)x_enc /= stdev_, _, N = x_enc.shape# Embeddingenc_out = self.enc_embedding(x_enc, None)enc_out, attns = self.encoder(enc_out, attn_mask=None)dec_out = self.projection(enc_out).permute(0, 2, 1)[:, :, :N]# De-Normalization from Non-stationary Transformerdec_out = dec_out * (stdev[:, 0, :].unsqueeze(1).repeat(1, self.pred_len, 1))dec_out = dec_out + (means[:, 0, :].unsqueeze(1).repeat(1, self.pred_len, 1))return dec_outdef forward(self, x_enc):dec_out = self.forecast(x_enc)return dec_out[:, -self.pred_len:, :] # [B, L, C]
4.1.2 DataEmbedding_inverted
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils import weight_norm
import mathclass DataEmbedding_inverted(nn.Module):def __init__(self, c_in, d_model, dropout=0.1):super(DataEmbedding_inverted, self).__init__()self.value_embedding = nn.Linear(c_in, d_model)self.dropout = nn.Dropout(p=dropout)def forward(self, x, x_mark):x = x.permute(0, 2, 1) # 此处即为转置所在 # x: [Batch Variate Time]if x_mark is None:x = self.value_embedding(x)else:x = self.value_embedding(torch.cat([x, x_mark.permute(0, 2, 1)], 1))# x: [Batch Variate d_model]return self.dropout(x)
# [batch_size,time,Variate]→[Batch Variate Time]→[batch_size,Variate,d_model]
其余注意力代码司空见惯不再赘述详细代码查看:https://github.com/thuml/iTransformer
里面全是好东西 哈哈哈
4.1.3 Baseline 数据流动
输入数据格式:输入数据[batch_size,time,Variate]
输出数据格式:输出数据[batch_size,pred_len,Variate]
模型内部输入查看:
1.模型输入 [batch_size,time,Variate]
2.输入数据归一化 mean→[batch_size,1,Variate];std→[batch_size,1,Variate] normed→[batch_size,time,Variate]
3.DataEmbedding_inverted :[batch_size,time,Variate]→[Batch Variate Time]→[batch_size,Variate,d_model]
4.encoder :
结构图: encode→EncoderLayer→AttentionLayer→FullAttention
由内到外:
encoder输入x→[batch_size,Variate,d_model] attn_mask = None
进入EncoderLayer的x→[batch_size,Variate,d_model] attn_mask = None
进入attention→AttentionLayer→FullAttention
映射前 x→[batch_size,Variate,d_model] 映射后 qkv [batch_size,Variate,d_model] view后[batch_size,Variate,n_head,d_model//n_head]
score→[batch_size,n_head,Variate,Variate]: torch.einsum("blhe,bshe->bhls", queries, keys)
scale→对最后一个维度[batch_size,n_head,Variate,Variate] →A
after_attention_output→[batch_size,Variate,n_head,d_model//n_head] torch.einsum("bhls,bshd->blhd", A, values)
out→[batch_size,Variate,d_model]
进入到EncoderLayer→residual→norm→2*conv1d(transpose(-1, 1) 通道数放在第一个位置 论文中时间上分别两次映射)→transpose(-1, 1)恢复数据形状
encoder 输出 →[batch_size,Variate,d_model]
4.2 Tricks 合集 (来源于各位大佬开源)
4.2.1 短时预测纠正长时间预测:多时间步增强 (可以更加细致)
4.2.2 损失函数设计
4.2.3 TTA
测试时增强(Test-Time Augmentation,TTA)是一种在深度学习模型的测试阶段应用数据增强的技术手段。它是通过对测试样本进行多次随机变换或扰动,产生多个增强的样本,并使用这些样本进行预测的多数投票或平均来得出最终预测结果。
本赛题:多个插值推理结果进行加权
4.2.4 特征工程
4.2.5 跳步采样
原始baseline 采样方式:滑窗采样 / 1h
跳步采样方式:滑窗采样/6h
4.2.6 多元注意力编码设计