☰
LSTM股市预测实战:从源码到调参的完整工程指南
2026/10/7 13:09:11 网站建设 项目流程

简介:这份资源面向金融量化初学者与深度学习爱好者,提供一套基于LSTM的股票价格预测完整实现,帮助理解循环神经网络在时间序列上的建模思路。压缩包共19个文件,约3.92MB,以9个Python脚本为核心,覆盖数据预处理、模型训练、参数选择、评估与绘图等环节,另含2个CSV与1个Excel数据集、2个H5训练模型、2张结果对比图及说明文档,结构清晰便于按模块复现。已有517人学习下载。读者可据此掌握从历史行情加载、归一化与序列化,到Keras搭建LSTM、设置批大小与优化器、用MSE与MAE评估,再到预测未来价格并绘制实际与预测对比曲线的完整流程,同时接触移动平均、指数平滑等技术指标与模型融合思路,是深度学习落地金融预测的实用案例。

1. 从一份能跑通的 LSTM 股市预测源码说起

很多人第一次接触 LSTM 时间序列预测,都是被"用深度学习预测股价"这个说法吸引进来的,但真正动手时才发现,网上大部分代码要么缺数据集,要么训练脚本和预测脚本对不上,跑起来一堆路径报错。这份lstm_stock-master资源算是少见的"全套齐活":源码、训练好的.h5模型、沪深300 和单只基金的 CSV 数据、参数配置文件、可视化脚本都在一个包里,run.py一条命令就能把训练到出图的链路走完。它解决的不是"教你什么是 LSTM"这种科普问题,而是"给你一套能复现、能改参数、能换自己数据的工程骨架"。适合两类人:一是刚学完 LSTM 理论、想找个完整项目练手的新手;二是做量化或金融数据分析、想快速验证 LSTM 在收益率序列上表现的从业者。下面我按拆包顺序,把这份资源的结构、跑法、参数和坑逐个讲清楚。

2. 拆开压缩包:目录结构与数据流走向

2.1 文件清单与各自职责

拿到lstm_stock-master.zip后先别急着解压运行,花两分钟把目录结构看明白,后面调参和排错会省很多事。这份资源的文件大致分四类:数据文件、模型文件、脚本文件、配置与依赖文件。

文件/目录类型作用
data/hs300.csv数据沪深300 指数历史行情,训练主数据
data/001632.csv数据单只基金净值/行情数据,用于换标的验证
hs300.h5/001632.h5模型已训练好的 LSTM 权重文件,可直接加载预测
hs300.png/001632.png输出预测对比图,实际值与预测值曲线
run.py脚本主入口,串联训练、评估、绘图流程
get_data/get_jz.py脚本数据获取,抓取基金净值
get_data/choose_fund.py脚本基金筛选逻辑
model/lstm_train.py脚本模型构建与训练
model/lstm_predict.py脚本加载模型做预测
model/model_evalute.py脚本评估指标计算(MSE/MAE/RMSE)
model/lstm_choose_parameter.py脚本参数搜索/网格调参
model/data_preprocess.py脚本数据清洗、归一化、序列化
model/plot_graph.py脚本绘图
parameter.xlsx配置超参数表,改这里比改代码方便
requirements.txt依赖Python 包版本清单

从数据流看,整条链路是:get_data抓数 →data_preprocess清洗归一化 →lstm_train训练并保存.h5→model_evalute算指标 →lstm_predict预测 →plot_graph出图。run.py把这几个环节串起来,所以理解run.py的调用顺序,等于理解了整个项目。

2.2 环境准备与依赖安装

这份代码基于 Keras + TensorFlow 后端,属于比较经典的写法。建议单独建虚拟环境,避免和你机器上已有的 TensorFlow 版本打架。

# 建虚拟环境,Python 3.8~3.10 兼容性最好 python -m venv lstm_env # 激活(Windows) lstm_env\Scripts\activate # 激活(macOS/Linux) source lstm_env/bin/activate # 安装依赖 pip install -r requirements.txt

requirements.txt里通常锁定了tensorflow、keras、pandas、numpy、matplotlib、scikit-learn、openpyxl这几个包。这里有个血泪经验:TensorFlow 2.x 和旧版 Keras 的 API 有差异,如果lstm_train.py里用的是from keras.models import Sequential这种独立 Keras 写法,而你装的是 TF 2.10 以上,可能会报ImportError。常见做法是统一改成from tensorflow.keras.models import Sequential,或者把 TF 版本降到 2.8 左右。装完先跑一句python -c "import tensorflow as tf; print(tf.__version__)"确认版本,再往下走。

2.3 数据格式与预处理逻辑

data_preprocess.py是整个项目里最值得细看的一段,因为 LSTM 预测效果好不好,七成看预处理。这份资源的数据是日频行情,字段一般包含日期、开盘、收盘、最高、最低、成交量。预处理做三件事:缺失值处理、归一化、滑窗序列化。

import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler # 1. 读取数据,parse_dates 把日期列转成时间索引 df = pd.read_csv('data/hs300.csv', parse_dates=['date']) df = df.sort_values('date').reset_index(drop=True) # 2. 缺失值:行情数据一般用前向填充,别用均值填充 df = df.fillna(method='ffill').dropna() # 3. 归一化:MinMax 把价格压到 [0,1],LSTM 对量纲敏感 scaler = MinMaxScaler(feature_range=(0, 1)) scaled = scaler.fit_transform(df[['close']].values) # 4. 滑窗:用过去 look_back 天预测下一天 def create_dataset(data, look_back=60): x, y = [], [] for i in range(len(data) - look_back): x.append(data[i:i + look_back, 0]) y.append(data[i + look_back, 0]) return np.array(x), np.array(y) x, y = create_dataset(scaled, look_back=60) # LSTM 输入要求三维:[样本数, 时间步, 特征数] x = np.reshape(x, (x.shape[0], x.shape[1], 1))

逻辑说明:look_back=60表示用 60 个交易日(约三个月)的历史收盘价预测下一天,这个值直接决定输入张量的时间步维度。归一化必须用fit_transform在训练集上拟合,预测时要复用同一个scaler做inverse_transform,否则预测出来的价格量纲是错的——这是新手最容易翻车的地方。reshape那一步不能省,Keras 的 LSTM 层只接受三维输入,二维会直接报维度错误。参数上,feature_range一般保持(0,1),如果你发现预测曲线整体偏移,先检查是不是归一化和反归一化用了两个不同的 scaler 实例。

3. 训练、评估与预测:把 run.py 跑通

3.1 模型结构与超参数配置

lstm_train.py里搭的是一个典型的单层或双层 LSTM 结构,配合 Dropout 防过拟合,最后接 Dense 输出一个标量。parameter.xlsx里放的就是这些超参数,改表比改代码安全。

from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout model = Sequential() # 第一层 LSTM,units 是隐藏单元数,input_shape 对应 (时间步, 特征数) model.add(LSTM(units=50, return_sequences=True, input_shape=(x.shape[1], 1))) model.add(Dropout(0.2)) # 第二层 LSTM,return_sequences=False 表示只输出最后一步 model.add(LSTM(units=50, return_sequences=False)) model.add(Dropout(0.2)) # 全连接输出预测值 model.add(Dense(units=1)) model.compile(optimizer='adam', loss='mean_squared_error') model.fit(x, y, epochs=50, batch_size=32, validation_split=0.1) model.save('hs300.h5')

参数说明:units=50是隐藏层维度,太小欠拟合、太大过拟合且训练慢,50~128 是常见区间;return_sequences=True只在还有下一层 LSTM 时才需要,最后一层 LSTM 必须设 False,否则维度对不上;Dropout(0.2)随机丢弃 20% 神经元,金融序列噪声大,这个值别超过 0.3;epochs=50、batch_size=32是保守配置,validation_split=0.1留 10% 做验证。optimizer='adam'基本是默认选择,学习率不用手动设。训练完model.save('hs300.h5')保存的是结构和权重,后面lstm_predict.py直接load_model就能用。

3.2 评估指标与预测出图

model_evalute.py算的是回归任务的标准三件套:MSE、RMSE、MAE。这三个指标都建立在反归一化之后的真实价格尺度上,如果直接在归一化数据上算,数值会小得离谱,没有参考意义。

from sklearn.metrics import mean_squared_error, mean_absolute_error import numpy as np # 预测并反归一化 pred = model.predict(x_test) pred = scaler.inverse_transform(pred) # 关键:反归一化 true = scaler.inverse_transform(y_test.reshape(-1, 1)) mse = mean_squared_error(true, pred) rmse = np.sqrt(mse) mae = mean_absolute_error(true, pred) print(f'MSE={mse:.4f}, RMSE={rmse:.4f}, MAE={mae:.4f}')

逻辑说明:inverse_transform必须用训练阶段那个 scaler,不能重新 fit。RMSE 和 MAE 的单位和股价一致,看的时候直接和股价波动幅度对比——如果 RMSE 是 50,而股价日均波动才 20,说明模型基本没学到东西。plot_graph.py用 matplotlib 把true和pred两条曲线画在一张图上,hs300.png就是这么来的。看图的技巧:别只看整体趋势吻合,重点看拐点处预测是否滞后,LSTM 在趋势反转点普遍滞后 1~2 天,这是模型特性不是 bug。

3.3 换自己的数据跑一遍

想验证这套代码能不能用在你手头的标的上,最直接的办法是换 CSV。步骤是:准备一份带date和close两列的 CSV,放到data/下,改run.py或data_preprocess.py里的文件路径,重新跑训练。

# 假设你把新数据存成 data/my_stock.csv # 修改 data_preprocess.py 中的读取路径后执行 python run.py

注意几点:新数据的日期要连续、按升序排列,中间停牌造成的空缺用前向填充补上;样本量至少 500 个交易日以上,否则 LSTM 参数根本训不起来;如果你的标的价格量级和沪深300 差很多(比如几块钱的股票 vs 几千点的指数),归一化会自动处理,不用手动缩放。跑完对比my_stock.png和hs300.png,如果新标的的 RMSE 明显更大,多半是数据噪声或样本太短,不是代码问题。

4. 避坑与常见问题排查

4.1 预测曲线是一条直线

现象:出图后预测值几乎不动,像一条水平线。原因:归一化后模型输出趋近均值,或者学习率/训练轮数不够,模型没收敛。解决:先确认epochs是否够(至少 50),再看 loss 曲线是否还在下降;如果 loss 早早平了,把units调大或加一层 LSTM;还有一种情况是look_back太小(比如设成 5),模型看不到足够历史,改成 30~60 再试。

4.2 反归一化后数值离谱

现象:预测价格是几万或负数,和真实股价完全对不上。原因:预测时用了新的MinMaxScaler实例,或者inverse_transform的输入形状不对。解决:确保训练和预测共用同一个 scaler 对象,最稳妥的做法是把 scaler 用joblib.dump存下来,预测时load回来;inverse_transform要求输入是二维(n,1),一维数组要先reshape(-1,1)。

4.3 加载 .h5 模型报错

现象:load_model('hs300.h5')抛ValueError或Unknown layer。原因:保存模型和加载模型的 Keras/TF 版本不一致,或者自定义层没注册。解决:训练和预测用同一个虚拟环境;如果跨版本,重新训练保存一次比折腾兼容性更快。这份资源里的.h5是配套的,直接用同环境加载一般没问题。

4.4 中文路径或编码报错

现象:读 CSV 时报UnicodeDecodeError。原因:Windows 下 CSV 可能是 GBK 编码,而 pandas 默认 UTF-8。解决:pd.read_csv(path, encoding='gbk'),或者用编辑器把文件另存为 UTF-8。路径里尽量别带中文和空格,这是省事的做法。

4.5 训练 loss 不下降

现象:跑了几十个 epoch,loss 一直在高位震荡。原因:数据没归一化、学习率过大、或者输入特征本身没有可学习模式。解决:先确认scaled数据在 [0,1] 区间;把optimizer换成Adam(learning_rate=0.001)显式指定;如果换了几组参数都不行,大概率是这个标的的价格序列本身接近随机游走,LSTM 学不到东西,这时候该接受现实而不是继续调参。

5. 进阶:用 parameter.xlsx 做网格调参

把项目跑通只是第一步,真正拉开差距的是调参。这份资源里lstm_choose_parameter.py和parameter.xlsx就是为这个准备的。我的习惯是把关键超参数列成一张表,用循环批量跑,记录每组参数对应的 RMSE,最后挑最优组合。下面是一个可复用的网格搜索骨架。

import pandas as pd from itertools import product # 定义搜索空间 look_backs = [30, 60, 90] units_list = [50, 100] epochs_list = [50, 100] results = [] for lb, units, ep in product(look_backs, units_list, epochs_list): x, y = create_dataset(scaled, look_back=lb) x = np.reshape(x, (x.shape[0], x.shape[1], 1)) model = build_lstm(units) # 封装好的建模型函数 model.fit(x, y, epochs=ep, batch_size=32, verbose=0) pred = model.predict(x) pred = scaler.inverse_transform(pred) true = scaler.inverse_transform(y.reshape(-1, 1)) rmse = np.sqrt(mean_squared_error(true, pred)) results.append({'look_back': lb, 'units': units, 'epochs': ep, 'rmse': rmse}) df = pd.DataFrame(results).sort_values('rmse') df.to_excel('parameter.xlsx', index=False) print(df.head())

逻辑说明:product做笛卡尔积,把三组参数的所有组合跑一遍;verbose=0关掉每轮输出,不然日志刷屏;结果写回parameter.xlsx并按 RMSE 升序排,第一行就是当前搜索空间里的最优组合。参数选择上,look_back影响最大,它决定模型能看多长的历史,金融序列一般 20~60 比较合理,太长会引入过多噪声;units和epochs次之。要注意的是,网格搜索出来的最优 RMSE 是在训练集上算的,有过拟合风险,严谨做法是留一段样本外数据做最终验证——我一般会把最后 20% 的数据完全隔离,调参全程不碰,最后只用它跑一次。

还有个容易被忽略的点:股票预测里单看 RMSE 会骗人。如果模型永远预测"明天等于今天",在平稳行情下 RMSE 也会很低,但毫无交易价值。所以除了 RMSE,我还会看预测值和真实值的涨跌方向一致率,这个指标更接近实战。从那以后我每次调完参,都强制把方向一致率也打出来,光看误差指标就下结论,翻车过不止一次。希望这份拆解能帮你少走点弯路,把这份资源真正用起来。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询