基于 ML-For-Beginners 的 ARIMA 实战任务:使用新数据集从零构建 ARIMA 模型并完成 MAPE 精度评估

发布时间:2026/9/7 5:26:34
基于 ML-For-Beginners 的 ARIMA 实战任务:使用新数据集从零构建 ARIMA 模型并完成 MAPE 精度评估 基于 ML-For-Beginners 的 ARIMA 实战任务使用新数据集从零构建 ARIMA 模型并完成 MAPE 精度评估【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners本篇技术指南围绕 ML-For-Beginners 时间序列课程7-TimeSeries第 2 课时《使用 ARIMA 进行时间序列预测》的课后任务展开任务要求读者在掌握现有 ARIMA 建模流程后自行挑选一份全新数据集、在 notebook 中构建并评估一个新的 ARIMA 模型。读完本文你将掌握一套可复制的数据选择—数据切分—缩放—SARIMAX 建模—滚动验证—MAPE 精度评估完整流程并能对照官方评分标准自查作品是否达到优秀Exemplary水平。一、任务在课程中的位置与前后置知识本任务对应的原始作业文件是课程根目录下的 7-TimeSeries/2-ARIMA/assignment.md本文讨论的关联文档是它的阿拉伯语翻译版 translations/ar/7-TimeSeries/2-ARIMA/assignment.md该页面系通过 Co-op Translator 机器翻译内容如有出入以仓库内英文原文为准。该任务位于时间序列预测课程单元的第二个课时之后前置课时7-TimeSeries/1-Introduction 讲解了时间序列预测的基本概念并加载了展示电力负荷波动的energy.csv数据集本课时7-TimeSeries/2-ARIMA/README.md 系统讲解了ARIMA自回归积分滑动平均AutoRegressive Integrated Moving Average模型的理论与完整建模代码其中还包含一段用 R 演示但概念通用的 ARIMA 入门视频本任务assignment在学完上述课时后脱离课程自带的能源数据用一份全新数据独立完成一次 ARIMA 建模全流程。因此要高质量完成本任务读者必须先熟悉课时 README 中三个核心统计学概念概念含义平稳性Stationarity数据的分布在时间平移后不发生改变。非平稳数据会因趋势产生波动需经变换后才能分析例如季节性会给数据引入波动可通过季节性差分消除差分Differencing通过移除数据中非常数趋势把非平稳数据转换为平稳数据的过程能够消除趋势与季节性的影响从而稳定时间序列的均值滞后Lag时间序列中某个观测值之前的历史取值是 ARIMA 各组成部分建模的基础二、任务拆解assignment 到底要求交付什么翻译版任务原文的Instructions部分内容凝练可拆解为四类交付物新模型 新数据在已经构建过一个 ARIMA 模型的基础上用一份全新数据构建另一个 ARIMA 模型任务原文建议从 Duke 大学公开的时间序列数据集集合中挑选——原任务以外部链接形式给出此处不再展开网址notebook 文档化将全部工作写入 notebook并做好逐格注释Annotate your work in a notebook可视化对数据本身和模型结果都要进行可视化精度评估使用MAPE平均绝对百分比误差检验模型精度。任务的Rubric评分标准表格定义了三个等级是判断作品质量最直接的标尺原表翻译对照如下标准优秀Exemplary合格Adequate需改进Needs Improvement交付物交付的 notebook 中构建、测试并讲解了一个全新的 ARIMA 模型包含可视化并明确写出精度交付的 notebook 未经注释或含有 bug交付的 notebook 不完整可以看出优秀的门槛是模型全新、经过测试、有解释、有可视化、精度被明确陈述这五者缺一不可而任务明确允许合格档出现未注释或含 bug 的作品——说明注释完整性和可运行性是拉开档次的关键分水岭。三、动手前的准备环境、依赖与公共工具函数课程把运行环境固化为 conda 配置文件位于 7-TimeSeries/2-ARIMA/solution/common/environment.yaml文件头部注释给出了三条标准命令# 创建环境 conda env create -f environment.yaml # 更新环境 conda env update -f environment.yaml # 激活并注册为 Jupyter kernel conda activate dlts python -m ipykernel install --user --name dlts --display-name Python (dlts)该文件锁定的核心依赖包括注意这是仓库教学时期固定的版本若在现代系统上重建环境遇兼容问题需在保持 API 一致性的前提下自行升级相应版本python3.6.6、pandas0.23.4、numpy1.16.2matplotlib3.0.0绘图scikit-learn0.20.3提供MinMaxScalerstatsmodels0.9.0提供SARIMAX构建 ARIMA/SARIMA 模型的核心库pip 侧额外安装pyramid-arima0.8.1提供auto_arima用于自动搜索最优模型参数课时代码还依赖两个公共工具函数它们在 7-TimeSeries/2-ARIMA/solution/common/utils.py 与根级 7-TimeSeries/common/utils.py 中各有实现load_data(data_dir)读取energy.csv把timestamp列设为索引并按小时频率重新索引为完整连续时间轴用于识别缺失时间片该数据集中无缺失对应实现位于 solution/common/utils.pymape(predictions, actuals)计算平均绝对百分比误差即对每个预测点求|预测值−真实值| / 真实值后取平均对应实现位于 solution/common/utils.py。课时 README 的完整 import 块如下新任务 notebook 应保持类似的库加载结构import os import warnings import matplotlib.pyplot as plt import numpy as np import pandas as pd import datetime as dt import math from pandas.plotting import autocorrelation_plot from statsmodels.tsa.statespace.sarimax import SARIMAX from sklearn.preprocessing import MinMaxScaler from common.utils import load_data, mape from IPython.display import Image %matplotlib inline pd.options.display.float_format {:,.2f}.format np.set_printoptions(precision2) warnings.filterwarnings(ignore) # 忽略告警保持输出整洁四、选数据一份合格的新数据应满足什么条件任务的核心约束是新数据即不能重复使用课程自带的energy.csv。可参考的候选来源是任务原文链接中 Duke 大学的时间序列数据集集合。结合课时示范数据GEFCom 2014 逐小时电力负荷数据见 7-TimeSeries/2-ARIMA/solution/data/energy.csv的特征挑选新数据时应重点考察以下五点时间可解析数据必须包含可解析为时间戳的列如日期、小时能被pd.read_csv(..., parse_dates[...])正确读取采样频率规整按固定频率小时/日/月采样为佳便于像课时那样用pd.date_range(..., freqH)重索引补齐缺失若为不规则采样需先做重采样历史长度充足至少要有能够支撑训练窗口 测试集切分的长度。课时示范取约 2 个月做测试、用 720 小时30 天做滚动训练窗口数据过短将无法复现该流程具备可建模结构肉眼观察应有趋势、季节性等可被 ARIMA/SARIMA 捕捉的模式课时数据呈现出明显的逐日季节性即用电量在一天 24 小时内的周期性波动无泄漏风险选择任务时点之前就存在的公开历史数据确保训练集时间段早于测试集时间段详见下文第五节的时序切分原则。五、参考工作流把课时的完整代码迁移到新数据上课程 README 与两份 notebook练习版 working/notebook.ipynb、参考实现版 solution/notebook.ipynb已经给出了一套端到端流程。构建新模型的任务本质上是把这套流程中的数据源替换为你的新数据其余环节保持方法论一致。下面逐步展开。5.1 加载并观察全量数据参照课时做法先加载数据并观察头部记录energy load_data(./data)[[load]] energy.head(10)再绘制 2012 年 1 月至 2014 年 12 月的全部电力负荷曲线确认时间序列的整体形态energy.plot(yload, subplotsTrue, figsize(15, 8), fontsize12) plt.xlabel(timestamp, fontsize12) plt.ylabel(load, fontsize12) plt.show()注意换成你的新数据后energy.csv、列名load、时间段等都需要同步替换为与新数据集对应的名称与取值。5.2 按时间顺序切分训练集与测试集时序建模的铁律是测试集必须覆盖比训练集更晚的时间段避免模型从未来学到信息。课时把 2014-09-01 至 2014-10-31 划给训练、11 月至 12 月留给测试示范代码如下train_start_dt 2014-11-01 00:00:00 test_start_dt 2014-12-30 00:00:00 energy[(energy.index test_start_dt) (energy.index train_start_dt)][[load]].rename(columns{load:train}) \ .join(energy[test_start_dt:][[load]].rename(columns{load:test}), howouter) \ .plot(y[train, test], figsize(15, 8), fontsize12) plt.xlabel(timestamp, fontsize12) plt.ylabel(load, fontsize12) plt.show()由于电力消耗存在强季节性、且近期日期的负荷形态最接近当前模式课时指出用一个相对较窄的时间窗口训练即可——这一点在你自己挑选的新数据上同样适用前提是你的数据也存在类似的近期相关结构。下方是课时对训练/测试切分进行可视化的参考结果即你在新数据上应产出的可视化样式注由于拟合 ARIMA 模型所用的函数在拟合过程中采用样本内验证课时明确省略了单独的验证集。随后过滤出两个集合train energy.copy()[(energy.index train_start_dt) (energy.index test_start_dt)][[load]] test energy.copy()[energy.index test_start_dt][[load]] print(Training data shape: , train.shape) print(Test data shape: , test.shape)示范数据的输出形状为Training data shape: (1416, 1)、Test data shape: (48, 1)即训练集 1416 个逐小时样本、测试集 48 个样本。5.3 用 MinMaxScaler 把数据缩放到 (0, 1)统计模型的数值稳定性对量纲敏感因此需把数据缩放到 (0, 1) 区间。关键操作是先用训练集fit_transform再用同一套缩放器transform测试集避免测试集信息泄漏进缩放参数scaler MinMaxScaler() train[load] scaler.fit_transform(train) train.head(10)课时还示范了用直方图对比原始数据与缩放后数据的分布形态energy[(energy.index train_start_dt) (energy.index test_start_dt)][[load]].rename(columns{load:original load}).plot.hist(bins100, fontsize12) train.rename(columns{load:scaled load}).plot.hist(bins100, fontsize12) plt.show()完成校准后缩放测试集test[load] scaler.transform(test) test.head()5.4 定义并拟合 SARIMAX 模型由于示范数据带有季节性24 小时周期课程使用的是SARIMA季节性 ARIMA模型通过statsmodels的SARIMAX()类实现。在 solution/notebook.ipynb 中可以看到实际调用形式order (4, 1, 0)、seasonal_order (1, 1, 0, 24)。建模前必须理解两组参数的语义p自回归部分的阶数刻画对*过去值滞后值*的回归d积分部分的差分阶数决定对序列施加多少差分以消除非平稳性q移动平均部分的阶数P、D、Q与p、d、q描述同一类关联但对应模型的季节性分量SARIMAX的seasonal_order元组第四个元素示范中为24表示季节周期长度这里是每日 24 小时。定义一个基础模型并查看拟合摘要order (4, 1, 0) seasonal_order (1, 1, 0, 24) model SARIMAX(endogtrain, orderorder, seasonal_orderseasonal_order) results model.fit() print(results.summary())results.summary()会输出一张包含对数似然示范中 Log Likelihood 为 3477.239、各系数及其显著性等内容的表格。课时提醒手工挑选最优p/d/q有一定主观性且耗时可考虑用pyramid-arima/pmdarima库的auto_arima()自动搜索见环境配置中的pyramid-arima0.8.1。5.5 用 Walk-Forward滚动验证评估模型评估时序模型不应只用单次切分测试。课时的做法是walk-forward 验证从序列起点开始在训练集上拟合模型、预测下一个时间步、与真实值对比随后把该真实值并入训练集继续重复。实践中时序模型通常在每个新数据点到来时重新训练以在每个时刻给出最优预测。效率提示课时建议保持训练窗口长度固定——每当向训练集尾部加入一个新观测就同步从开头移除一个最旧观测避免窗口无限膨胀。在开始滚动前需要先为HORIZON预测步数/预测期长度内的每一步构造测试目标列。设HORIZON 3预测未来 3 小时# Specify the number of steps to forecast ahead HORIZON 3 print(Forecasting horizon:, HORIZON, hours)随后把测试集按各步移位load1、load2分别为前 1、2 小时的目标值test_shifted test.copy() for t in range(1, HORIZON1): test_shifted[loadstr(t)] test_shifted[load].shift(-t, freqH) test_shifted test_shifted.dropna(howany) test_shifted.head(5)示范数据移位后形如timestamploadload1load22014-12-30 00:00:000.330.290.272014-12-30 01:00:000.290.270.272014-12-30 02:00:000.270.270.30接下来用滑窗在测试集长度内循环训练与预测——这是本任务 notebook 中最核心的代码块课时 README 中的完整实现为%%time training_window 720 # dedicate 30 days (720 hours) for training train_ts train[load] test_ts test_shifted history [x for x in train_ts] history history[(-training_window):] predictions list() order (2, 1, 0) seasonal_order (1, 1, 0, 24) for t in range(test_ts.shape[0]): model SARIMAX(endoghistory, orderorder, seasonal_orderseasonal_order) model_fit model.fit() yhat model_fit.forecast(steps HORIZON) predictions.append(yhat) obs list(test_ts.iloc[t]) # move the training window history.append(obs[0]) history.pop(0) print(test_ts.index[t]) print(t1, : predicted , yhat, expected , obs)循环中反复调用SARIMAX(...).fit()再forecast(stepsHORIZON)同时维护固定长度 720 的history窗口。该方法的优点是能给出模型在实践中表现的最稳健估计代价是训练了非常多个模型示范数据量小可接受但扩展到大规模数据时要权衡计算成本。滚动预测的中间输出形如2014-12-30 00:00:00 1 : predicted [0.32 0.29 0.28] expected [0.32945389435989236, 0.2900626678603402, 0.2739480752014323] 2014-12-30 01:00:00 2 : predicted [0.3 0.29 0.3 ] expected [0.2900626678603402, 0.2739480752014323, 0.26812891674127126]把全部预测结果组装成便于评估的eval_df并把缩放后的预测与真实值反变换回原始量纲以便与真实负荷直接对比eval_df pd.DataFrame(predictions, columns[tstr(t) for t in range(1, HORIZON1)]) eval_df[timestamp] test.index[0:len(test.index)-HORIZON1] eval_df pd.melt(eval_df, id_varstimestamp, value_nameprediction, var_nameh) eval_df[actual] np.array(np.transpose(test_ts)).ravel() eval_df[[prediction, actual]] scaler.inverse_transform(eval_df[[prediction, actual]]) eval_df.head()7-TimeSeries/common/utils.py中的create_evaluation_df是这段逻辑的封装实现。5.6 用 MAPE 检验模型精度MAPE平均绝对百分比误差把预测误差表达为真实值的比例公式为对每个预测点求|actual_t − predicted_t| / actual_t绝对差除以真实值再把全部预测点的取值求和后除以拟合点数 n最终以百分比呈现。数学式插图见 7-TimeSeries/2-ARIMA/images/mape.png。逐步计算多步预测中每个 horizon 的平均绝对误差if(HORIZON 1): eval_df[APE] (eval_df[prediction] - eval_df[actual]).abs() / eval_df[actual] print(eval_df.groupby(h)[APE].mean())计算单步预测t1的 MAPEprint(One step forecast MAPE: , (mape(eval_df[eval_df[h] t1][prediction], eval_df[eval_df[h] t1][actual]))*100, %)计算全部步长的整体 MAPEprint(Multi-step forecast MAPE: , mape(eval_df[prediction], eval_df[actual])*100, %)重要提醒课时示范数据得到的单步 MAPE 约 0.557%、多步 MAPE 约 1.146%是针对课程自带energy.csv的结果不应被当作你新数据模型的预期或达标数值。MAPE 越低越好例如 MAPE 为 10 意味着平均偏离 10%但不同数据集的可达精度差异很大任务评分关注的是流程完备性而非某个绝对分数。请在 notebook 中明确写出你自己模型实际测得的 MAPE。最后把预测与真实值画在同一张图上直观检查拟合质量。多步预测时课时按预测越远线条越浅越细的方式分层绘制线宽按4*pow(0.9,t)递减、透明度按pow(0.8,t)递减if(HORIZON 1): ## Plotting single step forecast eval_df.plot(xtimestamp, y[actual, prediction], style[r, b], figsize(15, 8)) else: ## Plotting multi step forecast plot_df eval_df[(eval_df.ht1)][[timestamp, actual]] for t in range(1, HORIZON1): plot_df[tstr(t)] eval_df[(eval_df.htstr(t))][prediction].values fig plt.figure(figsize(15, 8)) ax plt.plot(plot_df[timestamp], plot_df[actual], colorred, linewidth4.0) ax fig.add_subplot(111) for t in range(1, HORIZON1): x plot_df[timestamp][(t-1):] y plot_df[tstr(t)][0:len(x)] ax.plot(x, y, colorblue, linewidth4*math.pow(.9,t), alphamath.pow(0.8,t)) ax.legend(locbest) plt.xlabel(timestamp, fontsize12) plt.ylabel(load, fontsize12) plt.show()下图是课时在示范数据上得到的最终模型精度图——红粗线为真实负荷、蓝色渐细线为各步预测可作为你在新数据集上应产出的可视化基准六、对照 Rubric 的交付自查清单任务只有三档评分向优秀Exemplary冲刺时可逐条自查以下清单模型与数据维度使用了一份课程中未出现过的全新时间序列数据集模型确实为 ARIMA/SARIMA 族模型statsmodels的SARIMAX或pmdarima的ARIMA均可且不是简单复制课时参数的换数据跑一遍——若沿用课时参数请说明理由若能结合新数据的季节性周期如每日、每周周期长度设置seasonal_order会更出彩。notebook 注释与可复现性每个代码格均有 Markdown/注释说明意图对应Annotate要求数据集来源、加载方式、切分边界起止时间被明确交代notebook 可从头到尾无报错执行对应规避contains bugs档。可视化维度至少包含全量原始序列图观察趋势/季节性包含训练/测试切分可视化包含预测 vs 真实值的对比图形如上文精度图。精度维度使用 MAPE 计算精度并在 notebook 中以文字明确写出数值对应accuracy stated要求最好同时给出单步t1与多步 MAPE并可加一句对数值的解读误差约 X% 意味着平均偏离 X%。若上述项目全部完成即满足构建、测试、讲解、可视化、精度陈述五要素可判定为 Exemplary。七、延伸思考其他精度指标与自动化调参任务的核心评估指标是 MAPE但课时末尾的 Challenge 也提示时间序列模型的精度度量不止 MAPE 一种。作为锦上添花可在 notebook 中补充研究并记录诸如 MAE、MSE/RMSE、MAD 等指标与 MAPE 的适用场景差异——这将让你的讲解部分更有深度。另外若手动挑选p/d/q/P/D/Q让你感到耗时可在 notebook 中尝试环境里已配置的pyramid-arima提供的auto_arima()函数自动搜索参数再与手工参数的结果做对比以支撑你对自己参数选择的解释。整条工作流的参考实现可直接对照 7-TimeSeries/2-ARIMA/solution/notebook.ipynb练习起点则为 7-TimeSeries/2-ARIMA/working/notebook.ipynb课程同一目录下还提供了 R 与 Julia 两个语言的参考说明见 7-TimeSeries/2-ARIMA/solution/R 与 7-TimeSeries/2-ARIMA/solution/Julia可供跨语言对照学习。总而言之本任务考察的不是背出 ARIMA 的公式而是把课时方法论迁移到陌生数据上的完整工程能力——数据是否选得合理、notebook 是否自洽可复现、结论是否用 MAPE 和数据可视化支撑这三者缺一不可。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考