baseline模型
整体框架:
-
数据集的定义, 包括两部分Feature类和GT类,按lead_time建立起训练数据和标签之间的关系,即构建数据集mydataset;调用数据加载器(DataLoader)。
-
模型构建,构建简单的一层卷积层的网络,定义输入通道数72x24,输出通道数72。
具体而言,沿着S*C维度做卷积。输入通道数:定义的模型数据输入;输出通道数:输出通道数反映了卷积核的数量,表示卷积操作后提取到的特征图的数量。输出通道数与输入通道数无直接关系。
-
模型训练,定义损失函数, 优化器, 训练周期等,并保存好模型。
-
模型测试,调用保存的模型权重参数,进行test集的测试。
代码分析
Feature类
get_features_paths方法
def get_fts(self, init_time):
return xr.open_mfdataset(self.features_paths_dict.get(init_time) + '/*').sel(lead_time=self.fcst_steps).isel(
time=0)#类型 xarray.Dataset 可以转换为 xarray.DataArray处理
#1.features_paths_dict.get(init_time)根据文件名获取时间,再获取对应时间的文件路径。
#2.使用 xarray 的 open_mfdataset 方法打开多个文件并将它们组合成一个数据集。
#3.调用 sel 方法,选择数据集中 lead_time 维度为 self.fcst_steps 的数据。
#4.使用 isel 方法,基于索引选择的方法,选择数据集中的 time 变量。time=0 表示选择时间维度的第一个索引。
Feature
类中的一个方法 get_features_paths
,它的作用是返还一个字典,该字典包含初始时间与其对应的文件路径的映射关系。
转换后的日期时间(文件名)作为字典 init_time_path_dict
的键,并将对应的文件路径作为值存储在字典中。
最终返回的字典大致长这样:
{ Timestamp('2021-01-01 00:00:00'): '/data/features/2022/20220101-00', Timestamp('2021-01-01 12:00:00'): '/data/features/2022/20220101-12', ... }
这个字典可以用于后续根据具体的初始时间获取对应的特征数据文件路径。
1.使用 os.listdir
在指定年份目录中,返回一个列表,包含所有文件夹名
2.pd.to_datetime(init_time)
作用:将文件夹名转换为日期时间格式
get_fts方法
def get_fts(self, init_time):
return xr.open_mfdataset(self.features_paths_dict.get(init_time) + '/*').sel(lead_time=self.fcst_steps).isel(
time=0)#类型 xarray.Dataset 可以转换为 xarray.DataArray处理
#1.features_paths_dict.get(init_time)根据文件名获取时间,再获取对应时间的文件路径。
#2.使用 xarray 的 open_mfdataset 方法打开多个文件并将它们组合成一个数据集。
#3.调用 sel 方法,选择数据集中 lead_time 维度为 self.fcst_steps 的数据。
#4.使用 isel 方法,基于索引选择的方法,选择数据集中的 time 变量。time=0 表示选择时间维度的第一个索引。
我们这里查看一下20210101-00文件夹,经过处理后可以看到维度为(72,24,57,81),这里72应该就是表示time=0后的72小时。
如果选择lead_time=71,则数据维度会变为(71,24,57,81)
代码:
feature = Feature()
init_time = pd.Timestamp('20210101-00')
data = feature.get_fts(init_time)
print(data)
输出:
输出解释
Data variables: __xarray_dataarray_variable__ (lead_time, channel, lat, lon) float32 32MB dask.array<chunksize=(6, 24, 57, 81), meta=np.ndarray>
使用 dask
进行并行处理: 数据被分成块大小为chunksize= (6, 24, 57, 81)
进行处理。(共六块,在内存有限的情况便于并行处理)
数据维度
-
(lead_time, channel, lat, lon)
。-
lead_time
: 预测时间步长,共有 72 个步长。 -
channel
: 数据的通道或变量类型,共有 24 个通道(如气象变量)。 -
lat
: 纬度,共有 57 个纬度点。 -
lon
: 经度,共有 81 个经度点。
-
GT类
查看一下GT,设置init_time = pd.Timestamp('20210101-00'),可以看到选取到该时刻后的72h情况,维度(lat: 57, lon: 81, time: 72)
代码:
gt=GT()
init_time = pd.Timestamp('20210101-00')
timestamps = gt.parser_gt_timestamps(init_time)
print(timestamps)
data = gt.get_gts(init_time)
print(data)
输出,符合预期
我们再随机选取某个经纬点,看一下72h的降水情况,全是负值,处理起来要小心了
构建数据集
mydataset
代码解释:
ft_item = self.ft.get_fts(init_time).to_array().isel(variable=0).values
#to_array(): 将 xarray.Dataset 转换为 xarray.DataArray。
#xarray.Dataset 可以包含多个变量,而 xarray.DataArray 是一个多维数组,只包含一个变量。
#使用 xarray.DataArray 的 isel 方法,基于索引进行选择。variable=0: 选择第一个变量。
#.values: 将 xarray.DataArray 转换为 Numpy 数组。
可以借鉴,我们查看类型 xarray.Dataset 的具体数值时,可以转换为 xarray.DataArray处理。
构建模型
沿着S*C维度做卷积。
输入通道数:定义的模型数据输入
输出通道数:输出通道数反映了卷积核的数量,表示卷积操作后提取到的特征图的数量。输出通道数与输入通道数无直接关系。
代码解释:
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) #[1, 72, 24, 57, 81];sequence_length=lead_time=72
#[batch_size=1, sequence_length=72, channels=24, width, height]
x = x.reshape(B, -1, W, H)
out = self.conv1(x)
#自然而然沿着S*C维度进行卷积,最终输出通道为72(72个卷积核)
out = out.reshape(B, S, W, H) #[1, 72, 57, 81]
return out
伏羲大模型
比赛输入数据来自伏羲气象大模型的输出,伏羲大模型是复旦大学发布的数据驱动的气象大模型,数据分辨率0.25度,时间间隔1小时,包含地面和高空气压层多个气象要素
原理:
FuXi模型作为一个自回归模型,它采用前两个时间步的天气参数(𝑋𝑡−1,𝑋𝑡)作为输入,进而预测下一个时间步(𝑋𝑡+1)的天气参数。
模型优缺点:
-
FuXi模型进行60次迭代运行,能够生成15天的预报。
-
然而,基于纯数据驱动的机器学习(ML)模型缺乏物理限制,这可能会导致长期预报的误差显著增加。可以通过采用自回归多步损失函数,可以有效减少长期预报过程中的累积误差。
-
预训练的FuXi模型的级联模型架构,该架构针对特定的5天预报时间窗口进行精细调整,以实现最优性能。能提升短期和长期预报的性能。 窗口被划分为FuXi-Short(0-5天)、FuXi-Medium(5-10天)和FuXi-Long(10-15天)。
时间序列分析入门
时间序列分析在金融、经济、气象、市场营销、生产制造等领域有广泛应用,如股票价格预测、经济指标分析、气象变化研究、销售预测等。在这里我们需要研究的是气象变化。
特点:
-
时间序列分析是统计学和数据科学中的一个重要领域,涉及分析随时间变化的数据。时间序列数据通常是在特定时间间隔(如每日、每月、每年等)收集的有序数据点。
-
一般基于时间序列的前一部分的数据来预测后一部分的数据。
时间序列分析问题
一般包括以下几个方面:
-
描述性分析:
-
观察和描述时间序列数据的基本特征,如趋势、季节性、周期性、波动性等。
-
绘制时间序列图,计算基本统计量(均值、方差等),识别数据模式。
-
-
平稳性检验:
-
检验时间序列数据是否平稳(统计特性不随时间变化)。平稳性是许多时间序列分析方法的基本假设。
-
使用自相关函数(ACF)和偏自相关函数(PACF)等工具。
-
-
趋势和季节性分解:
-
将时间序列分解为趋势、季节性和随机成分,以便更好地理解数据的组成部分。
-
常用方法包括移动平均、指数平滑、分解法等。
-
-
模型构建和预测:
-
构建数学模型来描述时间序列数据的生成过程,并进行预测。
-
常见模型包括自回归(AR)、移动平均(MA)、自回归移动平均(ARMA)、自回归积分移动平均(ARIMA)、季节性ARIMA(SARIMA)等。
-
-
异常检测:
-
识别和处理时间序列中的异常点(即显著偏离正常模式的数据点)。
-
常用方法包括统计方法、机器学习方法等。
-
-
协整和因果关系分析:
-
研究多个时间序列之间的长期平衡关系(协整)和因果关系。
-
使用协整检验、格兰杰因果关系检验等方法。
-
模型分类
-
常用自回归(AR)模型、移动平均(MA)模型, 或者自回归滑动平均模型(ARMA)模型,到更先进的自回归积分滑动平均(ARIMA)模型
-
循环神经网络(RNN): 捕捉输入特征前后时间的逻辑+具备神经网络强大的拟合能力
-
transformer模型: 注意力机制,可以建立在全局建模时间序列中某个时间节点和其他时间节点的关系+强大的拟合能力
开始实践
选2021年,查看一下mydata多大sample num: 730
,730=365*2,合理,
诶~不对,看似合理,根据最后三天的气象要素,预测的都到2022年去了。
于是验证GT。
当我们设置init_time = pd.Timestamp('20211229-00'),我们尝试去找对应的GT中的值结果可想而知,KeyError: "not all values found in index 'time'"。
合理,预测72h的最后1h都到20220101-00。
于是末尾的六个文件,无用武之地~sample num: 724
1.baseline,epoch=10,得分0.14。
在验证集2020上情况:
-
sample num: 726 Tloss:1341.4099817872047 Avgloss:1.847672151222045
训练情况,loss不收敛,很不稳定。后来计算发现是这个loss的不合理。
2.全连接层,得分0.12。在验证集2020上情况:
-
sample num: 726 Tloss:432.15723699890077 Avgloss:0.5952579022023426
训练情况:最终平均loss为0.5663
3.模型baseline_up,得分0.06。
在验证集2020上情况:
-
Avgloss:0.96
4.fuxi模型,0.17,在验证集2020上的情况
-
sample num:726 Tloss:512.7716672909446 Avgloss:0.7063
5.baseline_fuxi,得分0.13,在验证集2020上的情况
-
sample num: 726 Tloss: 448.4797329409048 Avgloss:0.6177
训练情况:
总结思考
这个题目有点...,最终的评价指标csi和loss不是一套体系,即使通过采取阈值来设定评价指标csi有一定合理性。而且还是需要拿预测的值去预测值。
未来改进方向
-
网络结构优化,激活函数的选取。网络并不是越复杂越好。
-
查看feature数据,考虑进行特征工程。 有无负数,有无弱关联要素
-
结合赛题的评价指标入手
-
结合官网的数据标准化方法
评价指标
基于ERA5格点降水值选取极端降水案例
评测指标:
临界成功指数(CSI)
CSI = hits/(hits + false alarms + misses)
以24小时累积降水量50毫米为阀值,y_pre_1为预测的极端降水格点(24小时累积降水 >= 50 mm),y_obs_1为观测的极端降水格点,hits为预测与观测的重叠格点,其中false alarms = y_pre_1 - hits, misses = y_obs_1 - hits。
注意:
其中24小时累积降水量计算方式为:1-24,25-48,49-72。
脑洞大开
-
还记得上节task中给大家布置了一些思考题,经过本次的学习,相信你一定可以发现之前的baseline中是存在一些问题的, 请指出,并给出你的修改意见。
-
baseline模型不合理之处:loss的计算和输出不合理,应当改为每轮epoch的总损失或者平均损失。
-
另外一点,加上验证集(计算模型在未学习或训练过数据上的loss),这样更合理!
-
-
观察数据的组成结合时间序列分析, 你认为本次赛题数据中有哪些值得改进的地方, 或者如果赛题方将每个时间节点的数据作为赛题数据, 你会如何制作数据集?
-
后面部分数据可以不用给出,通过算法迭代预测;重点按lead_time建立起训练数据和标签之间的关系。
-
-
本次赛题你认为是否是时间序列预测问题, 并给出相应的理由
-
不太像时间序列预测问题,虽然题目要求预测72h的降水,涉及到时间,但并不涉及随时间变化的数据。看起来更像回归问题!而时间序列预测问题一般基于时间序列的前一部分的数据来预测后一部分的数据。
-