首页 / 资讯中心 / 文章详情

LSTM股票预测实战:从数据预处理到Django部署完整可运行项目解析

LSTM股票预测实战:从数据预处理到Django部署完整可运行项目解析 ★ FEATURED ARTICLE
简介基于Python的LSTM股票走势预测项目面向高校学生及金融时序分析初学者提供了从数据处理到模型预测的完整实现。项目以长短期记忆网络为核心涵盖历史行情数据清洗、特征构造、模型训练、评估及预测结果可视化等环节代码注释清晰逻辑易读适合毕业设计、期末大作业或课程设计直接参考或复现。压缩包共89个文件以24个Python源码文件为主包含模型定义、训练和预测脚本另有19个编译缓存、13个文本说明、6张效果截图、CSS/JS/HTML等Web展示文件以及Excel数据表和SQLite数据库文件整体体积8.88MB部署简单、目录规整。资源配有现成数据集和已训练模型下载后即可运行也支持自行调整参数进一步实验。项目经严格调试功能完整、界面美观已有141人学习下载作为导师认可的高分项目能帮助读者快速掌握LSTM在股票预测中的应用。1. 把 LSTM 用在股票走势预测上这份代码包到底能不能跑通股票预测在很多人眼里是玄学但作为期末大作业、毕设或者课程设计它的价值不在“预测得准不准”而在你有没有完整走通“数据获取 → 预处理 → 序列建模 → 训练 → 可视化 → 部署展示”这条链路。这是一份可以直接运行的 Python LSTM 股票预测资源包含源码、数据集和训练好的模型项目里还带一个 Django 页面能选股票、看预测曲线、下载结果。适合三类人想交一个高分期末大作业的学生、想快速拿到可复现代码做毕设的人、以及对 LSTM 时间序列预测感兴趣但不想从零搭环境的从业者。先说结论只要 Python 环境装好按本文流程复制粘贴半小时左右就能把预测曲线跑出来。提示这份资源的价值是完整可运行不是预测精度。用 LSTM 做股票短期走势本质是在拟合历史序列的统计规律。接下来按数据、模型、部署、排错的顺序拆。2. 数据从哪来、怎么喂给 LSTM预处理和滑动窗口样本构建2.1 数据集里有什么先搞清楚字段含义解压这份资源后核心文件是stock_prediction目录下的django code.py和数据集。数据集一般是 CSV 格式每一行是一天的交易记录字段通常包括字段含义用途Date交易日期时间轴Open开盘价特征High最高价特征Low最低价特征Close收盘价特征/标签Volume成交量特征我最常用的是Close收盘价作为预测目标偶尔加上Open、High、Low、Volume一起做多维输入。这里提醒一下拿到的 CSV 里第一行大概率是表头读取时处理好如果是从行情软件导出的可能还有前几行公司信息之类的杂数据最好先用 Excel 打开确认一次。import pandas as pd df pd.read_csv(your_stock_data.csv, parse_dates[Date]) df df.sort_values(Date) # 确保按时间升序 print(df.head()) print(df.info())这段代码做两件事把 Date 列解析成时间类型并按日期升序排列。很多新手直接用原始 CSV 顺序训练如果原始数据是降序最新日期在最上面序列就被倒过来了LSTM 学到的是反时序规律预测出来完全不对。排序这一步在金融数据里几乎从来不会省任何行情接口返回的数据都要先确认时间方向。2.2 标准化为什么用 MinMaxScaler 而不是 StandardScaler股票价格序列不是稳定的数值范围一直在变比如一只股票从 10 元涨到 80 元而 LSTM 内部用的是 tanh/sigmoid 激活函数输入数值过大或过小都会让梯度不稳定。所以训练前必须做归一化。常见做法是 MinMaxScaler把每列特征压缩到 [0, 1] 区间。这里有一个容易翻车的点scaler 必须在训练集上 fit再分别 transform 训练集和测试集。如果对整个数据集一次性 fit_transform测试集的信息比如未来的最高价就已经泄漏进训练阶段了这在答辩时会被老师抓住。from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler(feature_range(0, 1)) train_size int(len(df) * 0.8) train_df df.iloc[:train_size] test_df df.iloc[train_size:] scaled_train scaler.fit_transform(train_df[[Close]]) scaled_test scaler.transform(test_df[[Close]])fit_transform 帮我们完成两步先 fit 求出训练集每列的最小值和最大值再按这个范围做归一化。transform 则只应用已经算好的参数不再重新计算。区别就在这里——测试集的缩放必须复用训练集的 min/max否则测试数据会被重新规划到一个不同的尺度上模型推理时的输入分布和训练时不一致输出自然会乱。2.3 滑动窗口把一维价格变成 LSTM 的三维输入LSTM 不认识“单日收盘价”这种孤立数据它需要的是一个时间窗口比如用前 60 天的价格去预测第 61 天的价格。这个窗口在代码里通常叫lookback或time_step。窗口大小直接影响结果太短比如 5 天模型只看到最近几天的波动抓不住中期趋势太长比如 250 天训练样本数量骤减LSTM 也没必要记那么久。我一般习惯用 60 天约等于一个季度的工作日数。这是权衡之后比较均衡的值样本量足够信息量也不差。import numpy as np def create_sequences(data, lookback60): X, y [], [] for i in range(len(data) - lookback): X.append(data[i:ilookback, 0]) y.append(data[ilookback, 0]) return np.array(X), np.array(y) X_train, y_train create_sequences(scaled_train, lookback60) X_test, y_test create_sequences(scaled_test, lookback60) # 调整成 LSTM 需要的形状 (样本数, 时间步, 特征数) X_train X_train.reshape(X_train.shape[0], X_train.shape[1], 1) X_test X_test.reshape(X_test.shape[0], X_test.shape[1], 1) print(X_train.shape, y_train.shape)核心逻辑是对第 i 个样本截取data[i:ilookback]作为输入data[ilookback]作为标签。reshape 是新手最容易报错的地方——LSTM 层要求输入是三维张量三个维度分别是样本数、时间步数、特征数量。前 60 天的多列特征Open、High、Low、Close、Volume都拼接在最后一个维度上如果只用收盘价一列最后一个维度就是 1。2.4 划分训练集与测试集不能随机 shuffle分类任务里随机打乱样本没问题但时间序列任务里绝对不能。如果对序列做了 shuffle模型看到的是“今天预测昨天”这种毫无因果关系的样本。正确做法是严格按时间顺序切分比如前 80% 做训练、后 20% 做测试这样测试阶段模拟的才是“用历史数据预测未来”。3. LSTM 模型结构设计和训练参数网络搭起来还要让它收敛3.1 LSTM 为什么适合时间序列从门控机制说起LSTMLong Short-Term Memory相比普通 RNN 的核心改进是引入了三个门遗忘门、输入门、输出门。遗忘门决定丢弃哪些旧信息输入门决定写入哪些新信息输出门决定输出哪些信息。对股票数据来说这意味着模型可以自己学会“最近几天的急跌信号更重要三个月前的某次暴涨可以忽略”。很多课程设计用的是单层 LSTM 加一个 Dense 输出层。我的经验是单层 LSTM 就够用除非做研究否则堆两层 LSTM 只会让训练时间翻倍、过拟合风险增大预测精度提升却很有限。原因在于股票数据本身的信噪比极低模型复杂度再高也挖不出更多确定性的规律反而是噪声被学进去了。3.2 模型结构与关键参数模型结构可以这样定义from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout model Sequential([ LSTM(units50, return_sequencesFalse, input_shape(60, 1)), Dropout(0.2), Dense(1) ]) model.compile(optimizeradam, lossmean_squared_error, metrics[mae]) model.summary()几个参数说明units50记忆单元的数量控制模型容量。单元数太少欠拟合太多则可能把训练集的噪声都背下来。50 是折中值。return_sequencesFalse只返回最后一个时间步的输出因为要的是预测值而不是每个时间步的中间状态。如果堆叠多层 LSTM前面的层要设为 True否则第二层 LSTM 接收不到完整的时间序列。Dropout(0.2)随机丢弃 20% 的神经元连接降低过拟合。mean_squared_errorMSE 适合做回归。如果导师问为什么不选 MAE可以说 MSE 对大误差惩罚更大对极端波动更敏感这在股票风险场景下是合理的偏好。3.3 训练过程中的关键回调早停和模型保存训练有个常见问题不设早停只设很大的 epochs比如 500结果跑到后面过拟合训练损失低得离谱预测曲线却完全不动。我的做法是配合 EarlyStopping 和 ModelCheckpoint用验证集来决定什么时候停、保存哪一次的权重。from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint early_stop EarlyStopping(monitorval_loss, patience20, restore_best_weightsTrue) checkpoint ModelCheckpoint(best_model.h5, monitorval_loss, save_best_onlyTrue) history model.fit( X_train, y_train, validation_data(X_test, y_test), epochs100, batch_size32, callbacks[early_stop, checkpoint], verbose1 )patience20表示验证集损失连续 20 个 epoch 不降低就停止。restore_best_weightsTrue会把模型权重回滚到验证集最好的那一步。save_best_onlyTrue则只在验证集变好时保存模型文件。batch_size 选 32 是基于样本量的常规选择样本只有几千条的话batch_size 过大比如 128会让梯度更新太稳定过小比如 4则会震动太大。训练完以后最直观的验证是画一张图把测试集预测价格和真实价格叠在一起。如果预测线和真实线存在明显的滞后错位通常是模型把“昨天的价格”直接搬过来了这个放在第 5 章专门讲。4. 把模型跑起来并部署展示Django 页面和预测流程完整打通4.1 Django 项目里启动的准备工作这份资源里django code.py是入口不要被“代码.py”这个名字带偏它既包含数据处理逻辑也包含 Django 的启动配置。我把项目目录放在stock_prediction里面有requirements.txt或者在文件头能看到 import 的第三方库列表。先确认依赖装全。这份资源依赖基本是 pandas、numpy、scikit-learn、tensorflow、django、matplotlib 这几件套。pip install pandas numpy scikit-learn tensorflow django matplotlib注意TensorFlow 和 Python 版本有强绑定关系。如果用的是 Python 3.8装 TensorFlow 2.10 之前的问题不大如果是 Python 3.11 以上建议装 TensorFlow 2.13否则可能找不到对应版本的预编译包。装完在终端里用python -c import tensorflow as tf; print(tf.__version__)验证。4.2 预测流程加载模型、反归一化、出图页面上的实际预测流程通常是从表单里选股票代码 → 读取对应 CSV → 重复第 2 章的预处理步骤 → 加载训练好的模型 → 生成未来 N 天的预测 → 把归一化结果反变换回真实价格 → 用 matplotlib 画图 → 渲染到页面上。from tensorflow.keras.models import load_model import matplotlib.pyplot as plt model load_model(best_model.h5) # last_sequence 是最后一组长度为 60 的输入序列形状为 (1, 60, 1) pred_scaled model.predict(last_sequence) pred_price scaler.inverse_transform(pred_scaled) print(f预测价格: {pred_price[0][0]:.2f})这里有几个细节容易踩坑load_model需要和保存模型时的 Keras 版本兼容。用 TensorFlow 2.x 保存的.h5在另一个环境里如果 Keras 跨了大版本比如 2.15 加载 3.x 保存的模型会报 Unknown layer 或无法解析的错误。所以模型文件和训练环境尽量保持一致。inverse_transform只接收二维数组所以要把(1, 1)的三维预测结果先变成二维再传进去。上面pred_scaled的形状取决于模型输出层一般是(1, 1)。如果页面展示需要多天预测常见做法是迭代式预测把第 61 天的预测结果拼到序列末尾再预测第 62 天……但误差会逐日累积预测天数越长越不靠谱。这类项目通常只预测未来 5~30 天。4.3 Django 路由和页面渲染如果改成自己的页面核心就是三个文件urls.py配路由views.py写预测逻辑模板文件渲染图片。图片不用上传到静态目录直接以 base64 编码嵌进 HTML避免文件权限问题。import base64 from io import BytesIO def generate_chart(history, prediction): plt.figure(figsize(10, 4)) plt.plot(history, label历史价格) plt.plot(prediction, label预测价格, linestyle--) plt.legend() buf BytesIO() plt.savefig(buf, formatpng) buf.seek(0) image_base64 base64.b64encode(buf.read()).decode(utf-8) plt.close() return image_base64这段代码在本地跑通常不会出问题但部署到服务器上要注意中文字体问题。Linux 服务器大概率没有 SimHei 或 Microsoft YaHei 字体plt 画的图上中文会显示成方块。解决方式有两种一是在代码里指定一个服务器上装好的中文字体路径二是干脆把图里所有中文标签改成英文。课程设计答辩展示一般是本地跑但如果部署到实验室服务器上这个坑就会出现。4.4 完整的跑通顺序整个项目的运行顺序整理成四步照着走就能看到页面把 csv 数据集和django code.py放同一目录检查 csv 里 Date 和 Close 列存在。pip install依赖装完。运行python django code.py终端会显示 Django 启动地址比如http://127.0.0.1:8000。浏览器打开页面选股票名称点预测按钮。如果数据文件特别大比如几年的分钟级数据第一轮预处理可能会比较慢这是正常的。项目里用的是日线数据几千行对 pandas 来说是小事。5. 避坑指南这几条踩坑记录花了我一整晚5.1 现象LSTM 预测曲线看起来“非常准”但仔细看是错位的第一次跑出预测图看到测试集末尾的预测线和真实线贴得很近兴奋得不行。但放大了看预测值实际上是真实值的“昨天平移版”——模型只学会了“今天的价格约等于昨天的价格”。原因金融价格序列自相关性极高如果模型输入的最后一帧就是昨天的价格输出直接抄一个接近值就能把损失降到很低。LSTM 在这种场景下很容易走捷径学到滞后复制而不是真正的趋势推演。解决两个手段同时用。一是减小 lookback 窗口从 60 降到 30让模型不能单纯依赖最后一天二是把训练目标从“预测绝对价格”改成“预测涨跌幅度”比如标签变成(t1价格 - t价格) / t价格模型就没法直接抄了。注意这是 LSTM 股票预测里最容易迷惑新人的坑。答辩时如果被老师问“你的模型是不是只学了昨天的价格”要能说清你做了差分处理或涨跌幅标签。5.2 现象标准化时测试集信息泄漏测试集精度虚高有一次我把全部数据用同一个 MinMaxScaler 做完归一化再切训练测试集。测试集上 R² 高达 0.98自己都难以置信后来才发现是泄漏了。原因scaler 对全量数据 fit 时已经把未来区间的最大值、最小值写进了归一化公式。换句话说预测“今天”的时候模型已经见过“明天”的取值范围测试集结果自然漂亮。这在课程设计里属于数据泄漏导师一追问就会露馅。解决先切分再 fit 训练集再 transform 训练集和测试集。也就是第 2 章代码的顺序不能改。5.3 现象启动 Django 报错 ModuleNotFoundError 或模型文件加载失败Django 项目解压在别的电脑上直接跑起来报ModuleNotFoundError: No module named tensorflow或者OSError: Unable to open file (file not found)。原因目标电脑缺少依赖或者best_model.h5的相对路径不对。Django 运行时代码里的相对路径是相对于当前工作目录不是相对于代码文件目录。解决在django code.py开头强制把路径锚定到项目根目录最稳的做法是import os BASE_DIR os.path.dirname(os.path.abspath(__file__)) MODEL_PATH os.path.join(BASE_DIR, best_model.h5) DATA_PATH os.path.join(BASE_DIR, data.csv)这样无论从哪个目录启动都能找到模型和数据。另外如果本机确实没装 TensorFlow先去跑pip install tensorflow2.10.0之类的指定版本再返回来。5.4 现象训练时 loss 越来越小但预测曲线是条直线模型收敛了但画出来预测价格是一条几乎平坦的直线。原因如果把预测目标设成未来 N 日的价格且数据标准化后值域很窄模型倾向于输出训练集中最后的均值。特别是 dropout 过高0.5 以上或 LSTM units 过少时模型根本没有学到波动规律只学到了“输出一个中间价最安全”。解决降低 dropout 到 0.2 左右增加 units 到 50 或 64把目标从“未来多日价格”改成“未来一天价格”只预测 T1不要一步预测 T10。还可以检查是不是忘了设验证集——如果没有验证集模型完全过拟合训练集泛化能力极差。5.5 现象Python 版本和 TensorFlow 安装对不上pip install 一直报错在 Windows 上直接pip install tensorflow报ERROR: No matching distribution found for tensorflow。原因TensorFlow 对新版本 Python 的支持总是滞后。比如 Python 3.11 刚出的前半年TF 还没有对应的 wheel 包pip 找不到稳定版。解决先用python --version看一下自己的版本。3.8 装 TF 2.10、3.10 装 TF 2.13、3.11/3.12 装 TF 2.15 及以上。查准版本号以后再安装pip install tensorflow2.10.0装完用print(tf.__version__)验证顺便看看能不能识别到 GPU。没有 GPU 就用 CPU 跑几百个 epoch也完全够课程设计的量级只是慢一些。6. 从“跟着曲线走”到“趋势方向准确率”让项目在答辩里更立得住把项目跑通以后绝大多数人会停在“图很好看”这一步。但如果导师追问“你的模型到底比瞎猜好多少”就需要一套不那么主观的验证指标。这里给一个简单可复用的方法方向准确率。价格预测的回归指标MSE、MAE很容易让人误判。股票价格有很强的惯性误差小不等于预测有方向价值。方向准确率指的是预测的明天涨跌方向和真实涨跌方向一致的比例。随机猜测的期望是 50%模型如果稳定在 55% 以上起码说明它抓到了某种统计规律。def direction_accuracy(y_true, y_pred): # 输入是原始价格序列计算相邻日收益率方向 actual_ret np.diff(y_true.flatten()) pred_ret np.diff(y_pred.flatten()) correct (actual_ret 0) (pred_ret 0) return correct.sum() / len(correct) acc direction_accuracy(real_prices, predicted_prices) print(f方向准确率: {acc:.2%})这段函数先计算真实价格的相邻差再计算预测价格的相邻差然后比较符号。逻辑很简单但答辩时这道题的杀伤力很强——老师会立刻知道你确实理解了预测问题的本质。如果方向准确率只有 50% 多一点也不丢人你可以主动解释这说明价格的可预测性非常有限LSTM 比随机强一点但远达不到稳定盈利的水平。这个诚实的说法比吹嘘精度更能拿分。另一个能加分的验证方法是滚动回溯测试。把数据集前 60% 做训练接下来 10% 做验证调整参数后再往后滚动 10% 重新验证。这比一次性切训练测试集更接近真实场景因为模型始终只用“过去”的数据预测“未来”的数据。实现上就是写一个外层循环每次向后滚动若干条数据重新训练。for start in range(0, 400, 80): train df.iloc[start:start500] test df.iloc[start500:start600] # 重新执行预处理和训练 # 记录方向准确率最后汇总平均这段代码不需要跑很久展示思路即可。回溯测试里每次窗口重新训练的耗时可能较长答辩展示时建议只跑 1~2 轮然后口头说明完整过程没必要在现场等十分钟。我自己的习惯是拿到任何 LSTM 股票预测代码第一件事先跑通第二件事立刻用最近 90 个真实交易日做一次模拟验证——把第 60 天才有的数据留出来不碰重新训练后看这段区间的方向准确率。从那以后我每次提交课程设计或毕设代码都会强制走一遍这个验证流程确保模型不是被数据集“喂”出来的巧合也希望帮你在交付前多一层检查。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站