基于Python的时间序列预测:从ARIMA到LSTM的毕设级闭环

发布时间:2026/10/12 22:24:30
基于Python的时间序列预测:从ARIMA到LSTM的毕设级闭环 简介资源围绕 Python 深度学习的时间序列预测展开完整覆盖标普500与太阳黑子两类实验场景适合高校学生以毕设、课程设计或工程实训为背景进行入门与进阶实践。包内代码按数据集、标普500、太阳黑子三个模块组织包含基于 LSTM、ARIMA、SVM、ARMA 等模型的 Python 脚本以及对应 CSV 数据文件、说明文档与数据集目录便于对照实验流程理解数据预处理、模型构建、预测与评估。资源共 19 个文件以 Python 脚本为主辅以 CSV 数据、Markdown 说明和 dataset 目录压缩包约 177KB轻量易用。目前已有 158 人学习下载适合希望从实际案例入手掌握时间序列建模与深度学习应用的学习者可直接参考工程结构、运行思路与项目文档进行二次开发。1. 时间序列预测的 Python 落地版图从 ARIMA 到 LSTM 的毕设级闭环用 Python 做深度学习时间序列预测最容易卡住的不是模型本身而是数据、基准方法和评估链路没有一个能打通的完整样例。这套基于 Python 的深度学习时间序列预测项目同时放了太阳黑子月均值和标普500 两份数据集每个数据集目录下都有 loader、svm、arima/arma、lstm、predict、EvaluationIndex 全套脚本属于典型的「一份资源跑完三类模型」的毕设级工程。它能解决什么首先是给你一个可以直接对照的模型选型参照系统计模型、核方法、LSTM 在同样的数据上谁更稳、谁更吃数据量、谁需要先做平稳化。其次是给出一套可改参数复用的代码骨架——换数据集时只需要动 loader 和归一化部分。适合正在准备毕设、课程设计、大作业的学生也适合想短时间横向比较三类模型效果、不想从零搭框架的从业者。我拆这类资源的习惯是先不看模型先看数据文件和预处理脚本因为时间序列项目翻车十有八九发生在差分还原、归一化泄漏、指标计算这些细活上。下面我按数据与选型、代码模块、复现流程、避坑记录、进阶技巧的顺序把这份资源完整讲透。2. 数据与模型选型太阳黑子、标普500 为什么能当基准2.1 四份 CSV原始序列与差分序列的搭配逻辑dataset 目录下四份文件对应两类研究对象。sunspot_ms.csv 是太阳黑子月均值数值在 0 到 300 量级波动带有非常明显的约 11 年周期。周期性强的序列适合检验模型能不能学到相位。sunspot_ms_diff.csv 是它的一阶差分结果表示每月增量差分后序列变得平稳专供 ARMA 这类要求平稳输入的统计模型使用。spv2.csv 是标普500 处理后的收盘价序列趋势加波动混合非平稳属性明显。sp2005-2015.csv 是从中截取的 2005 到 2015 年区间版本样本量更小适合快速迭代调试也方便做同区间横向对比。标普这条线跟金融量化场景直接相关自己扩展成收益率序列就是量化策略里常见的预处理这份数据可以直接当练手入口。把强周期序列和金融序列放在同一套代码下本身就是对模型泛化能力的压力测试太阳黑子考验周期相位捕捉标普500 考验趋势与随机波动的分离。如果一套 loader 加三套模型在两类数据上都能给出合理指标这个资源可信度就立住了。拿到压缩包后我建议先跑一段探查脚本确认每份 CSV 的列名格式避免后面 loader 传参对不上import pandas as pd for path in [dataset/sunspot_ms.csv, dataset/sunspot_ms_diff.csv, dataset/spv2.csv, dataset/sp2005-2015.csv]: df pd.read_csv(path) print(path, df.shape, df.columns.tolist()) print(df.head(3).values.tolist())先打印列名对齐一遍是血泪教训换来的习惯。这个项目里不同文件的列名不完全一致有的是 close有的是 value直接套同一个 target_col 参数会报 KeyError。确认格式后再决定 loader.py 里怎么传参能省掉后面一大半无意义的报错排查。2.2 三类模型的适用边界统计基线、核方法与深度网络ARIMA/ARMA 是统计基线。ARMA 要求序列平稳所以项目里配套了 sunspot_ms_diff 差分序列ARIMA 则自带差分参数 d可以直接作用在非平稳序列上。它的优势是参数少、可解释性强对线性自相关结构拟合很稳但处理强非线性、长程依赖会明显力不从心。SVM实际是 SVR支持向量回归在这里代表核方法路线。把滑窗生成的向量当特征、下一时刻当标签用 RBF 核在高维空间做回归。SVR 在小样本下往往能跟 LSTM 打平训练快、不需要 GPU缺点是窗口拉长时特征维度变高核矩阵计算成本涨得快且对归一化尺度非常敏感。LSTM 是深度学习路线的主角。遗忘门和输入门能记住长程依赖理论上最适合带周期和趋势混合的序列。但它也是三者里最吃数据和调参的lookback 窗口、隐层数、学习率、随机种子差一点结果就差一大截属于典型的需要靠固定种子和多次实验压住波动性的模型。模型输入前提样本量需求长程依赖可解释性本资源中的定位ARIMA/ARMA差分后平稳小弱高p,d,q 直接可读统计基线SVR滑窗特征标准化中中中靠核函数核方法对照LSTM窗口序列归一化大强低黑匣子深度学习主角这张表建议打印出来贴在工位上每跑完一组实验就把三个模型的 RMSE、MAE 往里填一行。时间序列预测项目的答辩或汇报最能说明问题的就是这张对比表。2.3 为什么要准备差分数据ADF 检验与平稳化统计模型对平稳性的要求是硬约束不是可选项。平稳意味着序列的均值、方差不随时间漂移自相关结构稳定ARMA 系数估计才有统计意义。太阳黑子原始序列均值随周期波动标普500 更是长期趋势明显直接喂给 ARMA系数会失真。常见做法是用 ADF 检验先定量判断statsmodels 里一行就能出结果from statsmodels.tsa.stattools import adfuller def check_stationarity(series, nameseries): res adfuller(series, autolagAIC) print(f{name}: ADF{res[0]:.3f}, p-value{res[1]:.4f}) if res[1] 0.05: print( - 拒绝单位根假设序列平稳可直接建模) else: print( - 存在单位根建议做一阶差分后再检验) # sunspot_original / sunspot_diff 是两个 numpy 一维数组 check_stationarity(sunspot_original, sunspot) check_stationarity(sunspot_diff, sunspot_diff)ADF 检验的零假设是序列存在单位根也就是非平稳。p 值小于 0.05 才能拒绝零假设、认定平稳所以看到 p 值大不要慌那不是平稳性显著而是没法证明平稳。差分一次后 p 值通常会掉到 0.01 以下这才是能拿去建 ARMA 的信号。项目直接备好了 diff 版本但我还是建议自己跑一遍检查这是理解 ARIMA 里 d1 含义的关键一步。3. 代码模块拆解从 loader.py 到 EvaluationIndex.py 的完整链路3.1 loader.py统一数据入口、滑窗与可逆归一化sp500 和 sunspot 两个目录里都有 loader.py职责一致读 CSV、切分训练测试、构造滑窗样本、做归一化。这个模块是整个工程的地基因为三个模型的输入格式都要从这里统一出去。import numpy as np import pandas as pd def load_series(path, date_colNone, target_colclose): df pd.read_csv(path) if date_col is not None: df[date_col] pd.to_datetime(df[date_col]) df df.sort_values(date_col).reset_index(dropTrue) return df[target_col].to_numpy(dtypenp.float32) def split_series(data, train_ratio0.8): cut int(len(data) * train_ratio) return data[:cut], data[cut:] def make_windows(data, lookback12, horizon1): X, y [], [] for i in range(len(data) - lookback - horizon 1): X.append(data[i:i lookback]) y.append(data[i lookback:i lookback horizon]) return np.array(X), np.array(y) def minmax_fit_scale(train): vmin, vmax train.min(), train.max() def scale(x): return (x - vmin) / (vmax - vmin 1e-8) def inv_scale(x): return x * (vmax - vmin) vmin return scale, inv_scalemake_windows 用滑窗把一维序列切成监督学习的输入输出对X 是连续的 lookback 个历史值y 是未来 horizon 个值。minmax_fit_scale 返回 scale 和 inv_scale 两个闭包函数scale 把原始值映射到 [0,1]inv_scale 把预测结果还原回原量纲后面 predict.py 一定用得到。三个函数里参数最需要注意的是归一化拟合 min 和 max 只能用 train 部分test 只能调用 scale 做变换顺序不能反。3.2 传统基线arima.py/arma.py 的定阶与 svm.py 的窗口回归ARMA/ARIMA 脚本的核心是定阶。p 是自回归阶数q 是移动平均阶数d 是差分次数。定阶有两条路画 ACF/PACF 图肉眼判断或者用 AIC 网格搜索自动选。工程上我一般直接网格搜索范围压到合理区间import itertools from statsmodels.tsa.arima.model import ARIMA def best_arima_order(train, d1, max_p5, max_q5): best_aic, best_order float(inf), None for p, q in itertools.product(range(max_p 1), range(max_q 1)): try: model ARIMA(train, order(p, d, q)).fit() if model.aic best_aic: best_aic, best_order model.aic, (p, d, q) except Exception: continue return best_order, best_aicAIC 是拟合优度与参数数量的权衡越小越好。p、q 上限取 5 是因为太阳黑子这类月度序列通常低阶就能拟合盲目取 15 只会让搜索时间爆炸还容易过拟合。如果用的是 sunspot_ms_diff.csvd 直接传 0因为那份数据已经差分完毕再差一次反而丢信息。SVM 脚本走的是滑窗回归路线特征就是窗口里的历史值。SVR 对特征尺度敏感所以必须做标准化而且注意这里按特征维度标准化不是按样本from sklearn.svm import SVR from sklearn.preprocessing import StandardScaler def svm_forecast(X_train, y_train, X_test, kernelrbf, C1.0, epsilon0.01): scaler StandardScaler() X_train_s scaler.fit_transform(X_train) X_test_s scaler.transform(X_test) model SVR(kernelkernel, CC, epsilonepsilon) model.fit(X_train_s, y_train.ravel()) return model.predict(X_test_s)C 是正则化强度越大越倾向硬拟合、容易过拟合epsilon 是 ε-不敏感损失的宽度越大允许的误差越大、回归面越平滑。太阳黑子序列噪声不小epsilon 给 0.01 和 0.1 出来的预测曲线平滑度差异很大建议两个都试再结合指标选。3.3 lstm.py 与 model.py可复现的深度网络骨架LSTM 脚本在 PyTorch 下的写法可以拆成模型定义和训练循环两部分。model.py 里放模型类lstm.py 里放训练与预测流程import torch import torch.nn as nn class LSTMPredictor(nn.Module): def __init__(self, input_size1, hidden_size64, num_layers2, dropout0.2): super().__init__() self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue, dropoutdropout) self.fc nn.Sequential( nn.Linear(hidden_size, 16), nn.ReLU(), nn.Linear(16, 1) ) def forward(self, x): # x: (batch, lookback, input_size) out, _ self.lstm(x) last out[:, -1, :] return self.fc(last)x 的维度必须是 (batch, lookback, input_size)所以 loader 构造出的滑窗样本要 unsqueeze 出最后一维才能喂进来。取 out[:, -1, :] 是拿最后一个时间步的隐状态做全连接映射因为要预测的是窗口之后的未来值中间时刻的隐状态都用不上。dropout 在 nn.LSTM 里只作用于层与层之间单层 LSTM 传 dropout 会被直接忽略这个细节容易当玄学踩到。训练循环必须固定随机种子否则同一套参数两次跑完指标能差好几个点def set_seed(seed42): np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) def train_model(model, X_train, y_train, epochs100, lr1e-3, batch_size64): opt torch.optim.Adam(model.parameters(), lrlr) loss_fn nn.MSELoss() loader torch.utils.data.DataLoader( torch.utils.data.TensorDataset( torch.tensor(X_train, dtypetorch.float32).unsqueeze(-1), torch.tensor(y_train, dtypetorch.float32).view(-1, 1), ), batch_sizebatch_size, shuffleTrue) for epoch in range(1, epochs 1): model.train() total 0.0 for xb, yb in loader: opt.zero_grad() loss loss_fn(model(xb), yb) loss.backward() opt.step() total loss.item() if epoch % 20 0: print(fepoch {epoch:3d}, loss {total / len(loader):.5f})这里 shuffleTrue 是安全的因为每个样本是独立滑窗窗口内部顺序保持原样不存在把未来信息泄进过去的问题。batch_size 64、lr 1e-3 是这套代码的稳妥起点如果 loss 震荡不降把 lr 降到 3e-4 再试。3.4 predict.py 与 EvaluationIndex.py差分还原与指标闭环predict.py 是连接训练与评估的关键尤其要处理统计模型的差分还原。ARMA 预测的是差分值直接画图会得到一条围绕 0 波动的线必须做累积求和还原def diff_restore(diff_forecast, last_original): restored [last_original] for v in diff_forecast: restored.append(restored[-1] v) return np.array(restored[1:])还原要从训练集最后一个原始值开始累加不是从 0 开始。如果跳过这一步LSTM 和 ARIMA 的预测曲线不在同一量纲上对比表就是废的。EvaluationIndex.py 提供统一的评价入口四个模型共用一套指标import numpy as np def evaluate(y_true, y_pred): y_true np.asarray(y_true, dtypenp.float32) y_pred np.asarray(y_pred, dtypenp.float32) rmse np.sqrt(np.mean((y_true - y_pred) ** 2)) mae np.mean(np.abs(y_true - y_pred)) mape np.mean(np.abs((y_true - y_pred) / (np.abs(y_true) 1e-8))) * 100 ss_res np.sum((y_true - y_pred) ** 2) ss_tot np.sum((y_true - y_true.mean()) ** 2) r2 1 - ss_res / (ss_tot 1e-8) return {RMSE: rmse, MAE: mae, MAPE: mape, R2: r2}RMSE 对大误差敏感适合看有没有离谱的预测点MAE 更稳健是常用主指标MAPE 在太阳黑子趋近 0 的月份会飙到几千因为分母接近 0这时候我只看 RMSE 和 MAER2 是决定系数越接近 1 说明模型解释了越多的方差但非平稳序列上 R2 天然虚高要配合预测曲线图一起看不能单独用。4. 完整复现流程环境搭建、训练参数与指标解读4.1 环境准备与依赖清单先确认 Python 版本。这套代码按 Python 3.8 设计没有问题3.10 也兼容但低于 3.7 时 torch 的预编译包不好找。如果电脑上还没装 Python先按 3.8 装好再继续。我一般新建一个干净的虚拟环境避免把系统 Python 搞乱这也是动手深度学习类教程里反复强调的环境先行思路。包名用途建议版本numpy数组与滑窗计算1.24.xpandasCSV 读取2.0.xmatplotlib预测曲线绘图3.7.xscikit-learnSVR 与标准化1.3.xstatsmodelsARIMA/ARMA 与 ADF0.14.xtorchLSTM 训练2.x CPU 版即可pip install numpy pandas matplotlib scikit-learn statsmodels pip install torch只跑 LSTM 且数据量就是太阳黑子三千多个点和标普 2005-2015 区间CPU 完全够几分钟到十几分钟一个训练周期。不要一上来就配 CUDA先把流程跑通再谈加速这能省掉大量环境折腾的时间。4.2 按数据集跑通训练与预测复现顺序建议从统计模型开始再上 SVR最后上 LSTM。这样能逐步建立基线避免一上来就被深度模型的结果带偏。# 太阳黑子先统计模型后深度模型 python arima.py --csv ../dataset/sunspot_ms.csv --steps 60 python svm.py --csv ../dataset/sunspot_ms.csv --lookback 12 python lstm.py --csv ../dataset/sunspot_ms.csv --lookback 12 --epochs 100 --hidden 64 # 标普500同样三连 python arima.py --csv ../dataset/sp2005-2015.csv --steps 60 python svm.py --csv ../dataset/sp2005-2015.csv --lookback 20 python lstm.py --csv ../dataset/sp2005-2015.csv --lookback 20 --epochs 150 --hidden 128每个脚本跑完会调用 EvaluationIndex.py 打印一组指标正常输出类似{RMSE: 12.34, MAE: 9.12, MAPE: 8.76, R2: 0.93}。把这些数字按模型、按数据集填进表格就是答辩或汇报时最有说服力的素材。如果 arima.py 报 statsmodels 的收敛警告加 trendc 或者把 maxiter 调大一点通常会缓解。4.3 关键参数怎么调lookback、order、hidden 与 epochs参数不能靠猜要跟数据周期对齐。太阳黑子是月度数据一个太阳活动周期约 132 个月LSTM 用 lookback12 只能看到一年学到的周期感有限但 lookback 拉到 132训练样本会少掉 132 条SVR 的核矩阵也会变大。常见做法是取 24 或 36 折中条件允许就做 12/24/36/60 四组对比。标普500 是日线数据lookback 20 对应约一个月交易日比较合理。参数取值范围说明lookback太阳黑子 24~60标普 10~20对齐数据周期过短学不到周期过长样本骤减dARIMA0 或 1diff 版传 0原始序列传 1p/q 搜索上限3~5低阶足够过高过拟合且 AIC 惩罚hidden_size32/64/128样本量小就从 32 起步标普用 128 更稳lr1e-3 起步loss 震荡就降到 3e-4epochs100~200配早停防止过拟合测试集一个血泪经验epochs 不是越大越好。我见过有人把 LSTM 跑到 1000 轮训练 loss 压到 1e-4测试集指标反而比 100 轮时差典型的过拟合。更稳的做法是保留验证集每 20 轮看一次验证 loss连续三次不降就早停。5. 避坑记录五条高频翻车现场的定位与修复5.1 归一化参数用到全量数据隐蔽的数据泄漏现象训练 loss 很低测试集预测曲线跟真实曲线几乎重合曲线过度平滑但换一段新数据立刻失效。原因min 和 max 是用整条序列含测试集一起算的测试集的尺度信息提前进入训练属于最隐蔽的数据泄漏。解决归一化参数只从训练集计算测试集只做变换。loader 里 minmax_fit_scale 只喂 train然后用返回的 scale 处理 test顺序不能反。检查方法是在切分前后各打印一次 min/max看测试集的 min/max 是否影响过参数。5.2 差分预测只输出增量不还原量纲现象ARIMA 在 diff 序列上 RMSE 只有个位数看着很漂亮画出来是条围绕 0 抖动的线跟真实值对不上。原因预测目标是差分值评价指标也对在了差分序列上没有还原回原始值。解决predict.py 里用 diff_restore 从训练集最后一个原始值开始做累积求和再进 EvaluationIndex。判断标准很简单还原后的 RMSE 量纲应该和原始序列一致而不是个位数的增量量纲。5.3 LSTM 输入少了一维窗口被当成整段特征现象LSTM 跑通但 loss 死活不降或者预测结果几乎等于均值线。原因把 shape 为 (样本数, lookback) 的二维数组直接喂给了 LSTM模型把它当成二维输入缺了特征维度等于把整个窗口当成一个时刻的特征向量。解决训练前用 unsqueeze(-1) 把输入补成 (batch, lookback, 1)。定位方式很简单打印 X_train.shape第三维必须是 1如果是 2D 就补轴。5.4 序列样本整体 shuffle未来信息混进训练集现象训练 loss 异常低测试集指标却很差且换一个 shuffle 种子结果差距很大。原因如果在构造滑窗之前把原始序列整体打乱窗口内容跨越了时间顺序未来值被当成了历史值。解决shuffle 只作用于滑窗样本集合窗口内部的顺序必须保留原始时间顺序。也就是先 make_windows 得到 X/y 之后再 shuffle不能在 load_series 之后直接打乱数据。5.5 随机种子没固定模型对比失去意义现象同一套超参数LSTM 跑两次 RMSE 差 20% 以上结论根本没法写进报告。原因PyTorch 的权重初始化和 DataLoader 的数据打乱都带随机性没固定种子时每次实验都是新开局。解决训练前固定 np.random.seed、torch.manual_seedDataLoader 也指定 generator。报告里写清 seed 值别人按同样参数复现才能对得上数字。这五条基本覆盖了这套资源里最容易翻车的环节。每一条都是我先跑出错误结果、再回去读代码定位出来的修复之后这套代码才真正称得上可复现。6. 进阶技巧多步预测、差分还原与集成判定资源里的脚本默认做单步预测也就是用 lookback 长度预测未来一个点。实际项目里往往要预测未来 30、60 个点推荐递归法把预测出的值拼到窗口末尾丢掉最旧的值继续滚动预测。这套思路在 arima.py 的 --steps 参数里已经体现了LSTM 侧可以照搬def recursive_predict(model, last_window, steps, inv_scale): seq last_window.copy() preds [] model.eval() with torch.no_grad(): for _ in range(steps): x torch.tensor(seq, dtypetorch.float32).view(1, -1, 1) y_hat model(x).item() preds.append(y_hat) seq np.append(seq[1:], y_hat) return inv_scale(np.array(preds))递归法的问题在于误差会随步数累积预测 60 步时后半段基本就是一条平滑线。补救做法有两种一是直接多输出法把 LSTM 最后一层改成输出未来 N 个值损失改为多步 MSE二是做残差集成用 ARIMA 抓线性主趋势再用 LSTM 学习 ARIMA 残差里的非线性部分最后把两条预测相加。后者在这套资源上效果通常更稳因为太阳黑子序列的线性自相关部分占比很高。验证阶段除了看整体指标我还会按区间分段算 rolling RMSE。太阳黑子的活跃期和极小期表现差异很大如果模型只在极小期好、活跃期崩那对比表上的漂亮数字就是被平均掉的假象。分段指标加上预测曲线叠加图才能判断模型是真的学到了周期还是只学会了跟均值。从那以后我每次给时间序列模型下结论前都强制把「差分还原、随机种子固定、分段指标」三步走一遍再写结果这套资源我也是这么验证完才敢说能复现。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询