使用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()
- 绘制训练损失和验证损失的曲线。
- 对模型的预测结果进行反归一化处理,确保恢复到原始的股票价格范围。
- 绘制真实值与预测值的对比图。
热门推荐
四年级孩子数学成绩差怎么才能提高?全面深度分析!
《鬼灭之刃》为何成为少年漫画多年来最受欢迎的系列:深入探究其成功之道
厦门大学材料科学考研全攻略:难度分析、招生录取及复习规划
人格发展障碍:在迷雾中找寻自我
2024全球量子产业发展现状及展望报告
甲减全攻略:从病因到治疗再到日常养生
一文读懂GDP的三种计算方法:生产法、收入法与支出法
陕西人爱吃的18道经典秦菜,你都吃过吗?
图书出版新趋势:数字化浪潮下的机遇与挑战
中国越南盾汇率走势:最新趋势与预测分析
人类对话型AI,道德责任与法律界限探讨
社交元素深度嵌入网站建设带来的社交化变革
《姥姥的外孙》刷爆年轻人朋友圈,为什么一部泰国家庭片让他们哭到泪崩
生肖配对如何影响伴侣的幸福指数?
全球塑料回收政策全盘点:欧盟、美国与亚洲国家如何推进可持续发展
新兵成长进行时丨陆军某旅探索开展新兵精细分配定岗
车站乘车全攻略:从进站到出站,一文读懂火车站指示牌
股票风险的分析方法如何选择?这种分析对投资策略有何影响?
比熬夜还可怕的“睡眠碎片化”,如何改善这种情况提高睡眠质量?
识别儿童语言发育迟缓:类型、症状与应对策略
高考180多分男孩逆袭成双一流硕士,发帖讲故事鼓励考研学子
杀不死你的,会让你生不如死丨PTSD自助手册
探讨AI创作作品的著作权归属问题
猫塑女风爆火 如何打造猫系女孩妆容?
《大明混一图》:令人叹为观止的古代世界地图
SCI论文写作效率提升的多维度解析
降低半导体供应链风险:关键策略与实践
吕布之死:勇猛战神的悲剧人生
芝加哥大学计算机科学专业必修课程详解
Windows 11支持播放杜比视界电影吗?如何设置才能享受?