简介:这份PDF面向统计学、数据分析方向的高校学生与经济管理类研究者,围绕新能源汽车月度销量预测这一实际问题,完整呈现一次时间序列建模流程。文章以2014年1月至2019年5月的销量数据为样本,对序列作季节性分解与差分处理,借助ADF单位根检验确认平稳性,再依据ACF、PACF完成模型识别与定阶,最终建立ARIMA(1,0,0)(1,1,0)模型,并用2019年3至5月的实际值开展验证,相对误差控制在5%至9%之间,同时说明极值月份误差偏大的局限与短期预测的适用边界。资源为单个PDF文档,压缩包约1.11MB,篇幅精炼、结构完整,涵盖引言、模型概述、应用实例与结语,可直接作为课程论文写作或建模报告的参考范例。目前已有480人学习,适合希望掌握ARIMA建模步骤、了解新能源汽车市场趋势,并将其迁移到销售预测场景的读者研读。
1. ARIMA 预测销量:为什么“差分一次”比堆更多特征更管用
一份 2014—2019 年的月度销量数据摆到面前,大多数人的第一反应是上回归:把政策补贴、油价、竞品数量全塞进去做特征工程。但这份针对新能源汽车销量的预测研究走了一条反直觉的路——不引入任何外部变量,只靠销量序列自身的滞后值和随机误差,用 ARIMA(1,0,0)(1,1,0)模型就把 2019 年 3—5 月的预测相对误差压到了 9%、5%、6%。这里的关键动作不是建模,而是差分:一次季节差分把带趋势、带周期波动的非平稳序列“压平”成平稳序列,后面所有自回归和移动平均才有意义。搞懂差分到底改变了序列的什么统计性质、为什么 d 和 D 要分开计、定阶时 ACF 和 PACF 各自在看什么,才是这套方法能 work 的底层原因。这也是时间序列预测里最容易翻车、又最值得先搞明白的一段。
2. 平稳性:差分运算到底把序列的哪一部分“减”掉了
2.1 非平稳序列为什么不能直接喂给自回归
ARIMA 的自回归项本质上是拿 $y_{t-1}, y_{t-2}, \dots$ 去线性拟合 $y_t$。这个操作隐含一个前提:序列的均值、方差、自协方差不随时间平移而改变,也就是弱平稳。一旦序列带明显上升趋势,均值随时间漂移,同一个滞后系数在序列前段和后段拟合出的含义完全不同,最小二乘估计出来的参数就不具备一致性——通俗说,模型学到的“规律”其实是被趋势偷换过的伪相关。
新能源汽车销量恰恰是典型的非平稳序列:6 年区间内整体上升趋势极其明显,同时叠加每年 2—3 月淡季、10 月至次年 1 月旺季的季节波动。原论文先对异常离散值做移位水平处理,再做差分,正是为了先把这两层“随时间变的成分”剥离掉,让剩下的部分满足平稳性要求,再交给 ARIMA 建模。
2.2 普通差分与季节差分的分工
这里必须把 d 和 D 拆开看,因为它们是两个作用在不同周期尺度上的减法:
- 普通差分 d:$y't = y_t - y{t-1}$,消除的是整体趋势(Trend)。月度销量逐月抬升的那条斜线,被这一步减掉。
- 季节差分 D:$y't = y_t - y{t-s}$,s 为季节周期(月度数据 s=12),消除的是固定周期上的重复模式。每年同一个月份的“旺季基数”被这一步减掉。
本案例最终定为 (1,0,0)(1,1,0):小写 d=0 表示普通差分次数为 0,大写 D=1 表示做了一次季节差分。这个选择不是拍脑袋,而是先做了一次差分观察平稳性、再用 ADF 单位根检验确认新序列符合平稳性要求之后倒推出来的。ADF 检验的原假设是“存在单位根(非平稳)”,只有检验统计量落到拒绝域,才敢往下定阶。
提示:d 和 D 的取值要用检验说话,不要凭序列图“看起来平了”就定。图上看平可能只是方差被压缩,均值结构未必稳。
2.3 用代码复现“差分—检验”这一步
SPSS 里点两下就出结果,但理解机制最好自己跑一遍。下面这段用经典的时间序列思路复现差分与 ADF 检验的判定链路:
import numpy as np import pandas as pd from statsmodels.tsa.stattools import adfuller # sales: 月度销量序列,索引为月度时间戳,按时间升序 # 第一步:季节差分,消除 12 个月周期上的重复模式 sales_seasonal_diff = sales.diff(12).dropna() # 第二步:对季节差分后的序列再做普通差分,消除残余趋势 sales_final = sales_seasonal_diff.diff(1).dropna() def adf_report(series, name): # adfuller 返回统计量、p 值、滞后阶数等;p 值越小越倾向拒绝“非平稳” stat, p_value, used_lag, nobs, critical, _ = adfuller(series, autolag="AIC") print(f"{name}: ADF={stat:.4f}, p={p_value:.4f}, lag={used_lag}") for level, val in critical.items(): print(f" 临界值 {level}: {val:.4f}") return p_value # 对照实验:原序列 vs 差分后序列 adf_report(sales, "原始序列") adf_report(sales_seasonal_diff, "季节差分后") adf_report(sales_final, "季节差分+一阶差分后")代码后的逻辑说明:diff(12)对应 D=1 的季节差分,diff(1)对应 d=1 的普通差分;autolag="AIC"让检验自动按信息准则选滞后阶数,避免人为指定滞后带来的偏差。三个adf_report的输出构成一条证据链——只有当差分后序列的 p 值显著小于 0.05、且检验统计量低于各显著性水平的临界值,才有资格进入下一步定阶。案例中原始序列明显非平稳,季节差分后趋稳但仍带趋势,加上一阶差分后通过检验,这与论文中“一次差分后逐渐表现出平稳性基本特征”的叙述一致,只是论文最终在模型里把 d 取作 0、D 取作 1,说明其平稳化主要由季节差分承担。
3. 定阶:p、q 与 P、Q 分别在拟合什么
3.1 ACF 与 PACF 的分工不是“看图猜”
定阶的核心工具是自相关函数 ACF 和偏自相关函数 PACF。很多人把它们当成两个图形去“目测拖尾截尾”,但真正要理解的是它们在剔除什么:
- ACF衡量 $y_t$ 与 $y_{t-k}$ 的总体相关性,但它把中间所有滞后路径的影响都算进去了,所以哪怕真实阶数只有 1,ACF 也可能在 k=2、3 处仍有非零值。
- PACF在控制住 $y_{t-1} \dots y_{t-k+1}$ 之后,单独看 $y_{t-k}$ 对 $y_t$ 的净影响。它才是判断自回归阶数 p 的直接依据。
经验法则:PACF 在 k 阶后截断,提示 AR 阶数为 k;ACF 在 k 阶后截断,提示 MA 阶数为 k。论文中“按 ACF 和 PACF 分析原理开展拟合,最后取 p=1, q=0”,说明序列的偏相关在 1 阶后基本落入置信带,而移动平均项没有显著贡献,于是 q 归零。这不是玄学,是净相关性的直接读数。
3.2 六个参数的一次性拆解
ARIMA 的季节形式写成 $(p,d,q)(P,D,Q)_s$,六参数各管一段,混淆大小写是最常见的理解障碍。用一张表把职责钉死:
| 参数 | 含义 | 作用对象 | 本例取值 |
|---|---|---|---|
| p | 非季节自回归阶数 | 相邻月份滞后值 | 1 |
| d | 非季节差分次数 | 整体趋势 | 0 |
| q | 非季节移动平均阶数 | 相邻月份随机误差 | 0 |
| P | 季节自回归阶数 | 跨年同月滞后值 | 1 |
| D | 季节差分次数 | 年度周期模式 | 1 |
| Q | 季节移动平均阶数 | 跨年同月随机误差 | 0 |
本例 (1,0,0)(1,1,0) 的解读是:用上一个月销量的自回归项,加上去年同月销量的季节自回归项,配合一次季节差分,不含移动平均成分。这种稀疏结构在样本只有几十个月的场景下反而是优点——参数越少,过拟合风险越低,外推越稳。
3.3 拟合优度要看两个 R 方,而不是一个
论文报告了两个关键指标:平稳 R 方 0.538,考虑季节变动的整体 R 方 0.932。这两个数放在一起看才有意义。整体 R 方高,很大程度上是因为季节成分本身解释了大部分波动;平稳 R 方只统计差分后残差部分的解释力,0.538 说明在剥掉趋势和季节之后,模型对剩余波动的刻画只是中等水平。
注意:整体 R 方漂亮不等于模型强。做时间序列时,如果只报整体 R 方,很容易把“季节规律好学”误当成“模型预测准”。
4. 预测窗口:为什么超过 3 个月就不该信
4.1 “近大远小”效应的统计来源
论文明确划了一条线:只预测最近 3 个月,超出范围的结果不具预测意义。这条线的依据是时间序列的“近大远小”效应——随着预测步长 h 增加,预测方差单调增大。ARIMA 的预测区间宽度随 h 扩张,不是实现缺陷,而是模型结构决定的:每一步外推都把上一步的预测值当作已知输入,误差被逐层累积放大。步长越长,累积的误差项越多,置信区间越宽,点预测的信息量越低。
这与案例中“预测时间如果超过要求,精度会有一定程度降低”的判断完全对应。3 个月不是拍出来的经验数字,而是在该样本量级下、让预测区间仍具实用价值的窗口上限。
4.2 相对误差的三个读数说明了什么
论文用 2019 年 3—5 月做验证,实际销量 12.6、9.7、10.1 万辆,预测值 11.5、9.2、9.5 万辆,相对误差 9%、5%、6%。三个数字里,3 月误差最大。回看拟合结果,论文自己点出了原因:2018 年 12 月销量高达 22.5 万辆,最低月份仅 3.4 万辆,极值月份把模型的参数拉偏,导致个别时段误差偏大。
这暴露了纯时间序列方法的一个结构性短板:它只学历史自身的模式,对政策突变、补贴退坡这类外生冲击没有感知通道。极值不是噪声,是真实发生过的结构变化,但 ARIMA 会把它当成可被平滑的正常波动。这也解释了为什么论文在结语里提到“政策改变必然造成销量改变,主要通过更新数据实现对预测结果的更新”——用滚动更新数据来间接吸收外生冲击,是这套方法在现实中的补救手段。
4.3 滚动重估的实现骨架
既然靠更新数据来维持时效,那“滚动重估”就不是可选优化,而是方法论的一部分。下面这段展示按固定窗口滚动重估的骨架:
from statsmodels.tsa.statespace.sarimax import SARIMAX def rolling_forecast(series, order, seasonal_order, horizon=3, window=48): """ series: 完整月度销量序列 order: (p, d, q) seasonal_order: (P, D, Q, s) horizon: 每次外推步数,本例取 3 window: 每次重估使用的历史窗口长度 """ preds = [] # 滚动推进:每次用最近 window 个月重估,再预测未来 horizon 个月 for end in range(window, len(series) - horizon + 1): train = series.iloc[end - window:end] model = SARIMAX( train, order=order, seasonal_order=seasonal_order, enforce_stationarity=False, enforce_invertibility=False, ) fit = model.fit(disp=False) # 只取第一个外推点,避免长步长误差累积 preds.append(fit.forecast(steps=1).iloc[0]) return pd.Series(preds, index=series.index[window:len(series) - horizon + 1])逻辑说明:window控制每次重估回看多少个月,太长会把过时结构带进来,太短则参数估计不稳;horizon与论文的 3 个月窗口对应,但代码里每次只取第一步预测,是更保守的做法——如果要严格复现论文的 3 步外推,把steps=1改成steps=horizon并只保留最后一组即可。enforce_stationarity=False是因为差分已经承担了平稳化职责,不必让状态空间再强行约束,否则容易在样本边缘报收敛问题。
5. 常见问题与排查:这几处最容易翻车
5.1 差分次数靠目测定,ADF 检验形同虚设
现象:序列图看着平了就取 d=1,模型跑出来 R 方不低,但换一段数据预测就崩。原因:图形判断只能看均值,看不出单位根是否真的被消除,方差结构可能仍在漂移。解决:每次差分后强制跑 ADF,把检验统计量和临界值一起记录,不过检验不进入下一步;同时保留差分前后的对照,防止过度差分把有效信号减没。
5.2 把整体 R 方当模型能力的唯一证据
现象:整体 R 方 0.93,汇报时信心满满,实际预测误差却接近 10%。原因:整体 R 方混入了季节成分的解释力,平稳 R 方才反映差分后残差的拟合水平,本例后者只有 0.538。解决:两个指标并列报告,并以滚动外推的实际相对误差作为最终判据,而不是拿拟合优度替代预测精度。
5.3 极值月份不做处理直接进模型
现象:个别月份销量异常高或异常低,模型在这些时段预测误差明显放大。原因:极值会把自回归系数和季节因子拉偏,模型把它当正常波动平滑掉。解决:先按移位水平处理异常离散值,再差分;对确认由政策或一次性事件造成的极值,在建模前标注并做稳健化处理,而不是简单删点。
5.4 预测步长不设上限,外推越远越敢报
现象:把 12 个月后的点预测当结论用,置信区间宽到没有实际意义。原因:忽略了预测方差随步长单调扩张的结构性事实。解决:明确设定 3 个月的有效窗口,超出部分只作趋势参考不作决策依据;靠滚动更新数据来维持时效,而不是靠拉长单次外推距离。
5.5 只报点预测,不报置信区间
现象:给出一个精确到小数点的销量数字,使用方误以为是确定值。原因:点预测丢掉了不确定性信息,而 ARIMA 恰恰能输出预测区间。解决:预测值必须带上下置信限,尤其在使用方要据此排产或定策略时,区间比点值更有决策价值。
6. 设计取舍:为什么“简单模型 + 短窗口”在这个场景里是理性选择
把这份研究放回它的约束条件里看,ARIMA(1,0,0)(1,1,0)的选择其实是一次相当克制的取舍。样本只有 2014 年 1 月至 2019 年 5 月共几十个月度观测点,特征维度一旦往上堆,参数估计的方差会迅速吃掉偏差带来的收益;而新能源汽车销量又恰恰处在一个政策强驱动、结构快速变化的阶段,任何用历史外生变量拟合出的系数都可能在下一个政策节点失效。于是研究者选择了参数最少、可解释性最强的结构:只吃序列自身的时间依赖,用季节差分吸收周期,用一阶自回归捕捉短期惯性,剩下的交给滚动更新去追。
这套取舍的代价也很清楚。纯时间序列没有外生变量的入口,政策突变只能靠“更新数据”被动吸收,滞后性不可避免;极值月份会拉偏参数,导致个别时段误差放大到 9%;3 个月的有效窗口意味着它只能服务短期排产参考,撑不起中长期战略推演。论文在结语里提到“下一步可考虑组合多种方法预测”,本质上就是在承认单一 ARIMA 的信息边界。
但如果目标是“给有关部门和厂商一个短期、可复现、不依赖大量外部数据的趋势参考”,这个边界的另一面就是优势:模型轻、训练快、每次重估成本低,滚动更新的工程实现只需要几十行代码。相比之下,一个特征堆到几十维、每次重训要跑几小时的复杂模型,在只有几十个样本点的场景里,过拟合风险和运维成本都更不划算。
要验证这套方法在你自己数据上是否成立,我建议按三步走:先用 ADF 检验确认差分后的平稳性是否真的达标;再用滚动外推而非单次拟合计实际相对误差;最后把预测区间和点预测一起交给使用方,让不确定性可见。三步里任何一步偷懒,结论的可信度都会打折。
我自己的血泪经验是:早年做类似预测时,看到整体 R 方 0.9 就敢往外报一年后的数字,结果政策一调整,预测曲线和实际销量直接分叉,被使用方追问时才发现自己连置信区间都没输出。从那以后,我每次做时间序列预测,都强制走一遍“ADF 检验—滚动外推—区间报告”的流程,哪怕模型再简单也不跳过。希望这套拆解能帮你在拿到这份资源时,不只看它预测了什么,更看懂它为什么只能预测这么远、以及这个边界背后的统计必然性。
本文还有配套的精品资源,点击获取