Pytorch项目实战 :基于RNN的实现情感分析 视频教程 下载

67 阅读4分钟

获课地址:666it.top/4842/

时序预测——基于LSTM的股票价格趋势预测

引言
从自然语言处理领域,我们转向另一个重要的方向:时间序列预测。无论是金融领域的股票价格、商品销量预测,还是工业领域的设备故障预警,时序预测都有着巨大的应用价值。对于求职者来说,拥有一个时序预测项目,能证明你处理结构化数据、理解数据动态变化的能力。本篇将以经典的股票价格预测为例,手把手教你如何使用PyTorch构建一个LSTM模型来预测未来的股价趋势。

项目拆解:核心流程

  1. 数据理解与准备:时序数据的核心特征是时间依赖性。我们需要将原始的时间序列数据(如每日收盘价)转换为监督学习问题。常用的方法是创建“滑动窗口”,即用过去N天的数据作为特征(X),来预测第N+1天的数据作为标签(y)。
  2. 数据标准化:神经网络对输入数据的尺度非常敏感。对于股价这种数值范围较大的数据,使用MinMaxScaler将其缩放到[0, 1]或[-1, 1]区间是至关重要的预处理步骤。
  3. 模型构建:我们将再次使用LSTM,因为其记忆单元非常适合捕捉时间序列中的长期依赖关系。模型结构相对简单:一个LSTM层后接一个全连接层输出预测值。
  4. 训练与评估:在时序预测中,数据集的划分必须保持时间顺序,绝不能随机打乱。我们通常用较早的数据作为训练集,较晚的数据作为测试集。评估指标常用均方根误差或平均绝对误差。

PyTorch实战代码

import torch
import torch.nn as nn
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
import math

# --- 1. 数据准备与预处理 ---

# 创建一个模拟的股票价格数据
np.random.seed(42)
days = 200
prices = np.cumsum(np.random.randn(days) * 2 + 100) + 5000
data = pd.DataFrame(prices, columns=['Close'])

# 数据标准化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data)

# 创建滑动窗口数据集
def create_dataset(dataset, look_back=1):
    dataX, dataY = [], []
    for i in range(len(dataset) - look_back - 1):
        a = dataset[i:(i + look_back), 0]
        dataX.append(a)
        dataY.append(dataset[i + look_back, 0])
    return np.array(dataX), np.array(dataY)

look_back = 10 # 用过去10天的数据预测第11天
X, y = create_dataset(scaled_data, look_back)

# 划分训练集和测试集 (按时间顺序)
train_size = int(len(X) * 0.8)
test_size = len(X) - train_size
trainX, testX = X[0:train_size,:], X[train_size:len(X),:]
trainY, testY = y[0:train_size], y[train_size:len(y)]

# 转换为PyTorch Tensors
trainX = torch.from_numpy(trainX).float()
trainY = torch.from_numpy(trainY).float()
testX = torch.from_numpy(testX).float()
testY = torch.from_numpy(testY).float()

# 为LSTM调整输入形状 [samples, time_steps, features]
trainX = trainX.view(trainX.shape[0], trainX.shape[1], 1)
testX = testX.view(testX.shape[0], testX.shape[1], 1)

# --- 2. 模型构建 ---

class StockPriceLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(StockPriceLSTM, 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).to(x.device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        
        # LSTM前向传播
        out, _ = self.lstm(x, (h0, c0))
        
        # 只取最后一个时间步的输出
        out = self.fc(out[:, -1, :])
        return out

# --- 3. 训练循环 ---

# 超参数
input_size = 1
hidden_size = 50
num_layers = 2
output_size = 1
learning_rate = 0.01
num_epochs = 100

# 实例化模型、损失函数和优化器
model = StockPriceLSTM(input_size, hidden_size, num_layers, output_size)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
for epoch in range(num_epochs):
    model.train()
    outputs = model(trainX)
    optimizer.zero_grad()
    loss = criterion(outputs, trainY.view(-1, 1))
    loss.backward()
    optimizer.step()
    
    if (epoch+1) % 10 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.6f}')

# --- 4. 评估与预测 ---

model.eval()
with torch.no_grad():
    train_predict = model(trainX)
    test_predict = model(testX)

# 反标准化,将预测值转换回原始尺度
train_predict = scaler.inverse_transform(train_predict.numpy())
trainY_original = scaler.inverse_transform(trainY.view(-1, 1).numpy())
test_predict = scaler.inverse_transform(test_predict.numpy())
testY_original = scaler.inverse_transform(testY.view(-1, 1).numpy())

# 计算RMSE
trainScore = math.sqrt(mean_squared_error(trainY_original, train_predict))
print(f'Train Score: {trainScore:.2f} RMSE')
testScore = math.sqrt(mean_squared_error(testY_original, test_predict))
print(f'Test Score: {testScore:.2f} RMSE')

# --- 5. 结果可视化 (需要matplotlib) ---
# import matplotlib.pyplot as plt
# train_predict_plot = np.empty_like(scaled_data)
# train_predict_plot[:, :] = np.nan
# train_predict_plot[look_back:len(train_predict)+look_back, :] = train_predict

# test_predict_plot = np.empty_like(scaled_data)
# test_predict_plot[:, :] = np.nan
# test_predict_plot[len(train_predict)+(look_back*2)+1:len(scaled_data)-1, :] = test_predict

# plt.plot(scaler.inverse_transform(scaled_data), label='Original Data')
# plt.plot(train_predict_plot, label='Train Predict')
# plt.plot(test_predict_plot, label='Test Predict')
# plt.legend()
# plt.show()

总结与就业对标
本篇文章带你完成了第一个时序预测项目。在面试中,你需要重点突出以下几点:

  • 数据转换:清晰地解释为什么以及如何将时间序列数据通过“滑动窗口”转换为监督学习格式。这是时序建模的基石。
  • 数据划分:强调时序数据不能随机划分,必须按时间顺序切分,以避免“未来信息泄露”到训练中。
  • 模型选择:阐述为什么LSTM比传统的ARIMA或简单的MLP更适合处理具有长期依赖性的时序数据。
  • 评估指标:解释为什么在回归问题中,RMSE比准确率更合适。
    这个项目展示了你处理非文本、非图像的结构化数据的能力,拓宽了你的技术栈,使你在求职市场上更具竞争力。