LSTM预测股票走势 LSTM预测股票数据

前提:数据集还是之前几篇文章的那个数据集

LSTM的应用现状

长短期记忆神经网络(LSTM)是一种特殊的循环神经网络(RNN)。原始的RNN在训练中,随着训练时间的加长以及网络层数的增多,很容易出现梯度爆炸或者梯度消失的问题,导致无法处理较长序列数据,从而无法获取长距离数据的信息。

LSTM应用的领域包括:文本生成、机器翻译、语音识别、生成图像描述和视频标记等。

LSTM预测股票收盘价格

提取数据

from keras.models import Sequential
from keras.layers import LSTM, Dense
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import numpy as np
# 读取平安银行股票数据并将date日期作为索引
data = pd.read_csv('./000001.XSHE.csv',index_col='trade_date')
data

 

# 提取训练数据
new_data = data['close'] # 我们预测的是收盘价,所以单独提取出close收盘价数据
train_data = new_data[:2500] # 将股票的百分之70作为训练数据
#把训练数据转化为列向量
train_prices = train_data.values.reshape(-1, 1)
train_prices

 

数据归一化

归一化的意义

避免特征间的量纲不同带来的影响: 当特征的取值范围不同时,某些机器学习算法可能会因为特征值的差异而表现不佳。归一化可以将所有特征的值都缩放到相似的范围内,使得各个特征对模型的影响权重基本相同。

加速模型收敛: 对数据进行归一化可以使得优化算法(如梯度下降法)更快收敛,因为特征值相似范围内的数据更容易找到全局最优解或局部最优解。

提高模型的精度和稳定性: 归一化可以减少数据范围对模型训练过程的影响,提高模型的泛化能力和稳定性。

# 数据归一化
#Step 1: 初始化归一化器
#feature_range=(0, 1) 参数指定了将数据缩放到 [0, 1] 的范围内。
scaler = MinMaxScaler(feature_range=(0, 1))
#对训练数据进行拟合和转换
#scaler.fit(train_prices): 这一步是拟合归一化器,计算训练数据 train_prices 的最小值和最大值。
#scaler.transform(train_prices): 接着,transform 方法将 train_prices 数据根据已计算的最小值和最大值进行缩放转换
train_scaled = scaler.fit_transform(train_prices)
train_scaled

 

创建训练数据集

# 创建训练数据集
X_train = []
y_train = []
#个样本将由过去 30 个时间步的数据组成作为特征输入。
timesteps = 30 # 时间步长(指定了每个训练样本(或者说每个输入序列)包含的时间步数量)
for i in range(timesteps, len(train_scaled)):
 #对于每个 i,将 train_scaled 中从 i-timesteps 到 i-1 的数据切片取出,即过去 timesteps 个时间步的数据。
 #这个数据是列向量的数据,保证每个x都有timesteps 个时间步的数据
 X_train.append(train_scaled[i - timesteps:i, 0])
 
 #对于每个 i,将 train_scaled 中第 i 个时间步的第一个特征值(即下一个时间步的数据)添加到 y_train 中。
 #这些值将作为对应训练样本的目标输出。
 y_train.append(train_scaled[i, 0])
 
# 将训练数据转为数组形式
X_train, y_train = np.array(X_train), np.array(y_train)
# 调整输入数据的维度
"""
在使用 RNN 或者 LSTM 等模型时,输入数据的形状应为 (samples, timesteps, features)。
X_train.shape[0] 是样本数量,X_train.shape[1] 是时间步数。
np.reshape 用来将 X_train 的形状调整为 (samples, timesteps, 1),其中 1 表示每个时间步只有一个特征(单变量时间序列预测
"""
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
X_train

 

构建LSTM模型

from keras.callbacks import EarlyStopping
# 构建LSTM模型
#创建一个序贯模型,即层的线性堆叠
model = Sequential()
#添加一个具有 50 个 LSTM 单元的层。return_sequences=True 表示该层将返回完整的输出序列而不仅仅是最后一个时间步的输出。
#input_shape=(X_train.shape[1], 1) 指定输入数据的形状,其中 X_train.shape[1] 对应于每个样本的特征数,这里是时间步数(timesteps),1 是每个时间步的特征数。
model.add(LSTM(50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
#添加第二个具有 50 个 LSTM 单元的层,这一层默认的 return_sequences 为 False,即默认只返回最后一个时间步的输出。
model.add(LSTM(50))
#Dense(1) 添加一个全连接层,输出维度为 1,用于预测单一数值。
model.add(Dense(1))
# 编译模型
#loss='mean_squared_error' 指定损失函数为均方误差,适合回归问题,用于衡量预测值与实际值之间的差距。
#optimizer='adam' 指定优化器为 Adam,这是一种常用的随机优化算法,适合大多数情况。
model.compile(loss='mean_squared_error', optimizer='adam')
# 创建一个早停法的回调函数
#早停法(Early Stopping)是一种常用的正则化技术,它的作用是帮助防止模型在训练过程中过拟合。早停法通过监控验证集(或测试集)的性能指标,当模型在验证集上的性能不再提升或开始下降时,停止模型的训练,从而避免模型在训练数据上过度拟合
early_stop = EarlyStopping(monitor='val_loss', patience=10, verbose=1)
# 拟合模型
#epochs=100 指定训练轮数,即整个数据集将被训练 100 次。
#batch_size=32 指定每次训练的样本数目,每次更新模型的参数(权重)时使用的样本数。
#validation_split=0.2 表示将训练数据的 20% 用作验证集。这种方法适用于没有单独验证集的情况。
history = model.fit(X_train, y_train, epochs=100, batch_size=32, validation_split=0.2, callbacks=[early_stop])

 

绘制损失曲线观察模型是否过拟合

1. 观察训练集和验证集损失的趋势

训练集损失和验证集损失的比较: 训练集损失:它衡量了模型在训练数据上的拟合情况。随着训练的进行,训练集损失应该逐渐减少,直到收敛到一个稳定的水平。 验证集损失:它衡量了模型在没有见过的验证数据上的泛化能力。如果模型过拟合,验证集损失会在某个点开始上升,而不是继续下降或保持稳定。

2. 查看损失曲线图

绘制训练集和验证集的损失曲线: 如果模型在训练集上表现良好但在验证集上表现不佳,可能存在过拟合问题。 如果两条曲线的趋势基本一致且损失都在减小,可能表明模型正在有效地学习。

import matplotlib.pyplot as plt
# 绘制训练过程中的损失曲线
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='validation')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()

 

预测分析

# 提取测试数据
test_data = new_data[2500:] # 百分之30作为测试数据
test_prices = test_data.values.reshape(-1, 1)
# 数据归一化
test_scaled = scaler.transform(test_prices)
# 创建测试数据集
x_test = []
y_test = []
for i in range(timesteps, len(test_scaled)):
 x_test.append(test_scaled[i - timesteps:i, 0])
 y_test.append(test_scaled[i, 0])
# 将测试数据转为数组形式
x_test, y_test = np.array(x_test), np.array(y_test)
# 调整输入数据的维度
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
x_test
# 使用模型进行预测
predicted_prices = model.predict(X_test)
predicted_prices

结果可视化

# 预测结果可视化
import seaborn as sns
sns.set(font='SimHei')
plt.rcParams['font.sans-serif'] = ['SimHei'] #解决中文显示
plt.rcParams['axes.unicode_minus'] = False #解决符号无法显示
 
# 反归一化训练集和测试集的价格数据
#把他变化原来数字的区间
train_prices_scaled = scaler.inverse_transform(train_scaled)
test_prices_scaled = scaler.inverse_transform(test_scaled)
# 反归一化预测结果
predicted_prices_scaled = scaler.inverse_transform(predicted_prices)
# 创建日期索引
test_dates = pd.to_datetime(test_data.index[timesteps:])
plt.figure(figsize=(15, 7))
plt.plot(test_dates, test_prices_scaled[timesteps:], label='平安樱银行股票收盘价-测试数据')
plt.plot(test_dates, predicted_prices_scaled, label='LSTM预测收盘价格')
plt.legend()
plt.show()

 总结

总的来看预测结果还是要比arima要好的。

作者:elegy887原文地址:https://blog.csdn.net/weixin_74177409/article/details/140879153

%s 个评论

要回复文章请先登录注册