问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

基于LSTM实现多输入多输出单步预测(案例+源码)

创作时间:
作者:
@小白创作中心

基于LSTM实现多输入多输出单步预测(案例+源码)

引用
CSDN
1.
https://blog.csdn.net/sinat_41858359/article/details/140091523

本文将详细介绍如何使用LSTM(长短期记忆网络)实现多输入多输出的单步预测。具体来说,我们将使用一个包含多个特征变量的数据集,通过LSTM模型同时预测多个标签的未来值。

一、引言

单站点多变量输入多变量输出单步预测问题----基于LSTM实现。

  • 多输入就是输入多个特征变量
  • 多输出就是同时预测出多个标签的结果
  • 单步就是利用过去N天预测未来1天的结果

二、实现过程

2.1 读取数据集

import pandas as pd

df = pd.read_csv("data.csv", parse_dates=["Date"], index_col=[0])
print(df.shape)
print(df.head())
fea_num = len(df.columns)  

2.2 划分数据集

import numpy as np
import matplotlib.pyplot as plt

# 拆分数据集为训练集和测试集
test_split = round(len(df) * 0.20)
df_for_training = df[:-test_split]
df_for_testing = df[-test_split:]

# 绘制训练集和测试集的折线图
plt.figure(figsize=(10, 6))
plt.plot(df_for_training.index, df_for_training.values, label='Training Data')
plt.plot(df_for_testing.index, df_for_testing.values, label='Testing Data')
plt.xlabel('Year')
plt.ylabel('Passenger Count')
plt.title('International Airline Passengers - Training and Testing Data')
plt.legend()
plt.show()  

共5203条数据,8:2划分:训练集4162,测试集1041。

2.3 归一化

from sklearn.preprocessing import MinMaxScaler

# 将数据归一化到 0~1 范围(整体一起做归一化)
scaler = MinMaxScaler(feature_range=(0,1))
df_for_training_scaled = scaler.fit_transform(df_for_training)
df_for_testing_scaled = scaler.transform(df_for_testing)  

2.4 构造LSTM数据集(时序-->监督学习)

def createXY(data, win_size, target_feature_idxs):
    X, Y = [], []
    for i in range(len(data) - win_size):
        X.append(data[i:(i + win_size), :])
        Y.append(data[i + win_size, target_feature_idxs])
    return np.array(X), np.array(Y)

win_size = 12 # 时间窗口
target_feature_idxs = [0, 1, 2, 3, 4] # 指定待预测特征列索引
trainX, trainY = createXY(df_for_training_scaled, win_size, target_feature_idxs)
testX, testY = createXY(df_for_testing_scaled, win_size, target_feature_idxs)
print("训练集形状:", trainX.shape, trainY.shape)
print("测试集形状:", testX.shape, testY.shape)

# 将数据集转换为 LSTM 模型所需的形状(样本数,时间步长,特征数)
trainX = np.reshape(trainX, (trainX.shape[0], win_size, fea_num))
testX = np.reshape(testX, (testX.shape[0], win_size, fea_num))
print("trainX Shape-- ",trainX.shape)
print("trainY Shape-- ",trainY.shape)
print("testX Shape-- ",testX.shape)
print("testY Shape-- ",testY.shape)  

滑动窗口设置为12:

  • 取出df_for_training_scaled第【1-12】行第【1-5】列的12条数据作为trainX[0],
  • 取出df_for_training_scaled第【13】行第【1-5】列的1条数据作为trainY[0];
  • 依此类推。最终构造出的训练集数量(4150)比划分时候的训练集数量(4162)少一个滑动窗口(12)。

trainX是一个(4150,12,5)的三维数组,三个维度分布表示(样本数量,步长,特征数),每一个样本比如trainX[0]是一个(12,5)二维数组表示(步长,特征数),这也是LSTM模型每一步的输入。
trainY是一个(4150,5)的二维数组,二个维度分布表示(样本数量,标签数),每一个样本比如trainY[0]是一个(5,)一维数组表示(标签数,),这也是LSTM模型每一步的输出。

2.5 建立模拟合模型

from keras.models import Model
from keras.layers import Input, LSTM, Dense

# 输入维度
input_shape = Input(shape=(trainX.shape[1], trainX.shape[2]))
# LSTM层
lstm_layer = LSTM(128, activation='relu')(input_shape)
# 全连接层
dense_1 = Dense(64, activation='relu')(lstm_layer)
dense_2 = Dense(32, activation='relu')(dense_1)
# 输出层
output_1 = Dense(1, name='Open')(dense_2)
output_2 = Dense(1, name='High')(dense_2)
output_3 = Dense(1, name='Low')(dense_2)
output_4 = Dense(1, name='Close')(dense_2)
output_5 = Dense(1, name='AdjClose')(dense_2)
model = Model(inputs = input_shape, outputs = [output_1, output_2, output_3, output_4, output_5])
model.compile(loss='mse', optimizer='adam')
model.summary()  

这是一个多输入多输出的 LSTM 模型,接受包含12个时间步长和5个特征的输入序列,在经过一层128个神经元的 LSTM 层和5个全连接层后,输出5个单独的预测结果,分别是 Open、High、 Low、Close和 AdjClose。

进行训练,这里[trainY[:,i] for i in range(trainY.shape[1])]把原来的trainY做了转置,是一个(5,4150)的二维数组,分别表示(标签数,样本数)。相当于建立了5个通道,每个通道是(4150,)的一维数组。

history = model.fit(trainX, [trainY[:,i] for i in range(trainY.shape[1])], epochs=20, batch_size=32)  

2.6 进行预测

进行预测,上面我们分析过模型每一步的输入是一个(12,5)二维数组表示(步长,特征数),模型每一步的输出是是一个(5,)一维数组表示(标签数,)。

prediction_test = model.predict(testX)  

如果直接model.predict(testX),testX的形状是(1029,12,5),是一个批量预测,输出prediction_test是一个(5,1029,1)的三维数组,prediction_test[0]就是第一个标签的预测结果,prediction_test[1]就是第二个标签的预测结果...多输出就是同时预测出多个标签的结果

2.7 预测效果展示

分析一下第一个变量open的效果,i=0:

prediction_train = model.predict(trainX)
prediction_train0 = model.predict(trainX)[0]
prediction_train_copies_array = np.repeat(prediction_train0, fea_num, axis=-1)
pred_train = scaler.inverse_transform(prediction_train_copies_array)[:, 0]

original_train_copies_array = trainY
original_train = scaler.inverse_transform(original_train_copies_array)[:, 0]

print("train Pred Values-- ", pred_train)
print("\ntrain Original Values-- ", original_train)

plt.plot(df_for_training.index[win_size:,], original_train, color = 'red', label = '真实值')
plt.plot(df_for_training.index[win_size:,], pred_train, color = 'blue', label = '预测值')
plt.title('Stock Price Prediction')
plt.xlabel('Time')
plt.xticks(rotation=45)
plt.ylabel('Stock Price')
plt.legend()
plt.show()  

训练集真实值与预测值:

测试集真实值与预测值:

prediction_test = model.predict(testX)
prediction_test0 = model.predict(testX)[0]
prediction_test_copies_array = np.repeat(prediction_test0, fea_num, axis=-1)
pred_test = scaler.inverse_transform(prediction_test_copies_array)[:, 0]

original_test_copies_array = testY
original_test = scaler.inverse_transform(original_test_copies_array)[:, 0]

print("\ntest Original Values-- ", original_test)
plt.plot(df_for_testing.index[win_size:,], original_test, color = 'red', label = '真实值')
plt.plot(df_for_testing.index[win_size:,], pred_test, color = 'blue', label = '预测值')
plt.title('Stock Price Prediction')
plt.xlabel('Time')
plt.xticks(rotation=45)
plt.ylabel('Stock Price')
plt.legend()
plt.show()  

2.8 评估指标

通过上述预测效果展示,我们可以直观地看到模型在训练集和测试集上的表现。为了更准确地评估模型的预测能力,可以计算一些定量的评估指标,如均方误差(MSE)、均方根误差(RMSE)等。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号