使用LSTM进行股票价格的时间序列预测
创作时间:
作者:
@小白创作中心
使用LSTM进行股票价格的时间序列预测
引用
CSDN
1.
https://m.blog.csdn.net/weixin_43729592/article/details/145108331
本文将详细介绍如何使用LSTM(长短期记忆网络)进行股票价格的时间序列预测。通过Python代码实现数据加载、预处理、模型定义、训练和结果可视化等多个步骤,帮助读者理解LSTM模型在实际问题中的应用。
1. 导入库并加载数据
import torch
import torch.nn as nn
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from torch.utils.data import DataLoader, Dataset
from torch.utils.data import TensorDataset
import matplotlib.pyplot as plt
from tqdm import tqdm # 导入tqdm库
import warnings # 避免一些可以忽略的报错
warnings.filterwarnings('ignore') # 过滤警告信息
plt.rcParams['font.sans-serif'] = ['SimHei'] # 正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
# 加载数据
df = pd.read_csv("Microsoft_Stock.csv")
print(f"len(df): {len(df)}")
df.head()
# 提取收盘价数据
Close = df['Close'].values
print(f"Close: {len(Close)}") # Close:1511
# 绘制收盘价变化图
plt.plot([i for i in range(len(Close))], Close)
- 导入必要的库,包括 PyTorch、Pandas、Numpy、sklearn、Matplotlib 等。
- 读取 CSV 文件,提取相关列(如 Date、Open、High、Low、Close),并绘制收盘价变化图。
2. 数据预处理与归一化
# 选择相关的列,数据列名为:['Date', 'Open', 'High', 'Low', 'Close']
df = df[['Date', 'Open', 'High', 'Low', 'Close']]
# 转换日期为日期类型
df['Date'] = pd.to_datetime(df['Date'])
# 使用 MinMaxScaler 归一化数据
scaler = MinMaxScaler(feature_range=(-1, 1))
scaled_data = scaler.fit_transform(df[['Open', 'High', 'Low', 'Close']])
# 设置时间窗口 (Sequence Length)
seq_length = 3 # 过去3天的数据来预测当天的收盘价
# 数据划分函数
def split_data(data, seq_length):
dataX = []
datay = []
for i in range(len(data)-seq_length):
dataX.append(data[i:i+seq_length])
datay.append(data[i+seq_length, 3]) # 收盘价是目标数据(归一化后对应第4列)
dataX = np.array(dataX).reshape(len(dataX), seq_length, -1)
datay = np.array(datay).reshape(len(dataX), -1)
return np.array(dataX), np.array(datay)
# 创建数据集
dataX, datay = split_data(scaled_data, seq_length)
print(f"dataX.shape: {dataX.shape}, datay.shape: {datay.shape}")
- 选择需要的列并将日期列转换为日期类型。
- 使用 MinMaxScaler 对数据进行归一化,范围为 [-1, 1]。
- 设置时间窗口为 3,表示使用过去 3 天的数据来预测当天的收盘价。
- 使用 split_data 函数将数据划分为输入序列(dataX)和目标序列(datay)。
3. 训练集和测试集划分
# 数据集划分
X_train, X_test, y_train, y_test = train_test_split(dataX, datay, test_size=0.2, shuffle=False)
print(f"X_train.shape: {X_train.shape}, X_test.shape: {X_test.shape}")
# 转换为 PyTorch 张量
X_train = torch.tensor(X_train, dtype=torch.float32)
Y_train = torch.tensor(y_train, dtype=torch.float32)
X_test = torch.tensor(X_test, dtype=torch.float32)
Y_test = torch.tensor(y_test, dtype=torch.float32)
# 打印训练集输入张量的形状
print('X_train: ', X_train.shape)
print('Y_train: ', Y_train.shape)
# 创建训练数据集和加载器
train_dataset = TensorDataset(X_train, Y_train)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=False)
# 创建测试数据集和加载器
test_dataset = TensorDataset(X_test, Y_test)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
- 使用 train_test_split 将数据集拆分为训练集和测试集。
- 将 NumPy 数组转换为 PyTorch 张量。
- 使用 TensorDataset 和 DataLoader 创建训练集和测试集的加载器。
4. 定义 LSTM 模型
# LSTM 模型定义
class LSTMModel(nn.Module):
def __init__(self, input_size=4, hidden_size=64, output_size=1, num_layers=3):
super(LSTMModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size) # 初始化隐藏状态h0
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size) # 初始化记忆状态c0
out, _ = self.lstm(x, (h0, c0)) # 仅返回最后一个时间步的输出
out = self.fc(out[:, -1, :]) # 取最后一个时间步的输出
return out
# 初始化模型
model = LSTMModel(input_size=4, hidden_size=64, output_size=1, num_layers=1)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
- 定义 LSTM 模型类,继承自 nn.Module。
- 在 init 中初始化 LSTM 层和全连接层。
- 在 forward 方法中定义前向传播过程。
- 初始化模型,并将模型移动到 GPU(如果可用)。
5. 训练模型
# 训练模型
criterion = nn.MSELoss() # 使用均方误差损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
epochs = 100 # 设置训练轮数
train_losses = []
val_losses = []
for epoch in range(epochs):
model.train()
running_train_loss = 0.0
for x_train, y_train in tqdm(train_loader, desc=f"Epoch {epoch+1}/{epochs} - Training", ncols=100):
x_train, y_train = x_train.to(device), y_train.to(device)
optimizer.zero_grad() # 清空梯度
y_train_pred = model(x_train) # 模型预测
loss = criterion(y_train_pred, y_train) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新权重
running_train_loss += loss.item() * x_train.size(0) # 累加训练损失
epoch_train_loss = running_train_loss / len(train_loader.dataset)
train_losses.append(epoch_train_loss)
# 验证集评估
model.eval()
running_val_loss = 0.0
with torch.no_grad():
for x_test, y_test in test_loader:
x_test, y_test = x_test.to(device), y_test.to(device)
y_test_pred = model(x_test) # 模型预测
loss = criterion(y_test_pred, y_test) # 计算损失
running_val_loss += loss.item() * x_test.size(0) # 累加验证损失
epoch_val_loss = running_val_loss / len(test_loader.dataset)
val_losses.append(epoch_val_loss)
print(f"Epoch {epoch+1}/{epochs}, Train Loss: {epoch_train_loss:.4f}, Validation Loss: {epoch_val_loss:.4f}")
- 设置损失函数为均方误差 (MSELoss),优化器为 Adam。
- 在每个 epoch 中训练模型,并记录训练损失和验证损失。
- 使用 tqdm 显示训练进度条。
6. 绘制损失曲线和预测结果
# 绘制训练和验证损失曲线
plt.figure(figsize=(8, 6))
plt.plot(range(1, epochs+1), train_losses, label='Train Loss', marker='o')
plt.plot(range(1, epochs+1), val_losses, label='Validation Loss', marker='s')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Training and Validation Loss')
plt.legend()
# 获取模型预测值并反归一化
predictions = model(X_test).detach().numpy().reshape(-1, 1)
real_values = Y_test.detach().numpy().reshape(-1, 1)
# 将 predictions 和 real_values 转换为 (302, 4) 的数组,填充前三列为零
predictions = np
.column_stack([np.zeros((predictions.shape[0], 3)), predictions]) # 填充前三列为零
real_values = np.column_stack([np.zeros((real_values.shape[0], 3)), real_values]) # 填充前三列为零
# 反归一化
predictions = scaler.inverse_transform(predictions)[:, 3] # 提取最后一列(即收盘价)
real_values = scaler.inverse_transform(real_values)[:, 3] # 提取最后一列(即收盘价)
# 绘制预测结果与真实值

plt.figure(figsize=(12, 6))
plt.plot(real_values, label='真实值', color='blue')
plt.plot(predictions, label='预测值', color='red', linestyle='dashed')
plt.xlabel('时间步')
plt.ylabel('股票价格')
plt.title('LSTM 模型预测结果 vs 真实值')
plt.legend()
plt.show()
- 绘制训练损失和验证损失的曲线。
- 对模型的预测结果进行反归一化处理,确保恢复到原始的股票价格范围。
- 绘制真实值与预测值的对比图。
热门推荐
双肺多发性磨玻璃结节怎么办
历史上的司马氏是个什么样的家族?是如何发迹的
如何规划客户价值管理
白骑士综合征是什么
非法定继承人继承的要求有哪些
清明:一个揭示向死而在的节日
个人信誉调查是什么?如何维护良好的信用记录?
天津渤海职业技术学院学费多少钱一年-各专业收费标准
AI软件测试的未来:自动化测试与智能化分析的结合
铁矿石开采详细步骤
首次公开!长征九号重型火箭来了,一级重复2030年首飞,两级33年
进程的基础知识
塔罗牌恶魔逆位:感情发展新解读
2025深圳眼科医院三甲风采:专业服务深度解析
羊奶的热量
银行的理财产品和存款有什么不同?
经常拉伸小腿肌肉会瘦小腿吗
古代诗人笔下的晚霞:从刘禹锡到王国维
市场供需法则:探究股票价格变动的基本经济原理
痛性眼肌麻痹:Tolosa-Hunt综合征的病因、诊断与治疗
体检前一天晚餐食谱
以中国故事开创中国风格
基于红利基金探究基金高频次分红策略
肝火旺盛,针灸这些穴位助你泻火
《GTAOL》24年限时国安局警察套装获取方法 官方警察局套装怎么获取
13本百年前的排日账,勾勒出中国农民的家庭日常
自我介绍英语口语对话
从男神到奥斯卡影帝,盘点莱昂纳多·迪卡普里奥的11部高分电影
旅途的意义:探索、成长与内心的平静
家庭教育中的理财规划启蒙:为孩子打下坚实的财务基础