最近在筹备写知识星球的文章,主要想把自己看完论文之后偶然产生的想法idea,以及实验验证过程记录下来。其实平时有挺多想法,但大多没有形成文字,或是跑跑代码就丢掉了,回过头想查资料就很麻烦,特别是知道自己曾经有过灵感,但就想不起来就很急。目前已经完成了一部分,本篇先分享出来,请大家给点意见。
为什么首先要对数据集有概念?
认识标准数据集在学习深度学习模型之前至关重要。标准数据集就像是一个基准,提供了被广泛认可和整理好的数据。首先,它能够帮助初学者熟悉数据的结构和格式。例如在图像识别领域的MNIST数据集,它包含了手写数字的图像及对应的标签,让学习者明白图像数据是如何组织以及标注的。其次,通过标准数据集可以快速验证模型的基本性能。因为很多成熟的模型在这些标准数据集上已经有了参考结果,学习者可以用自己搭建的模型与之对比,直观地了解模型是否有效、存在哪些差距。再者,标准数据集有利于理解不同深度学习任务的特点,像分类任务、回归任务对应的数据集就有明显差异,它是深入学习深度学习模型的一个重要基础。
目前时间序列领域常用的数据集有6个,分别是Electricity、ETT、Exchange、ILI、Traffic、Weather,涵盖了用电量、温度、外汇、流感、交通和天气领域。如下图所示,这些数据集是以.csv 格式的文件进行存储。同时我们也看到了ETT数据集有四张表,分别代表不同的采样周期。下面,我们逐一看各张数据表的具体形式。所有的数据集都可以从autoformer下载,不方便也可以从我公众号后台下载。
用电量Electricity数据集
电力数据集包含了320位客户从2016年7月至2019年7月每小时的电力消耗情况,数据集第一列给出了时间戳,其实时间本身也是非常重要的特征,例如:节假日大家因为居家时间更久,用电量可能会更多,今年NIPS24就有一篇专门研究时间戳的文章,可以查看我对论文的解读文章。中间0-319列是feature,最后一列OT是预测目标。OT和前面的特征有什么关系呢?后文我们细讲。
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
Electricity = pd.read_csv('electricity.csv')
ETTh1 = pd.read_csv('ETTh1.csv')
ETTh2 = pd.read_csv('ETTh2.csv')
ETTm1 = pd.read_csv('ETTm1.csv')
ETTm2 = pd.read_csv('ETTm2.csv')
Exchange = pd.read_csv('exchange_rate.csv')
traffic = pd.read_csv('traffic.csv')
weather = pd.read_csv('weather.csv')
Electricity.head()
可以通过一个简单代码可视化看一下目标列OT的变化情况。直观的看,有两点现象值得注意,第一是异常值,第二是周期性。异常值是上下插针,可能是设备故障导致的,这种很难预测;周期性可以从大周期和小周期角度看。
px.line(Electricity.sort_values(["date"]), x='date', y='OT',title = "Electricity" )
电力变压器ETT数据集
ETT是英文“Electricity Transformer Temperature”缩写,即 “电力变压器温度”,数据集有小时级别ETTh1、ETTh2和分钟级别ETTm1、ETTm2,所以总共四个数据表。ETT时间范围为2016年7月至2018年7月,涵盖电力变压器负载和油温等信息,可用于分析电力变压器运行状态,为研究电力变压器相关问题以及模型训练评估等提供了重要的数据基础。
如果我们想查看数据各列特征的相关性,我们可以使用以下代码语句,先计算各列相关性,然后画出热力图,下图是我们绘制的热力图:
selected_ETTh1 = ETTh1.iloc[:, 1:8]
correlation_matrix = selected_ETTh1.corr()
print(correlation_matrix)
plt.rcParams['axes.unicode_minus'] = False
# 绘制热力图
sns.heatmap(correlation_matrix, annot=True, cmap="YlGnBu")
# 设置标题
plt.title("Heatmap of the correlation matrix.")
# 显示图形
plt.show()
我们还可以使用箱体图来查看OT以及各个变量在每一年中不同月份的变化情况,这也有助于我们了解各个变量随着时间的变化情况,比如是周期变化还是呈现出增长趋势?降低趋势?平稳性如何?当然,平稳性靠画图是很难看出来的,还是要用统计学方法来建议,这里只是提供直观的数据展示。
a = ETTh1.copy()
a['date'] = pd.to_datetime(a.date)
a["year"] = a.date.dt.year
a["month"] = a.date.dt.month
px.box(a, x="year", y="OT" , color = "month", title = "ETT OT changes")
px.box(a, x="year", y="HUFL" , color = "month", title = "HUFL OT changes")
下图是OT列的箱体绘制结果,由于数据是2016年7月份开始,到2018年6月底结束,所以2016年和2018年实际只有半年的数据,但是我们还是能够看出OT列每一年都是1-6月逐渐升高,然后7-12月逐渐降低,这是在大周期上能够观察到的变化。
我们还可以看其它变量的数据分布情况,比如HUFL列;时间序列领域其实大家普遍都直接魔改模型看结果,挺少有人认真的做分析,根据分析结果设计模型。我个人认为这样并不合理,还是要有一个分析过程,让我们对数据有直观的认识,然后有依据的设计模型结构。
外汇交易数据exchange_rate数据
我们来看看第四个金融外汇相关的数据集,这个其实是比较难预测的,我们通过可视化就能直观的看出来,首先还是先看数据的基本情况,我们观察到算上时间date列,总共7列。
接下来,我们先看一下OT列随时间的变化情况,重点观察是否有明显的周期性,趋势性等。
a = Exchange.copy()
a['date'] = pd.to_datetime(a.date)
a.set_index('date', inplace=True)
plt.figure(figsize=(8, 4))
a['OT'].plot()
# 设置图形标题等自定义内容
ax = plt.gca()
ax.set_title('OT value details')
ax.set_xlabel('date')
ax.set_ylabel('OT values')
使用上面的代码绘制OT从1990年到2010年的变化曲线,直观来看没有什么明显的规律😔。
当然,我们还可以分析每列feature与OT之间的关系,这里我们以feature 1和feature 2为例,通过散点图展示特征与OT关联,其实也可以直接计算相关性系数。从图中我们可以直观的看出,feature 0这一列和OT列有明显的相关性,而且计算Corr系数也得到0.9,说明确实是相关的。feature 1这一列与OT则相关性不明显,无论是看图还是计算Corr都可以发现。
fig, axes = plt.subplots(1, 2, figsize = (15,5))
Exchange.plot.scatter(x = "OT", y = "0", ax=axes[0])
Exchange.plot.scatter(x = "OT", y = "1", ax=axes[1], color = "r")
# 计算特征与OT列之间的相关性系数
corr0_OT = Exchange['OT'].corr(Exchange['0'])
corr1_OT = Exchange['OT'].corr(Exchange['1'])
axes[0].set_title('Corr between OT & feature0 is '+str(round(corr0_OT,2)), fontsize = 15)
axes[1].set_title('Corr between OT & feature1 is '+str(round(corr1_OT,2)), fontsize = 15)
ILI疾病数据集
ILI 包含2002 年至 2021 年美国疾病控制和预防中心每周数据,数据结构如下图所示。看到这样的数据,我还是会首先画出OT列随时间变化的曲线图,观察是否有明显的周期性、趋势性,具体代码如下:
a = ILI.copy()
a['date'] = pd.to_datetime(a.date)
a.set_index('date', inplace=True)
plt.figure(figsize=(8, 4))
a['OT'].plot()
# 设置图形标题等自定义内容
ax = plt.gca()
ax.set_title('OT value details')
ax.set_xlabel('date')
ax.set_ylabel('OT values')
OT列随时间的变化情况如下图所示,非常有意思。我们既看到了数据的周期波动,又看到了逐渐的增长趋势。这是否说明流感数据既有周期性,同时又有趋势性呢?那么,如果数据确实兼具周期和趋势性,我们又该如何有针对性的进行建模?一个自然而然的想法就是做分解,分解出周期项和趋势项。那么问题又来了,该使用什么方法进行分解,移动平均?傅立叶变换?这些方法都可以!我们将在后续的文章中尝试分析。
交通 Traffic 数据集
Traffic数据集主要是描述了2015 年至 2016 年旧金山高速公路传感器记录的每小时道路占用率。
这里我们还是先看OT随时间的变化曲线,此外我们观察到数据特征有860列之多,不妨看看特征之间的相关性如何,考虑做一个热力图直观表示出来。但是如果你直接用ILI画折线的图的代码进行绘制,你会发现由于数据过于密集,实际都挤在一起,因此我们考虑拆分一下,先看2017年1月到12月的数据情况。代码和绘图结果如下所示,可以看出:1、周期性非常明显,这也容易理解,人们每天的出行其实规律性很强;2、有些类似“异常值”的点,但是否是异常值并不能直接下结论,因为据我了解,在特定节假日,确实会出现集中放假,集中外出的情况,所以最近的一些研究就从时间戳的角度做工作,强化这方面的特征。
fig, axes = plt.subplots(2, 1, figsize = (20,5))
a1['OT'].plot(ax=axes[0])
a2['OT'].plot(ax=axes[1])
# 设置图形标题等自定义内容
axes[0] = plt.gca()
axes[0].set_title('OT value between 2017-01-01 and 2017-07-01')
axes[0].set_xlabel('date')
axes[0].set_ylabel('OT values')
axes[1] = plt.gca()
axes[1].set_title('OT value between 2017-07-01 and 2017-12-31')
axes[1].set_xlabel('date')
axes[1].set_ylabel('OT values')
# 调整两个子图的上下距离
fig.subplots_adjust(hspace=0.5)
下面的代码用箱体图展示了日内变化情况,可以很清晰的看到数据比较能够反映人们作息及出行规律,这和上面出现的周期性变化是吻合的,这类数据建模时肯定要重点考虑周期性,此外还有之前提到的特殊节假日,即时间戳特征。
a = traffic.copy()
a['date'] = pd.to_datetime(a.date)
a["year"] = a.date.dt.year
a["month"] = a.date.dt.month
a['day'] = a.date.dt.day
a["hour"] = a.date.dt.hour
px.box(a, x="hour", y="OT" , color = "hour", title = "daily OT changes") # 日内变化
# px.box(a, x="month", y="OT" , color = "month", title = "ETT OT changes") # 按月看年内变化
天气数据集weather
天气数据集的表结构如下图所示,数据包括21个天气指标,范围从2020年1月1日到2021年1月1日,时间记录间隔为10分钟。老规矩,先看大周期上OT的变化情况,能看到出现了异常值,为了方便我们先简单的把OT低于-8000的数值用平均值代替一下,然后画出折线图。
a = weather.copy()
a['OT'] = a['OT'].apply(lambda x: a['OT'].mean() if x <-300 else x)
px.line(a.sort_values(["date"]), x='date', y='OT',title = "weather" )
这么看粒度太细了,我们还是先按照天聚合一下,求出每天的OT均值,然后看一年的变化情况,这样看好像还是没发现什么明显的规律性。
a['date'] = pd.to_datetime(a['date'])
a.set_index('date', inplace=True)
daily_mean = a.resample('D').mean()
daily_mean = daily_mean.reset_index()
px.line(daily_mean, x='date', y='OT',title = "weather" )
a = weather.copy()
a['OT'] = a['OT'].apply(lambda x: a['OT'].mean() if x <-300 else x)
a['date'] = pd.to_datetime(a.date)
a["day"] = a.date.dt.day
a["hour"] = a.date.dt.hour
# px.box(a, x="year", y="OT" , color = "month", title = "ETT OT changes")
px.box(a, x="hour", y="OT" , color = "hour", title = "weather OT changes")
换个思路,看看其他特征和OT列的相关性情况,只看OT列的话,情况也不是很乐观啊,好像相关性也并不强😢。
大家可以关注我【科学最top】,第一时间follow时序高水平论文解读!!!,后台回复“交流”加入讨论群,回复“资源”获取2024年度论文讲解合集