尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

LSTM股票预测实战:Keras源码与数据集全流程

发布时间:2026/9/28 17:24:52

资讯中心
01
ARTICLE

LSTM股票预测实战:Keras源码与数据集全流程

LSTM股票预测实战:Keras源码与数据集全流程
简介这份资源围绕LSTM在股票市场的应用展开面向对量化交易与深度学习感兴趣的学生及实验者帮助其理解如何把原始行情数据转换为时间序列样本并完成多变量收益预测的建模流程。包内共4个文件以2个zip数据压缩包、1个py源码和1个docx说明文档为主整体约3.87MB其中源码以600000.SH为基准回测期覆盖2016年3月至2017年12月另附20支股票数据与模型损失、RMSE计算表。已有4800人学习下载。读者可据此掌握数据准备、LSTM建模、预测结果还原到原始量纲的完整思路并借助损失与误差数据评估模型表现适合作为课程实验或量化策略入门的参考案例。1. 用 LSTM 做股票预测从 Keras 源码到数据集一套能跑通的方案很多人第一次接触时序预测都是从股票数据开始的。打开行情软件看到一条条 K 线心里想的是这玩意儿到底能不能用 LSTM 预测答案不是简单的能或不能而是取决于你把问题定义成什么。如果你想让模型告诉你明天精确的收盘价那大概率会失望但如果你想让模型学习一段历史窗口内的价格形态输出未来若干天的涨跌方向或价格区间LSTM 配合 Keras 是完全可以落地的。这篇文章不讲虚的直接围绕 LSTM 股票数据预测的源代码和数据集展开把数据怎么来、模型怎么搭、参数怎么调、坑在哪里一步步拆开讲清楚。适合已经会一点 Python、想拿真实数据跑通一个完整时序预测项目的人也适合做过其他深度学习任务、但还没碰过金融时序的工程师。2. 股票数据集的获取与预处理别急着往 LSTM 里塞原始价格2.1 数据集从哪来以及为什么不能直接用收盘价做 LSTM 股票预测第一步不是写模型而是把数据搞对。常见的数据集来源有几类一是用 yfinance、tushare 这类接口拉取公开行情数据二是用 Kaggle 上现成的股票历史数据集三是券商或数据商提供的日频/分钟频数据。不管哪种拿到手的数据通常包含日期、开盘价、最高价、最低价、收盘价、成交量这几个字段。很多人直接把收盘价一列丢进 LSTM结果模型训练 loss 降得很快但预测出来就是一条直线或者永远预测前一天的值。这不是模型不行是数据没处理对。股票价格是非平稳序列均值和方差随时间变化。LSTM 虽然能捕捉长期依赖但它对输入尺度很敏感。原始价格从几块到几百块不等直接输入会导致梯度更新不稳定。更关键的是价格序列本身带有强趋势性模型很容易学到“明天等于今天”这种平凡解。所以预处理的核心目标有两个一是把数据缩放到合理区间二是构造出模型真正要学的监督学习样本。常见做法是只用收盘价或者用收盘价加成交量。如果做多变量输入可以把开盘、最高、最低、收盘、成交量都放进去但要注意量纲差异。成交量动辄几百万价格只有几十不处理的话成交量会主导梯度。我一般会先把所有特征做归一化再构造滑动窗口。2.2 用 MinMaxScaler 做归一化以及滑动窗口的构造代码下面这段代码展示了从原始 CSV 到 LSTM 输入张量的完整过程。假设你有一个 stock_data.csv包含 Date 和 Close 两列。import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler # 读取数据按日期排序 df pd.read_csv(stock_data.csv, parse_dates[Date]) df df.sort_values(Date).reset_index(dropTrue) # 只取收盘价shape 为 (n, 1) close_prices df[Close].values.reshape(-1, 1) # 归一化到 [0, 1] scaler MinMaxScaler(feature_range(0, 1)) scaled_data scaler.fit_transform(close_prices) # 构造滑动窗口用过去 60 天预测第 61 天 def create_dataset(data, look_back60): 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) look_back 60 X, y create_dataset(scaled_data, look_back) # LSTM 输入要求 shape: (样本数, 时间步, 特征数) X np.reshape(X, (X.shape[0], X.shape[1], 1)) # 按 8:2 划分训练集和测试集注意不能打乱顺序 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] print(X_train.shape, X_test.shape) # 例如 (1600, 60, 1) (400, 60, 1)这段代码里有几个参数需要说明。look_back 设为 60意思是模型每次看过去 60 个交易日的数据来预测下一天。这个值不是固定的短一点可以捕捉近期波动长一点能学到更宏观的趋势但太长会导致训练变慢且容易过拟合。我一般会在 20 到 120 之间试。MinMaxScaler 的 feature_range 默认是 (0,1)也可以改成 (-1,1)对 tanh 激活函数更友好但差别不大。划分训练集时绝对不能 shuffle因为时序数据打乱后未来信息会泄露到训练集模型在测试集上看起来很好实际用的时候完全失效这是血泪教训。注意归一化用的 scaler 只能在训练集上 fit然后 transform 测试集。上面为了简洁在全量数据上 fit 了严格做法应该先划分再 fit否则测试集的极值会影响训练时的缩放范围。2.3 多特征输入时的列选择和对齐问题如果你想把成交量也加进去代码要改成多列处理。但这里有个坑成交量和价格的缺失值处理方式不同。价格通常用前向填充成交量如果某天停牌就是 0不能随便填。另外多特征归一化要按列分别做不能把价格和成交量放在一起算均值和方差。常见做法是先把所有特征拼成一个 DataFrame然后对每一列单独用 MinMaxScaler或者用同一个 scaler 但 fit 的时候传入多列数据它会按列独立计算。对齐方面确保所有特征的日期索引一致不要出现价格有 1000 行、成交量只有 998 行的情况合并时用 inner join 或者先对齐再填充。3. Keras 搭建 LSTM 模型层数、单元数和 Dropout 怎么定3.1 一个能跑通的基线模型结构Keras 搭 LSTM 非常直接Sequential 模型就能搞定。下面是一个基线版本输入 60 个时间步每个时间步 1 个特征输出一个标量预测值。from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout from tensorflow.keras.optimizers import Adam model Sequential() # 第一层 LSTM返回序列给下一层 LSTM model.add(LSTM(units50, return_sequencesTrue, input_shape(look_back, 1))) model.add(Dropout(0.2)) # 第二层 LSTM只返回最后一个时间步的输出 model.add(LSTM(units50, return_sequencesFalse)) model.add(Dropout(0.2)) # 全连接层输出一个值 model.add(Dense(units1)) model.compile(optimizerAdam(learning_rate0.001), lossmean_squared_error) model.summary()这个结构里第一层 LSTM 的 return_sequencesTrue 是必须的因为后面还接了一层 LSTM。如果只堆一层 LSTMreturn_sequences 设为 False 即可。units50 表示 LSTM 内部隐藏状态的维度这个值越大模型容量越强但训练也越慢容易过拟合。股票数据通常噪声很大50 到 100 是比较稳妥的范围。Dropout 加在 LSTM 后面比例 0.2 到 0.5 之间我一般用 0.2 或 0.3。注意 Dropout 不能加在 LSTM 内部除非用 recurrent_dropout否则会破坏时间依赖Keras 里直接加在层与层之间就行。损失函数用 MSE 是最常见的因为回归任务。优化器 Adam 的 learning_rate 默认 0.001如果训练 loss 震荡厉害可以降到 0.0005 或 0.0001。batch_size 一般设 32 或 64epochs 先跑 50 看看收敛情况。3.2 训练过程中的 EarlyStopping 和 ModelCheckpoint股票数据训练很容易过拟合训练 loss 一直降验证 loss 开始升。这时候需要 EarlyStopping 来提前终止并保留验证集上最好的权重。from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint callbacks [ EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue), ModelCheckpoint(best_lstm_model.keras, monitorval_loss, save_best_onlyTrue) ] history model.fit( X_train, y_train, epochs100, batch_size32, validation_data(X_test, y_test), callbackscallbacks, verbose1 )EarlyStopping 的 patience10 表示验证 loss 连续 10 个 epoch 不下降就停。restore_best_weightsTrue 会自动恢复到验证 loss 最低时的权重省得你手动再加载。ModelCheckpoint 保存的格式用 .keras这是 Keras 3 的推荐格式旧版用 .h5 也行。validation_data 直接用测试集是不严谨的严格来说应该从训练集里再切一部分做验证集测试集只在最后评估用。但股票数据量通常不大很多人就这么用了你知道这个区别就行。3.3 预测结果的反归一化和评估指标模型输出的是归一化后的值要还原成真实价格才能看。反归一化用 scaler.inverse_transform但注意输入形状要匹配。# 预测 train_predict model.predict(X_train) test_predict model.predict(X_test) # 反归一化 train_predict scaler.inverse_transform(train_predict) y_train_inv scaler.inverse_transform(y_train.reshape(-1, 1)) test_predict scaler.inverse_transform(test_predict) y_test_inv scaler.inverse_transform(y_test.reshape(-1, 1)) # 计算 RMSE from sklearn.metrics import mean_squared_error import math train_rmse math.sqrt(mean_squared_error(y_train_inv, train_predict)) test_rmse math.sqrt(mean_squared_error(y_test_inv, test_predict)) print(fTrain RMSE: {train_rmse:.2f}) print(fTest RMSE: {test_rmse:.2f})RMSE 是最常用的指标单位跟价格一样。如果测试集 RMSE 是 5 块而股价本身才 20 块那这个模型基本没用。通常测试集 RMSE 会比训练集高不少这是正常的但如果高得离谱比如训练集 RMSE 1 块、测试集 20 块那就是过拟合了需要减层、减 units、加 Dropout 或者加更多数据。另外可以看 MAE 和 MAPEMAPE 对价格量级不敏感但股价接近 0 时会爆炸慎用。4. 避坑与排查LSTM 股票预测里最容易翻车的 5 个地方4.1 现象模型预测出来是一条直线几乎不变原因最常见的是归一化没做对或者 look_back 太短模型学不到变化。另一个可能是学习率太低模型还没收敛就停了。还有一种情况是数据本身波动极小比如选了波动率很低的银行股日线。解决先检查归一化后的数据范围确认不是全 0 或全 1。把 look_back 从 60 调到 30 或 90 试试。学习率调到 0.001 或 0.0005多跑几个 epoch。如果还不行换一只波动大一点的股票或者改用分钟级数据。4.2 现象训练 loss 正常下降但测试集预测完全对不上原因时序数据泄露。最常见的是在划分训练集和测试集之前做了 shuffle或者用全量数据 fit 了 scaler。另一个原因是用了未来数据做特征比如把明天的成交量也放进了输入。解决确保划分时按时间顺序切不要打乱。scaler 只在训练集上 fit。检查特征列里有没有包含预测目标之后的信息。如果是多变量输入逐个确认每个特征的时序对齐是否正确。4.3 现象模型训练非常慢一个 epoch 要跑好几分钟原因LSTM 层数太多、units 太大或者 batch_size 太小。另外如果用了 CPU 跑速度会比 GPU 慢几十倍。解决先把 units 从 100 降到 50层数从 3 层降到 2 层。batch_size 从 16 调到 64 或 128。确认 TensorFlow 是否识别到了 GPU用 tf.config.list_physical_devices(GPU) 检查。如果只能用 CPU考虑把 look_back 从 120 降到 30减少时间步。4.4 现象验证 loss 比训练 loss 低很多原因这种情况比较少见通常是因为验证集恰好比较简单或者 Dropout 在训练时拉高了 loss而验证时 Dropout 关闭了。如果差距很大也可能是验证集太小统计波动大。解决如果只是略低不用管。如果低很多检查验证集划分是否合理是不是把一段平稳期全划过去了。可以试试把验证集比例调大或者用交叉验证的方式做时序切分。4.5 现象换一只股票或换一个时间段模型完全失效原因股票市场风格切换模型在旧数据上学到的模式在新数据上不适用。LSTM 不是万能函数逼近器它只能学到训练分布内的规律。解决这是本质问题没有银弹。常见做法是定期用新数据重新训练或者用滚动窗口的方式每次只用最近 N 天数据训练。也可以把多只股票的数据混在一起训练增加多样性但要注意不同股票的尺度差异归一化要按股票分别做。5. 让 LSTM 股票预测真正可用的几个进阶技巧5.1 用多步预测代替单步预测单步预测就是预测下一天多步预测是一次输出未来 5 天或 10 天。Keras 里可以把 Dense 层的 units 改成 5然后 y 也改成对应的多步标签。这样模型学到的不是某一天的值而是一段趋势。多步预测的评估不能只看某一天的 RMSE要看整段预测曲线的形状是否跟真实走势一致。我一般会把预测出来的 5 天连成线跟真实 5 天叠在一起看如果方向对但幅度有偏差说明模型学到了趋势只是尺度没校准好。5.2 加入技术指标作为额外特征只用收盘价信息量有限。可以加入 MACD、RSI、布林带这些技术指标。计算 MACD 用 pandas 的 ewm 很方便但要注意指标的计算窗口不能包含未来数据。比如 12 日 EMA 在计算时第 t 天的值只用到 t 天及之前的数据这是天然满足的。把 MACD 的 DIF 和 DEA 两列加进去归一化后跟收盘价拼在一起输入 shape 变成 (样本数, look_back, 3)。实测加入 MACD 后模型对趋势转折的捕捉会好一些但也不是万能的指标本身有滞后。5.3 用回调函数动态调整学习率固定学习率有时候不够灵活。可以加 ReduceLROnPlateau当验证 loss 不再下降时自动降低学习率。from tensorflow.keras.callbacks import ReduceLROnPlateau reduce_lr ReduceLROnPlateau( monitorval_loss, factor0.5, patience5, min_lr1e-6, verbose1 )factor0.5 表示每次降低一半patience5 表示 5 个 epoch 不降就触发。min_lr 是下限防止学习率降到 0。这个回调跟 EarlyStopping 一起用效果通常比固定学习率好。我自己的习惯是先跑一个基线看 loss 曲线如果下降过程中有明显的平台期就加 ReduceLROnPlateau如果一直震荡就手动把初始学习率调低。5.4 保存和加载模型的正确姿势训练完的模型要保存方便下次直接预测。Keras 3 推荐用 model.save(model.keras)加载用 tf.keras.models.load_model(model.keras)。注意保存的时候要把 scaler 也一起存下来否则下次预测时归一化对不上。可以用 joblib 存 scaler。import joblib model.save(lstm_stock_model.keras) joblib.dump(scaler, scaler.pkl) # 加载时 model tf.keras.models.load_model(lstm_stock_model.keras) scaler joblib.load(scaler.pkl)加载后做预测输入数据要先按 scaler 做 transform预测完再 inverse_transform。这一步顺序不能错我见过有人加载模型后直接喂原始价格结果预测出来全是负数排查了半天才发现是忘了归一化。5.5 一个我常用的验证习惯每次训练完我不会只看 RMSE。我会把测试集最后 100 天的真实价格和预测价格画在一张图上用 matplotlib 保存成图片。然后肉眼看一下模型是不是在大部分时间都滞后于真实价格如果是说明 look_back 可能太短或者模型偏向于保守预测。如果模型在趋势转折点完全没反应说明它只学到了平滑没有学到突变。这个习惯帮我省了很多次盲目调参的时间。股票预测本身不确定性极高LSTM 能做的只是从历史数据里提取统计规律不要指望它战胜市场。把它当成一个时序建模的练手项目把数据处理、模型搭建、调参、评估这套流程跑通比追求预测精度更有价值。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。