23.3 时间序列实战:股票价格预测(LSTM)
时间序列实战:使用TensorFlow和Bidirectional LSTM进行股票价格预测
本章节通过实战项目,详细讲解如何使用TensorFlow和Bidirectional LSTM进行股票价格预测。涵盖从数据加载到预测结果可视化的完整流程,适合新手学习,提供简单易懂的代码示例和解释。
时间序列实战:股票价格预测(LSTM)
本章节将带你从零开始,使用TensorFlow和Long Short-Term Memory(LSTM)网络进行股票价格预测的实战项目。我们将重点介绍双向LSTM(Bidirectional LSTM),它能够更好地捕捉时间序列中的前后依赖关系。内容针对TensorFlow新手设计,力求简单易懂,通过代码示例和分步讲解,让你掌握整个流程。
引言
股票价格预测是一个经典的时间序列分析问题,机器学习方法如LSTM因其处理序列数据的能力而广受欢迎。LSTM通过记忆单元能够有效捕获长期依赖关系,而双向LSTM则结合前向和后向信息,进一步提升模型性能。本章将实战演练如何利用TensorFlow构建这样的模型。
项目需求与数据加载
项目需求
我们的目标是基于历史股票价格数据,构建一个预测未来价格的模型。我们将使用Python和TensorFlow库,数据处理依赖Pandas,可视化使用Matplotlib。
数据加载(使用Pandas)
假设我们有一个CSV文件stock_prices.csv,包含日期和收盘价等列。首先安装必要库:pip install tensorflow pandas matplotlib。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 加载数据
data = pd.read_csv('stock_prices.csv')
# 假设数据列:Date (日期), Close (收盘价)
data['Date'] = pd.to_datetime(data['Date']) # 转换日期格式
data.set_index('Date', inplace=True) # 设置日期为索引
close_prices = data['Close'].values.reshape(-1, 1) # 提取收盘价并重塑
print(close_prices.shape) # 查看数据形状
这里,我们使用Pandas加载CSV文件,提取收盘价列并将其转换为NumPy数组,便于后续处理。
时间序列预处理
归一化
时间序列数据通常需要归一化,以避免不同尺度影响模型训练。我们使用MinMaxScaler将数据缩放到0到1之间。
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(close_prices)
print("归一化后数据:", scaled_data[:5]) # 显示前几个值
归一化后,数据更稳定,有助于模型快速收敛。
滑动窗口构建样本
LSTM需要序列输入,我们将数据划分为多个滑动窗口样本。每个窗口包含多个时间步的数据作为输入,下个时间步的值作为标签。
def create_dataset(data, time_steps=60):
"""
创建滑动窗口样本
data: 归一化后的数据
time_steps: 时间步数,即每个样本的长度
"""
X, y = [], []
for i in range(len(data) - time_steps):
X.append(data[i:i+time_steps, 0])
y.append(data[i+time_steps, 0])
return np.array(X), np.array(y)
# 设置时间步数为60天
X, y = create_dataset(scaled_data, time_steps=60)
print("样本数:", X.shape)
print("标签数:", y.shape)
这里,每个样本是前60天的收盘价序列,标签是第61天的收盘价。
LSTM 模型构建
LSTM简介
LSTM是循环神经网络(RNN)的一种变体,通过门控机制控制信息流,适合处理长序列。双向LSTM结合两个方向的LSTM层,可以同时考虑过去和未来的信息。
构建Bidirectional LSTM模型
使用TensorFlow Keras API构建模型。我们将使用一个Bidirectional LSTM层,后接一个密集层进行预测。
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Bidirectional, LSTM, Dense
# 重塑输入数据以适应LSTM
# X的形状应为 (样本数, 时间步数, 特征数),特征数为1(收盘价)
X_reshaped = X.reshape(X.shape[0], X.shape[1], 1)
# 划分训练集和测试集(例如,80% 训练,20% 测试)
train_size = int(len(X) * 0.8)
X_train, X_test = X_reshaped[:train_size], X_reshaped[train_size:]
y_train, y_test = y[:train_size], y[train_size:]
# 构建模型
model = Sequential([
Bidirectional(LSTM(units=50, return_sequences=False, input_shape=(X_train.shape[1], 1))),
Dense(units=1) # 输出层,预测单个值
])
# 编译模型
model.compile(optimizer='adam', loss='mean_squared_error') # 使用Adam优化器和均方误差损失
print(model.summary()) # 显示模型结构
这个模型使用一个双向LSTM层,包含50个神经元,输入形状为(时间步数, 特征数)。
模型训练与预测
训练模型
训练模型以最小化损失,这里我们训练10个epoch,并监控验证损失。
# 训练模型
history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_split=0.2, verbose=1)
# 绘制训练损失
plt.plot(history.history['loss'], label='训练损失')
plt.plot(history.history['val_loss'], label='验证损失')
plt.xlabel('Epoch')
plt.ylabel('损失')
plt.legend()
plt.title('模型训练损失曲线')
plt.show()
训练后,损失应该逐渐下降,表明模型在学习。
单步预测与多步预测
单步预测指预测下一个时间步的值,多步预测则连续预测多个未来值。
- 单步预测:直接使用测试集进行预测。
# 单步预测
y_pred = model.predict(X_test)
# 反归一化,将预测值转换回原尺度
y_pred_inv = scaler.inverse_transform(y_pred.reshape(-1, 1))
y_test_inv = scaler.inverse_transform(y_test.reshape(-1, 1))
print("单步预测前几个值:", y_pred_inv[:5])
- 多步预测:递归使用预测值作为输入,预测未来多个步骤。
# 多步预测示例:预测未来30天
def multi_step_predict(initial_input, steps=30, model=model, scaler=scaler):
"""
initial_input: 初始输入序列,形状 (1, 时间步数, 1)
steps: 预测步数
"""
predictions = []
current_input = initial_input.copy()
for _ in range(steps):
pred = model.predict(current_input)
predictions.append(pred[0, 0])
# 更新输入,移除最早值,添加预测值
current_input = np.roll(current_input, -1, axis=1)
current_input[0, -1, 0] = pred[0, 0]
predictions = np.array(predictions).reshape(-1, 1)
return scaler.inverse_transform(predictions)
# 示例:从测试集最后一个样本开始预测
initial_seq = X_test[-1].reshape(1, 60, 1)
future_predictions = multi_step_predict(initial_seq, steps=30)
print("多步预测结果形状:", future_predictions.shape)
多步预测需要注意误差累积问题。
预测结果可视化与分析
可视化
可视化真实值与预测值,直观比较模型性能。
# 单步预测可视化
plt.figure(figsize=(12, 6))
plt.plot(y_test_inv, label='真实值', color='blue')
plt.plot(y_pred_inv, label='单步预测', color='red', linestyle='--')
plt.xlabel('时间步')
plt.ylabel('收盘价')
plt.title('股票价格预测:真实 vs 单步预测')
plt.legend()
plt.show()
# 多步预测可视化(仅作示例,需结合实际情况)
plt.figure(figsize=(12, 6))
plt.plot(range(len(y_test_inv)), y_test_inv, label='真实值', color='blue')
plt.plot(range(len(y_test_inv), len(y_test_inv) + 30), future_predictions, label='多步预测', color='green', linestyle=':')
plt.xlabel('时间步')
plt.ylabel('收盘价')
plt.title('股票价格多步预测示例')
plt.legend()
plt.show()
性能分析
评估模型性能,如计算均方误差(MSE)或平均绝对误差(MAE)。
from sklearn.metrics import mean_squared_error, mean_absolute_error
# 计算单步预测误差
mse = mean_squared_error(y_test_inv, y_pred_inv)
mae = mean_absolute_error(y_test_inv, y_pred_inv)
print(f"单步预测均方误差 (MSE): {mse:.4f}")
print(f"单步预测平均绝对误差 (MAE): {mae:.4f}")
较低的误差值表示模型预测较准确。
总结
本章通过股票价格预测的实战项目,让你掌握了时间序列数据的预处理、Bidirectional LSTM模型构建、训练和预测流程。关键点包括滑动窗口构建、归一化、双向LSTM的优势,以及单步与多步预测的区别。在实际应用中,你可以调整模型参数或尝试其他网络结构以优化性能。