LSTM预测股票走势

elegy887 2024-10-12 09:01:04 阅读 80

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

LSTM的应用现状

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

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

LSTM预测股票收盘价格

提取数据

<code>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')code>

data

 

<code># 提取训练数据

new_data = data['close'] # 我们预测的是收盘价,所以单独提取出close收盘价数据

train_data = new_data[:2500] # 将股票的百分之70作为训练数据

#把训练数据转化为列向量

train_prices = train_data.values.reshape(-1, 1)

train_prices

 

数据归一化

归一化的意义¶

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

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

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

<code># 数据归一化

#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

 

创建训练数据

<code># 创建训练数据

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模型

<code>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' 指定损失函数为均方误差,适合回归问题,用于衡量预测值与实际值之间的差距。code>

#optimizer='adam' 指定优化器为 Adam,这是一种常用的随机优化算法,适合大多数情况。code>

model.compile(loss='mean_squared_error', optimizer='adam')code>

# 创建一个早停法的回调函数

#早停法(Early Stopping)是一种常用的正则化技术,它的作用是帮助防止模型在训练过程中过拟合。早停法通过监控验证集(或测试集)的性能指标,当模型在验证集上的性能不再提升或开始下降时,停止模型的训练,从而避免模型在训练数据上过度拟合

early_stop = EarlyStopping(monitor='val_loss', patience=10, verbose=1)code>

# 拟合模型

#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. 查看损失曲线图

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

<code>import matplotlib.pyplot as plt

# 绘制训练过程中的损失曲线

plt.plot(history.history['loss'], label='train')code>

plt.plot(history.history['val_loss'], label='validation')code>

plt.xlabel('Epoch')

plt.ylabel('Loss')

plt.legend()

plt.show()

 

预测分析

<code># 提取测试数据

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')code>

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='平安樱银行股票收盘价-测试数据')code>

plt.plot(test_dates, predicted_prices_scaled, label='LSTM预测收盘价格')code>

plt.legend()

plt.show()

 总结

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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。