资讯详情

资讯详情

LSTM股票预测实战:从数据到推理的Python全链路项目

简介这份资源面向具备一定Python与深度学习基础、希望上手金融时间序列预测的学习者与开发者围绕长短期记忆网络LSTM构建股票价格预测模型解决传统RNN在长序列中梯度消失、难以捕获长期依赖的问题。压缩包共12个文件约959KB包含3个py脚本与2个pyc编译文件用于模型训练和预测2个csv提供上证综合指数及单支股票的历史行情数据另有checkpoint、meta、data与index等TensorFlow权重文件可直接加载已训练模型并附docx说明文档。内容覆盖数据获取、清洗、标准化与训练测试集划分LSTM层结合Dense、Dropout的架构设计以及损失函数、优化器选择与模型评估预测的完整流程。目前已有22363人学习下载适合作为课程设计、毕业项目或量化入门实践参考帮助读者理解门控机制原理并掌握用Python实现序列预测的排错与调参思路。1. 用 LSTM 做股票预测这个 Python 项目把数据到推理的链路全打通了很多人第一次接触「人工智能 python」就是从股价预测开始的但真正动手时才发现难点从来不是调一个 LSTM 层而是把行情数据抓取、缺失值处理、时间窗切分、模型训练、结果可视化这一整条链路串起来。这个基于 LSTM 的股票预测项目恰好把这条链路完整落地了输入一段历史收盘价序列输出未来若干天的预测走势并附带训练曲线和预测对比图。它适合两类人——刚学完 LSTM 理论想找个完整案例练手的 Python 开发者以及需要快速搭一个时序预测基线、再往上叠特征工程的算法工程师。项目不依赖冷门库核心就是 numpy、pandas、TensorFlow/Keras 加 matplotlib拿到源码后半小时内能跑出第一张预测图。2. 项目结构与技术选型为什么是 LSTM 而不是 ARIMA2.1 目录组织与模块职责这个项目的目录结构是典型的「脚本式」组织没有过度工程化对新手友好也方便二次开发时快速定位。常见做法是拆成数据、模型、训练、可视化四块stock_lstm/ ├── data/ │ ├── raw/ # 原始行情 csv按股票代码命名 │ └── processed/ # 归一化、切窗后的 npy 文件 ├── src/ │ ├── config.py # 超参数、路径、窗口大小集中管理 │ ├── data_loader.py # 读取 csv、缺失值处理、归一化 │ ├── dataset.py # 滑动窗口切分、训练/测试集划分 │ ├── model.py # LSTM 网络定义 │ ├── train.py # 训练循环、回调、模型保存 │ └── predict.py # 加载模型、反归一化、输出预测 ├── outputs/ │ ├── models/ # 保存的 .h5 或 .keras 权重 │ └── figures/ # 损失曲线、预测对比图 ├── requirements.txt └── main.py # 一键跑通入口把超参数抽到config.py是我强烈建议保留的习惯。股票预测里窗口大小、预测天数、学习率这几个参数改动频率极高散落在各个脚本里改一次要翻五个文件血泪经验。集中管理后换一只股票、换一个预测周期只动一个地方。2.2 为什么选 LSTM 而不是传统时序模型ARIMA 这类统计模型对线性、平稳序列友好但股票收盘价有明显的非线性、长依赖和波动聚集特征ARIMA 很难捕捉。LSTM 的门控机制能选择性记忆长期信息天然适合这种场景。项目里用的是单层或双层 LSTM 接一个全连接输出层结构不复杂但足够作为基线。技术选型上深度学习框架用 TensorFlow/Keras 而非 PyTorch原因是 Keras 的SequentialAPI 定义这种简单时序网络代码量最少新手读起来没有负担。数据处理用 pandas 做时间索引对齐numpy 做张量运算可视化用 matplotlib。这套组合在「人工智能 python」生态里是最通用的几乎不存在环境兼容的玄学问题。2.3 数据管线的关键设计数据管线是整个项目最容易被低估的部分。股票数据常见的问题是停牌导致的缺失、除权除息造成的价格跳变、以及不同股票价格量级差异巨大。项目在data_loader.py里做了三件事按日期排序、前向填充缺失值、用 Min-Max 归一化把价格压到 0 到 1 区间。# src/data_loader.py import pandas as pd import numpy as np def load_and_clean(csv_path, price_colclose): # 读取行情解析日期列并设为索引 df pd.read_csv(csv_path, parse_dates[date]) df df.sort_values(date).reset_index(dropTrue) # 停牌日缺失用前值填充避免插值引入未来信息 df[price_col] df[price_col].ffill() # 丢弃仍然为空的行通常是开头 df df.dropna(subset[price_col]) return df def minmax_scale(series): # 只对训练段拟合 scaler 是更严谨的做法这里为演示简化 lo, hi series.min(), series.max() scaled (series - lo) / (hi - lo 1e-8) return scaled, lo, hi这里有个关键点归一化的lo和hi必须保存下来预测阶段要用它们把模型输出反归一化回真实价格。很多新手跑完模型发现预测值全是 0 到 1 之间的小数就是忘了这一步。另外严格来说 scaler 只应该在训练集上拟合再应用到测试集否则会有数据泄漏项目里为了代码简洁做了简化二次开发时建议修正。3. 核心模块拆解滑动窗口、LSTM 网络与训练循环3.1 滑动窗口切分把序列变成监督学习样本LSTM 的输入是三维张量(样本数, 时间步, 特征数)而原始数据只是一维价格序列。dataset.py的核心任务就是用滑动窗口把一维序列切成一个个「过去 N 天预测未来 M 天」的样本对。# src/dataset.py import numpy as np def make_windows(series, window60, horizon1): X, y [], [] for i in range(len(series) - window - horizon 1): # 取连续 window 天作为输入特征 X.append(series[i:i window]) # 取窗口之后 horizon 天的价格作为标签 y.append(series[i window horizon - 1]) X np.array(X).reshape(-1, window, 1) # 增加特征维度 y np.array(y) return X, y def train_test_split_ts(X, y, ratio0.8): # 时序数据必须按时间顺序切不能随机打乱 split int(len(X) * ratio) return X[:split], y[:split], X[split:], y[split:]window60表示用过去 60 个交易日预测horizon1表示预测下一天。这两个参数直接决定模型难度窗口太短捕捉不到趋势太长则样本数骤减且容易过拟合。我一般会从 30 和 60 各跑一遍对比。reshape(-1, window, 1)里的 1 是特征数如果后续要加入成交量、换手率等多特征这里改成对应维度即可这是二次开发最常见的扩展点。时序切分绝对不能随机打乱这是新手最容易翻车的地方。一旦 shuffle测试集里混入了未来信息评估指标会好得离谱上线就崩。3.2 LSTM 网络定义与参数含义模型定义在model.py结构是「LSTM 层 → Dropout → 全连接」。Dropout 是抑制过拟合的关键股票数据噪声大不加 Dropout 训练集损失会一路下降而验证集反弹。# src/model.py from tensorflow.keras import layers, models def build_lstm(window60, units64, dropout0.2): model models.Sequential([ # 第一层 LSTMreturn_sequencesFalse 只输出最后时间步 layers.LSTM(units, input_shape(window, 1), return_sequencesFalse), layers.Dropout(dropout), # 输出单个预测值 layers.Dense(1) ]) model.compile(optimizeradam, lossmse, metrics[mae]) return modelunits64是隐藏状态维度太小欠拟合太大显存吃紧且过拟合。return_sequencesFalse表示只取最后一个时间步的输出送入全连接如果要做多步预测或堆叠多层 LSTM这里要改成True。损失函数用 MSE 是因为回归任务评估指标加 MAE 是为了让误差有价格量纲上的直观感受。优化器 Adam 默认学习率 0.001通常够用如果损失震荡可以降到 0.0005。3.3 训练循环与回调配置train.py负责把数据、模型、回调串起来。回调里最关键的是EarlyStopping和ModelCheckpoint前者防止无效训练后者保证保存的是验证集最优权重而不是最后一轮。# src/train.py from tensorflow.keras import callbacks from src.model import build_lstm def train_model(X_train, y_train, X_val, y_val, window, epochs100): model build_lstm(windowwindow) cbs [ # 验证损失 10 轮不降就停并恢复最优权重 callbacks.EarlyStopping(patience10, restore_best_weightsTrue), # 只保存验证损失最低的模型 callbacks.ModelCheckpoint( outputs/models/best.keras, save_best_onlyTrue), # 损失平台期自动降学习率 callbacks.ReduceLROnPlateau(factor0.5, patience5) ] history model.fit( X_train, y_train, validation_data(X_val, y_val), epochsepochs, batch_size32, callbackscbs, verbose1) return model, historypatience10配合restore_best_weightsTrue是标配避免最后几轮过拟合把好权重覆盖掉。batch_size32是时序任务里比较稳的默认值样本量小可以降到 16。ReduceLROnPlateau在损失卡住时把学习率减半往往能让模型再往下走一段。训练完history里存着每轮的 loss 和 mae直接喂给 matplotlib 就能画出损失曲线判断是否过拟合一目了然。4. 从零跑通环境、数据与一键执行4.1 环境准备与依赖安装项目依赖不多建议用虚拟环境隔离。Python 版本选 3.9 到 3.11 之间TensorFlow 对这几个版本支持最稳。# 创建并激活虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖 pip install numpy pandas matplotlib tensorflow scikit-learn如果机器没有独立显卡TensorFlow 会自动走 CPU训练速度慢一些但完全能跑。requirements.txt里建议锁版本比如tensorflow2.15.0避免不同机器上 Keras API 行为不一致。这一步最常见的坑是 numpy 版本和 TensorFlow 不匹配报np.object之类的错锁版本能省很多事。4.2 数据准备csv 格式约定项目默认读取data/raw/下的 csv至少包含date和close两列。日期格式用YYYY-MM-DD收盘价是浮点数。如果你手头的数据列名不同改data_loader.py里的price_col参数即可。数据量建议至少 500 个交易日否则切完窗口后训练样本太少模型学不到东西。提示不同股票价格量级差异大务必每只股票单独归一化不要用全市场统一 scaler。4.3 一键执行与结果查看main.py把加载、切分、训练、预测、画图串成一条流水线直接运行即可。python main.py --csv data/raw/demo.csv --window 60 --horizon 1 --epochs 100跑完后outputs/figures/下会生成两张图loss_curve.png展示训练和验证损失随轮次的变化prediction.png把测试集真实价格和预测价格叠在一起。判断模型好坏先看预测图——如果预测曲线整体滞后真实曲线一天说明模型在「抄昨天的答案」需要调整窗口或加入更多特征。命令行参数都对应config.py里的默认值临时实验直接传参覆盖不用改代码。5. 避坑与常见问题排查5.1 预测值全是 0 到 1 之间的小数现象画出来的预测曲线是一条贴着底部的直线。原因忘了反归一化模型输出的是归一化空间的值。解决在predict.py里用训练时保存的lo和hi做逆变换real pred * (hi - lo) lo。5.2 验证损失远高于训练损失现象训练 loss 降到 0.001验证 loss 停在 0.01 下不去。原因过拟合模型把训练集的噪声也记住了。解决加大 Dropout 到 0.3 到 0.4减小 LSTM units或者增加训练数据量。股票数据本身信噪比低验证损失比训练高是常态但差距过大就要处理。5.3 损失曲线剧烈震荡不收敛现象loss 上下跳动没有下降趋势。原因学习率过大或 batch_size 太小。解决把学习率从 0.001 降到 0.0005batch_size 提到 64或者加ReduceLROnPlateau回调让它自动降。5.4 换了新股票后预测完全失效现象在 A 股票上表现不错换 B 股票预测离谱。原因不同股票波动特性差异大超参数没有重新调。解决每换一只股票重新跑一遍窗口大小和学习率的网格搜索别指望一套参数通吃。5.5 训练速度慢到无法忍受现象一个 epoch 要几分钟。原因CPU 训练加上窗口切分用了 Python 循环。解决确认 TensorFlow 是否识别到 GPU把make_windows里的循环用 numpy 的sliding_window_view重写速度能提升一个量级。6. 二次开发多特征输入与多步预测改造跑通基线之后真正有价值的是往上叠东西。这个项目最值得改造的两个方向是多特征输入和多步预测下面说具体怎么动。多特征输入的核心是改dataset.py的切窗逻辑和model.py的input_shape。假设你要加入成交量和换手率先把它们和收盘价一起归一化然后让每个时间步的特征数从 1 变成 3# 多特征版本features 是 (T, 3) 的数组 def make_windows_multi(features, window60, horizon1): X, y [], [] for i in range(len(features) - window - horizon 1): X.append(features[i:i window]) # 形状 (window, 3) y.append(features[i window horizon - 1, 0]) # 只预测收盘价 return np.array(X), np.array(y) # model.py 里 input_shape 改成 (window, 3) layers.LSTM(units, input_shape(window, 3), return_sequencesFalse)注意标签仍然只取收盘价那一列因为你要预测的是价格其他特征只是辅助输入。这一步改完模型能利用量价关系通常比单特征稳。多步预测则是把horizon从 1 改成 5 或 10同时把输出层改成Dense(horizon)标签也要相应变成未来 horizon 天的价格序列。这里有个策略选择直接多输出一次预测多天还是滚动预测预测一天把结果喂回去再预测下一天。直接多输出训练稳定但精度随步数衰减快滚动预测精度好但误差会累积。我一般先用直接多输出跑基线再对比滚动预测。验证改造是否有效别只看 loss要看方向准确率——预测涨跌方向和真实方向一致的比例。价格预测的绝对误差往往很大但方向对了才有交易价值。可以在predict.py里加一段统计# 计算方向准确率 direction_acc np.mean( np.sign(np.diff(y_true)) np.sign(np.diff(y_pred))) print(f方向准确率: {direction_acc:.2%})这个指标比 MSE 更能反映模型有没有实际用处。如果方向准确率长期在 50% 附近说明模型没学到东西得回去检查特征和窗口。最后提醒一句股票预测模型最容易自欺欺人的地方就是拿测试集反复调参调到指标好看为止。我现在的习惯是留一段完全没碰过的数据做最终验证训练和调参全程不碰它只在最后跑一次。从那以后我每次改完模型都强制走一遍这个流程指标难看但真实比好看但虚的强。希望这个项目能帮你把 LSTM 时序预测的整条链路真正跑通剩下的就靠你在特征工程上慢慢磨了。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →