TensorFlow 中文手册

23.3 时间序列实战:股票价格预测(LSTM)

时间序列实战:使用TensorFlow和Bidirectional LSTM进行股票价格预测

TensorFlow 中文手册

本章节通过实战项目,详细讲解如何使用TensorFlow和Bidirectional LSTM进行股票价格预测。涵盖从数据加载到预测结果可视化的完整流程,适合新手学习,提供简单易懂的代码示例和解释。

推荐工具
PyCharm专业版开发必备

功能强大的Python IDE,提供智能代码补全、代码分析、调试和测试工具,提高Python开发效率。特别适合处理列表等数据结构的开发工作。

了解更多

时间序列实战:股票价格预测(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的优势,以及单步与多步预测的区别。在实际应用中,你可以调整模型参数或尝试其他网络结构以优化性能。

开发工具推荐
Python开发者工具包

包含虚拟环境管理、代码格式化、依赖管理、测试框架等Python开发全流程工具,提高开发效率。特别适合处理复杂数据结构和算法。

获取工具包