《Python实战进阶》No35:循环神经网络(RNN)时间序列预测
Python实战进阶:循环神经网络(RNN)时间序列预测
摘要
在本篇文章中,我们将深入探讨循环神经网络(RNN)在时间序列预测中的应用。我们将从基础概念出发,逐步构建一个完整的股票价格预测系统,并探讨LSTM和GRU这两种重要的RNN变体。通过实战案例(苹果公司近一年的股价实盘和预测曲线),读者将掌握如何预处理时间序列数据、构建和训练RNN模型,以及如何评估预测结果。
核心概念和知识点
1. 时间序列数据的特点与挑战
- 时间依赖性:数据点之间存在时间上的依赖关系
- 趋势性:数据可能呈现长期上升或下降趋势
- 季节性:数据可能呈现周期性变化
- 噪声:数据中可能包含随机波动
2. RNN、LSTM和GRU的结构与区别
- RNN:基础循环神经网络,存在梯度消失问题
- LSTM:通过门控机制解决梯度消失问题
- GRU:LSTM的简化版本,计算效率更高
3. 序列到序列(Seq2Seq)模型
- 编码器-解码器架构
- 注意力机制
- 多步预测策略
4. 与 AI 大模型的关联
- Transformer 的崛起 :基于自注意力机制的模型(如 Informer)在长序列预测中表现优异。
- 混合模型 :结合 CNN(提取局部特征)和 LSTM(建模时序依赖)提升预测精度。
实战案例:股票价格预测
- 我们将使用苹果公司(AAPL)的历史股价数据
实战代码依赖包:
numpy>=1.21.0
pandas>=1.3.0
yfinance>=0.1.63
torch>=1.9.0
scikit-learn>=0.24.2
matplotlib>=3.4.2
1. 环境准备
import numpy as np
import pandas as pd
import yfinance as yf
import torch
import torch.nn as nn
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
2. 数据获取和预处理
# 获取股票数据
def get_stock_data(symbol, start_date, end_date):
stock = yf.download(symbol, start=start_date, end=end_date)
return stock['Close'].values.reshape(-1, 1)
# 数据预处理
def prepare_data(data, sequence_length):
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
X, y = [], []
for i in range(len(scaled_data) - sequence_length):
X.append(scaled_data[i:(i + sequence_length)])
y.append(scaled_data[i + sequence_length])
return np.array(X), np.array(y), scaler
3. 构建LSTM模型
class LSTMPredictor(nn.Module):
def __init__(self, input_dim, hidden_dim, num_layers, output_dim):
super(LSTMPredictor, self).__init__()
self.hidden_dim = hidden_dim
self.num_layers = num_layers
self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).to(x.device)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[:, -1, :])
return out
4. 训练模型
def train_model(model, X_train, y_train, epochs=100):
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
5. 预测和可视化
def predict_and_plot(model, X_test, y_test, scaler):
model.eval()
with torch.no_grad():
predictions = model(X_test)
# 反归一化
predictions = scaler.inverse_transform(predictions.numpy())
y_test = scaler.inverse_transform(y_test)
# 绘制结果
plt.figure(figsize=(10, 6))
plt.plot(y_test, label='实际值')
plt.plot(predictions, label='预测值')
plt.title('股票价格预测')
plt.xlabel('时间')
plt.ylabel('价格')
plt.legend()
plt.show()
程序运行输出:
可以看到红色预测线在趋势上整体比较准确,适合波段量化操作使用
完整代码:
import numpy as np
import pandas as pd
import yfinance as yf
import torch
import torch.nn as nn
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
# 设置随机种子以确保结果可复现
torch.manual_seed(42)
np.random.seed(42)
# 获取股票数据
def get_stock_data(symbol, start_date, end_date):
stock = yf.download(symbol, start=start_date, end=end_date)
return stock['Close'].values.reshape(-1, 1)
# 数据预处理
def prepare_data(data, sequence_length):
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)
X, y = [], []
for i in range(len(scaled_data) - sequence_length):
X.append(scaled_data[i:(i + sequence_length)])
y.append(scaled_data[i + sequence_length])
return np.array(X), np.array(y), scaler
class LSTMPredictor(nn.Module):
def __init__(self, input_dim, hidden_dim, num_layers, output_dim):
super(LSTMPredictor, self).__init__()
self.hidden_dim = hidden_dim
self.num_layers = num_layers
self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).to(x.device)
out, _ = self.lstm(x, (h0, c0))
out = self.fc(out[:, -1, :])
return out
def train_model(model, X_train, y_train, epochs=100):
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
def predict_and_plot(model, X_test, y_test, scaler):
model.eval()
with torch.no_grad():
predictions = model(X_test)
# 反归一化
predictions = scaler.inverse_transform(predictions.numpy())
y_test = scaler.inverse_transform(y_test)
# 绘制结果
plt.figure(figsize=(12, 6))
plt.plot(y_test, label='实际值', color='blue')
plt.plot(predictions, label='预测值', color='red', linestyle='--')
plt.title('股票价格预测')
plt.xlabel('时间')
plt.ylabel('价格')
plt.legend()
plt.grid(True)
plt.show()
def main():
# 设置参数
symbol = 'AAPL' # 苹果公司股票
sequence_length = 10
hidden_dim = 64
num_layers = 2
epochs = 100
# 获取数据
end_date = datetime.now()
start_date = end_date - timedelta(days=365)
print("正在获取股票数据...")
data = get_stock_data(symbol, start_date, end_date)
# 准备数据
print("正在预处理数据...")
X, y, scaler = prepare_data(data, sequence_length)
# 划分训练集和测试集
train_size = int(len(X) * 0.8)
X_train = torch.FloatTensor(X[:train_size])
y_train = torch.FloatTensor(y[:train_size])
X_test = torch.FloatTensor(X[train_size:])
y_test = torch.FloatTensor(y[train_size:])
# 创建模型
print("正在创建模型...")
model = LSTMPredictor(input_dim=1, hidden_dim=hidden_dim,
num_layers=num_layers, output_dim=1)
# 训练模型
print("开始训练模型...")
train_model(model, X_train, y_train, epochs)
# 预测和可视化
print("正在进行预测和可视化...")
predict_and_plot(model, X_test, y_test, scaler)
if __name__ == "__main__":
main()
与AI大模型的关联
- 大语言模型(如GPT)中的Transformer架构借鉴了RNN的序列处理思想
- 时间序列预测技术在大模型训练数据的预处理中发挥重要作用
- 混合模型(如CNN+Transformer)在时间序列预测中展现出强大潜力
总结
RNN及其变体(LSTM、GRU)是处理时间序列数据的强大工具。通过本篇文章的实战案例,我们不仅学习了如何构建和训练RNN模型,还深入理解了时间序列数据的特点和挑战。在实际应用中,我们需要根据具体问题选择合适的模型架构和参数。
扩展思考
- Transformer 在时间序列预测中的应用
优势 :自注意力机制能捕捉长距离依赖,适合处理多变量时间序列。
示例模型 :Informer、TimeSformer,可在 PyTorch Forecasting 库中快速实现。 - 混合模型(CNN + LSTM)
场景 :结合 CNN 提取空间特征(如图像序列)与 LSTM 建模时序依赖。
示例 :视频动作识别、气象预测。 - 如何处理多变量时间序列预测问题?
- 模型的可解释性在金融预测中的重要性
参考资料
- Deep Learning with PyTorch
- Time Series Forecasting with Deep Learning
- Attention Is All You Need