使用 Tensorflow LSTM 进行时间序列预测

时间序列数据

时间序列数据,也称为时间戳数据,是按时间顺序索引的数据点序列。

这些数据点通常由同一来源在固定时间间隔内进行的连续测量组成,用于跟踪随时间的变化。

什么是 LSTM?

长短期记忆 (LSTM) 是一种深度学习的顺序神经网络,可以让信息持续存在。它是一种特殊类型的循环神经网络,能够学习序列预测问题中的顺序依赖性。 LSTM 旨在解决传统 RNN 模型面临的梯度消失问题。

下次我们将详细介绍 LSTM 及其架构和工作原理。在这篇文章中,我们将重点讨论使用 LSTM 来解决时间序列预测问题。

为什么使用 LSTM 进行时间序列预测?

LSTM 是一种循环神经网络,其中神经元能够学习序列数据中的模式并预测序列中的下一项。

由于时间序列数据已经是连续测量的序列,按时间顺序索引,即数据是确定的、连续的和周期性的,非常适合 LSTM 网络学习并为时间顺序中的未来连续趋势提供预测。

时间序列预测的类型

  1. 单变量时间序列预测(除时间戳特征外还有 1 个输入特征)
  2. 多元时间序列预测(除时间戳特征外超过 1 个输入特征)

在这篇文章中,我们将讨论单变量时间序列预测的 LSTM 实现。我将在下一篇文章中讨论多元时间序列预测的实现。

问题背景

耶拿气候是德国耶拿马克斯普朗克生物地球化学研究所气象站记录的天气时间序列数据集。该数据集由 14 个不同的量(例如气温、大气压、湿度、风向等)组成,这些量在几年内每 10 分钟记录一次。该数据集涵盖2009年1月1日至2016年12月31日的数据。

我们需要使用此数据中的温度记录来预测未来 10 天的温度。

首先让我们加载必要的库。

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
from datetime import date

接下来我们读取数据

clim = pd.read_csv('DataRepository/jena_climate_2009_2016.csv', index_col = 0)

您可以从以下链接找到数据(最后给出的Github链接):

我们正在实施 LSTM 模型来查找给定数据中的温度预测。这就是单变量时间序列预测。

取第 6 条记录,因为我们只需要每小时的数据,因此忽略其他所有记录(在 10 分钟级别)

如果这是业务需求,我们还可以取连续 6 条记录的平均值/中位数,但现在还不是。

df = clim[['Date Time','T (degC)']].rename(columns = {'T (degC)':'T','Date Time':'datetime'})
df['datetime'] = pd.to_datetime(df['datetime'])


df_hour_lvl = df[5::6].reset_index().drop('index', axis=1)

检查数据图和数据分布

df.plot(figsize = (15,5))

plt.figure(figsize = (14,5))
sns.distplot(df_hour_lvl['T'])

该数据是一个非常好的正态分布数据。如果我们的数据不是正态分布的,那么我们必须使用数据变换(通常是 Box-Cox 变换)将其转换为正态数据。

如果您的数据不是正态分布的,您可以在下面的链接中查看该问题的解决方案:

为 LSTM 创建输入数据

时间序列 LSTM(或任何 RNN)模型所需的输入数据不是简单的具有少量行和列的 pandas 或 pyspark 数据框。输入数据需要拆分为X和y,其中X是二维numpy数组(记录数,输入序列数),而y是一维numpy数组(记录数)。

n_input 是用于预测未来时间序列的历史输入的数量。

def Sequential_Input_LSTM(df, input_sequence):
    df_np = df.to_numpy()
    X = []
    y = []
    
    for i in range(len(df_np) - input_sequence):
        row = [a for a in df_np[i:i + input_sequence]]
        X.append(row)
        label = df_np[i + input_sequence]
        y.append(label)
        
    return np.array(X), np.array(y)


n_input = 10      

df_min_model_data = df_hour_lvl['T']

X, y = Sequential_Input_LSTM(df_min_model_data, n_input)

创建训练-测试分割

您完全可以选择用于训练、验证和测试模型的记录数量。对下面的代码进行相应的更改。

# Training data
X_train, y_train = X[:60000], y[:60000]

# Validation data
X_val, y_val = X[60000:65000], y[60000:65000]

# Test data
X_test, y_test = X[65000:], y[65000:]

创建 LSTM 模型

from tensorflow.keras.models import Sequential, save_model, load_model
from tensorflow.keras.layers import *
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.losses import MeanSquaredError
from tensorflow.keras.metrics import RootMeanSquaredError
from tensorflow.keras.optimizers import Adam 
n_features = 1                        

model1 = Sequential()

model1.add(InputLayer((n_input,n_features)))
model1.add(LSTM(100, return_sequences = True))     
model1.add(LSTM(100, return_sequences = True))
model1.add(LSTM(50))
model1.add(Dense(8, activation = 'relu'))
model1.add(Dense(1, activation = 'linear'))

model1.summary()

总共 151,817 个参数用于训练这个深度神经网络

需要注意的一些要点:

  • n_features是用于预测的输入变量的数量(这里只有1,即温度)
  • LSTM 网络使您能够将序列数据输入到网络中,并根据序列数据的各个时间步进行预测。因此,我们使用 LSTM 的equential() keras 模型。
  • 最后一个密集层中的神经元数量是我们想要的输出形状。对于时间序列,我们需要一维输出。因此,最后一个密集层中的神经元数量应该为 1。
  • 为了更好的预测,我们使用 3 层 LSTM(称为 Stacked/Deep LSTM)而不是仅 1 层 LSTM(称为 Simple LSTM)。
  • 如果使用多个 LSTM 层,请使用“return_sequences = True”,除了最后一个 LSTM 层(否则我们将面临维度不匹配错误)
  • 使用 EarlyStopping() 可以为我们节省大量时间,一旦它意识到在接下来的 epoch 中损失不会再减少,它就会停止模型训练,并且现在可以比所描述的 epoch 更早停止训练。
  • 我使用 RootMeanSquaredError() 作为模型性能评估、Adam 优化器和 relu/线性激活函数的指标。请随意尝试其他指标、优化器和激活函数并比较结果。
early_stop = EarlyStopping(monitor = 'val_loss', patience = 2)

model1.compile(loss = MeanSquaredError(), 
               optimizer = Adam(learning_rate = 0.0001), 
               metrics = RootMeanSquaredError())

model1.fit(X_train, y_train, 
           validation_data = (X_val, y_val), 
           epochs = 50, 
           callbacks = [early_stop])

检查模型性能

losses_df1 = pd.DataFrame(model1.history.history)

losses_df1.plot(figsize = (10,6))

我们可以观察到,每次迭代或 epoch 的损失都会减少,有趣的是,我们的模型只经历了 8 个 epoch,即使我们要求模型运行 50 个 epoch。这是由于使用了早期停止回调,模型在第 8 个 epoch 后停止,因为损失已降至最小值。

如果模型不能提供良好的预测,我们需要尝试一些不同的方法,例如数据缩放、数据转换、使用更多 LSTM 或密集层或调整其他超参数。

保存并重复使用模型

# save the model
save_model(model1, "LSTM_Models/lstm_univariate.h5")

# load the model
model1 = load_model('LSTM_Models/lstm_univariate.h5')

根据测试数据预测温度

test_predictions1 = model1.predict(X_test).flatten()


X_test_list = []
for i in range(len(X_test)):
    X_test_list.append(X_test[i][0])
    

test_predictions_df1 = pd.DataFrame({'X_test':list(X_test_list), 
                                    'LSTM Prediction':list(test_predictions1)})

基于完整测试数据的 LSTM 温度预测

test_predictions_df1.plot(figsize = (15,6))

测试数据中最近 1 个月的 LSTM 温度预测(720 小时)

test_predictions_df1[(len(X_test) - 720):].plot(figsize = (15,5))

现在让我们使用 LSTM 模型进行未来预测

def futureForecast(df, col, n_input, n_features, forecast_timeperiod, model):

    x_input = np.array(df[len(df)-n_input:][col])

    temp_input=list(x_input)

    lst_output=[]
    i=0

    while(i < forecast_timeperiod):

        if(len(temp_input) > n_input):

            x_input = np.array(temp_input[1:])
            x_input = x_input.reshape((1, n_input, n_features))
            yhat = model.predict(x_input, verbose=0)
            temp_input.append(yhat[0][0])
            temp_input = temp_input[1:]
            lst_output.append(yhat[0][0])

            i=i+1

        else:
            x_input = x_input.reshape((1, n_input, n_features))
            yhat = model.predict(x_input, verbose=0)
            #print(yhat[0])
            temp_input.append(yhat[0][0])
            lst_output.append(yhat[0][0])

            i=i+1
            
    return lst_output
n_input = 10
n_features = 1
forecast_timeperiod = 240         # next 10 days
model = model1

forecast_output = futureForecast(df_hour_lvl, 
                                 'T', 
                                 n_input, 
                                 n_features, 
                                 forecast_timeperiod, 
                                 model)
last_10_days = df_hour_lvl['T'][len(df_hour_lvl) - 240:].tolist()

next_10_days = pd.DataFrame(forecast_output, columns = ['FutureForecast'])
plt.figure(figsize = (15,5))p

hist_axis = len(last_10_days)
forecast_axis = hist_axis + len(next_10_days)

plt.plot(np.arange(0,hist_axis),last_10_days, color = 'blue')
plt.plot(np.arange(hist_axis,forecast_axis),next_10_days['FutureForecast'].tolist(), color = 'orange')

plt.title('LSTM Forecast for Next 10 Days')
plt.xlabel('Hours')
plt.ylabel('Temperature')

# save the figure
plt.savefig('Pics_Models/lstm_univariate_forecast_pic.png')
plt.savefig('Pics_Models/lstm_univariate_forecast_pdf.pdf')

详细代码的 GitHub 链接:

  • 34
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当然,我可以为您提供一个基于 TensorFlowLSTM 时间序列预测的代码示例。以下是一个简单的示例,用于训练一个 LSTM 模型进行预测: ```python import numpy as np import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 创建时间序列数据 data = [10, 20, 30, 40, 50, 60, 70, 80, 90] # 准备训练数据 def prepare_data(data, n_steps): X, y = [], [] for i in range(len(data)): end_idx = i + n_steps if end_idx >= len(data): break seq_x, seq_y = data[i:end_idx], data[end_idx] X.append(seq_x) y.append(seq_y) return np.array(X), np.array(y) # 定义超参数 n_steps = 3 n_features = 1 # 准备训练数据 X_train, y_train = prepare_data(data, n_steps) # 调整输入数据形状 X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], n_features)) # 构建 LSTM 模型 model = Sequential() model.add(LSTM(50, activation='relu', input_shape=(n_steps, n_features))) model.add(Dense(1)) model.compile(optimizer='adam', loss='mse') # 训练模型 model.fit(X_train, y_train, epochs=200, verbose=0) # 进行预测 test_data = [70, 80, 90, 100] X_test = np.array(test_data).reshape((1, n_steps, n_features)) y_pred = model.predict(X_test) print("预测结果:", y_pred) ``` 这个示例代码创建了一个简单的时间序列数据,并使用 LSTM 模型进行预测。首先,我们准备训练数据,并且调整输入数据的形状以符合 LSTM 模型的要求。然后,我们构建了一个包含单个 LSTM 层和一个全连接层的模型,并使用均方误差作为损失函数进行优化。最后,我们使用训练好的模型进行预测。 请注意,这只是一个简单的示例代码,您可能需要根据实际情况进行适当的修改和调整。希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoshun007~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值