每日气候预测:使用 LSTM、递归神经网络进行时间序列预测

855 阅读6分钟

目录:

  1. 介绍
  2. 背景
  3. 数据预处理
  4. LSTM模型构建
  5. 模型训练与评估
  6. 结论
  7. 参考

介绍

时间序列预测是一种统计技术,用于预测按时间排序的一系列数据点的未来值。它涉及分析历史数据模式以识别数据中的趋势、模式和季节性,然后使用该信息来预测未来值。由于时间序列预测的广泛应用,包括金融、天气预报、销售预测等,因此在各个领域都必不可少。

由于时间序列数据的特征(包括趋势、季节性和噪声),时间序列预测提出了独特的挑战。了解和应对这些挑战对于确保准确可靠的预测至关重要,我们将在接下来的章节中介绍这些挑战。

在本文中,我们重点介绍 LSTM,它代表长短期记忆,是一种循环神经网络 (RNN),因其能够有效地对顺序数据中的长期依赖性进行建模而广受欢迎,使其非常适合用于时间序列预测任务。LSTM 是 RNN 的一种变体,专门用于解决梯度消失问题,这是训练深度神经网络的常见问题。

背景

LSTM 具有独特的架构,允许它们在扩展序列上捕获和存储信息,从而使它们能够处理具有长期依赖性的时间序列数据。LSTM 的关键特征是它的记忆单元,它可以长时间存储信息,并在处理新数据点时有选择地忘记或更新这些信息。这使得 LSTM 能够有效地捕捉时间序列数据中的模式,包括趋势、季节性和其他复杂的依赖关系。

LSTM 捕获序列中的长期依赖性的能力来自于记忆单元和门控机制的结合。记忆单元允许 LSTM 在长序列上存储信息,门机制(输入门、遗忘门和输出门)允许 LSTM 有选择地更新和遗忘信息,使它们能够捕获相关的长期依赖关系,同时忽略不相关的信息。

LSTM模型的架构: image.png

  1. 记忆单元(记忆门) :允许 LSTM 在长序列上捕获和存储信息。它有一个内部状态,根据门的输入和输出在每个时间步更新
  2. 输入门:确定当前时间步长的输入量应存储在记忆单元中。它将来自前一个时间步的输入特征和隐藏状态作为输入,并将它们传递给一个 sigmoid 激活函数,该函数为每个特征生成一个介于 0 和 1 之间的值。
  3. 遗忘门:确定应遗忘或擦除前一时间步长的存储单元中的信息量。它将来自前一个时间步的输入特征和隐藏状态作为输入,并将它们传递给 sigmoid 激活函数。遗忘门的输出与当前记忆单元状态逐元素相乘,允许 LSTM 有选择地从记忆单元中擦除信息。
  4. 输出门:确定在当前时间步应输出多少存储单元状态。它将来自前一个时间步的输入特征和隐藏状态作为输入,并将它们传递给 sigmoid 激活函数。当前记忆单元状态然后通过 tanh 激活函数,tanh 激活的输出与输出门的输出逐元素相乘,产生 LSTM 的最终输出。

EDA 和数据预处理

如前所述,我们将处理来自 Kaggle 的每日气候数据(来源:www.kaggle.com/datasets/su… ?datasetId=312121&sortBy=voteCount&searchQuery=LSTM ) .

印度德里的数据时间范围为 1 月 13 日至 4 月 17 日,具有温度、湿度、风速和压力等属性。

电子数据分析

我们从时间序列的基本 EDA 开始,观察整个时间段内所有变量的相当稳定的图表。平均温度肯定有季节性,我们将在未来讨论

plt.figure(figsize=( 20 , 10 )) 
colors = [ '#FF7F50' , '#DDA0DD' , '#66CDAA' , '#BC8F8F' ] 
for i, j in 枚举(df.set_index( 'date' ) .columns): 
  plt.subplot( len (df.set_index( 'date' ).columns) + 1 , 1 , i + 1 ) 
  plt.plot(df.set_index( 'date' )[j], color=colors[我]); 
  plt.ylabel(j, fontsize= 16 ) 
  plt.grid() 
plt.xlabel( '日期', 字体大小= 16 )

image.png

绘制数据中的所有变量

ADF 平稳性检验

我们通过利用 ADF 测试检查然后检查时间序列的平稳性,并观察到 ​​>0.05 的 p 值 0.15 表明时间序列中的非平稳性

test_results = adfuller(df[ "meantemp" ]) 

print ( f"ADF 测试统计: {test_results[ 0 ]} " ) 
print ( f"p-value: {test_results[ 1 ]} " ) 
print ( "临界阈值:" ) 
for key, value in test_results[ 4 ].items(): 
  print ( f"\t {key} : {value} " )

为了纠正时间序列中的非平稳性,我们对数据进行对数变换以使其平稳

fig, ax = plt.subplots(3, 1, figsize=(20, 15)) 

ax[0].plot( df [ "date" ], df [ "meantemp" ], label= "原始系列" ) 
ax[ 1].plot( df [ "date" ], np.log( df [ "meantemp" ]), label= "对数转换后" ) 

df [ "meantemp_transformed" ] = pd.Series(np.log( df [ " meantemp" ])).diff(periods=12)   # 12 个月
df.dropna(inplace=True) 
ax[2].plot( df [ "date" ],df ["meantemp_transformed" ], label= "差分后" );

执行对数转换后,我们再次执行 ADF 检验并获得 ~1.34(e-5) 的 ADF 检验的 p 值,这使我们能够拒绝零假设并确认平稳性

缩放

一旦我们有了固定时间序列,我们将使用 MinMaxScaler 缩放数据以将所有值置于 0,1 范围内。缩放具有重要作用,因为它直接影响模型性能,强烈推荐

scaler = StandardScaler() 
df_scaled = scaler.fit_transform(df.drop(columns= 'date' )) 
df_scaled = pd.DataFrame(df_scaled, columns=df.drop(columns= 'date' ).columns)

经典滑动窗

我们需要将数据框转换为滑动窗口张量,这是 LSTM 模型中需要的输入。我们使用 10 天作为过去数据的窗口

image.png

滑动窗口

def  create_window ( target, feature, window= 1 , offset= 0 ): 
    feature_new, target_new = [], [] 
    feature_np = feature.to_numpy() 
    target_np = target.to_numpy()
    对于范围内的 i (window, target.shape[ 0 ] - 偏移量):         feature_list = feature_np[i - window:i]         feature_new.append(feature_list.reshape(window, feature_np.shape[ 1 ]))         target_new.append(target_np[i+offset].reshape( 1 ))返回np.array(feature_new), np.array(target_new) window = 10 feature_columns = [



    


'湿度' , 'wind_speed' , 'meanpressure' , 'meantemp' ]

特征, target = create_window(df_scaled[ 'meantemp' ],df_scaled[feature_columns], window=window) 
df_scaled.head()

训练-测试拆分

最后,在数据预处理中,我们会根据时间顺序将数据拆分为Train-Test

def  train_test ( feature, target, perc_train = 0.9 ): 
    size_train = int ( len (feature) * perc_train) 

    x_train = feature[ 0 :size_train] 
    y_train = target[ 0 :size_train] 

    x_test = feature[size_train: len (feature)] 
    y_test = target[size_train: len (feature)]

    返回x_train, x_test, y_train, y_test

image.png

平均温度的训练测试拆分

LSTM 建模构建

我们主要处理了所需的数据预处理,所以现在让我们深入研究模型构建部分。我们将使用具有 LSTM 和密集层的深层网络的顺序模型和均方误差作为我们的评估指标

def model_lstm (x_shape):

    模型 = keras. 顺序()
    模型。添加( keras.layers.LSTM ( 50 ,return_sequences=True, input_shape=(x_shape[ 1 ], x_shape[ 2 ])))    模型。添加(keras.layers.LSTM ( 64 , return_sequences = False))    模型。添加(keras.layers.Dense ( 32 ))    模型。添加(keras.layers.Dense ( 16 ) )    模型。添加(keras.layers。



密集(x_shape[ 2 ]))
    
    模型。编译(loss= 'mean_squared_error' , optimizer= 'adam' )
    返回模型

image.png

模型训练与评估

完成模型训练后,我们将进入其性能评估。从下图中,我们可以判断模型性能相当不错,我们能够实现非常低的 MSE 损失,约为 0.003。

image.png

总的来说,如果我们看到测试的预测值与原始值的汇编,重叠非常好,表明模型能够理解模式并准确预测

image.png

结论

因此,我们总结了我们对 LSTM 的学习和在时间序列数据集上的实际应用。