简介:这份PDF文档围绕ARIMA模型在新能源汽车销量预测中的应用展开,面向数据分析、统计学及汽车产业研究方向的读者,帮助解决如何用时间序列方法对月度销量进行短期预测的问题。资源包内仅含1个PDF文件,大小约1.11MB,内容为期刊论文全文,涵盖模型概述、数据来源与平稳性分析、模型识别定阶及检验、拟合预测与结果对比等完整章节。文中选取2014年1月至2019年5月的新能源汽车月销量数据,建立ARIMA(1,0,0)(1,1,0)模型,并给出2019年3月至5月的预测值与相对误差,同时讨论了季节波动、极值处误差偏大等局限。目前已有480人学习下载,适合需要参考建模流程、理解差分与ACF/PACF定阶思路,或为汽车企业战略研究寻找实证依据的读者。
1. 一份用 ARIMA 拆解新能源汽车月销量的实战文档
手里这份《基于ARIMA模型的新能源汽车销量预测.pdf》,本质上是一篇完整的时间序列建模案例,不是纯理论综述。它拿 2014 年 1 月到 2019 年 5 月的国内新能源汽车月度销量做样本,走了一遍「平稳性检验 → 季节性分解 → 差分 → 定阶 → 参数估计 → 拟合验证」的全流程,最后落到 2019 年 3 到 5 月三个月的预测对比上。适合谁看?做销量预测、市场分析、运营计划排期的从业者,以及正在学时间序列、需要一份能跑通的中文案例的学生。它最大的价值在于把 ARIMA(p,d,q)(P,D,Q)这套带季节项的模型讲得足够具体,连 SPSS 输出的平稳 R 方、Sig 值、相对误差都摆出来了,你照着能复现,也能判断它到底靠不靠谱。
2. 先搞懂 ARIMA 在销量预测里到底干了什么
2.1 从非平稳到平稳:差分这一步绕不过去
新能源汽车月销量这条曲线,你只要画出来就知道它不老实——整体往上走,每年 2 到 3 月掉下去,10 月到次年 1 月又冲上来,典型的趋势加季节双重叠加。ARIMA 的核心思路就一句话:先把这种不平稳的序列通过差分变成平稳的,再用自回归和移动平均去拟合残差结构。
文档里写得很清楚,原始序列经过一次差分后逐渐表现出平稳性特征,ADF 单位根检验也过了。这里的 d=1 就是一次普通差分,D=1 是季节差分。为什么季节差分也要做一次?因为每年同一个月份的销量模式高度相似,不做季节差分,模型会把季节波动当成随机误差,预测出来就会在淡旺季上翻车。
我一般会先画三张图再动手:原始序列图、一阶差分后的序列图、季节差分后的序列图。三张图摆在一起,d 和 D 该取几基本就有数了。文档里用的是 SPSS 的季节性分解,输出了一张季节因子序列图,这一步在 Python 里用 statsmodels 的 seasonal_decompose 也能做,效果一样。
2.2 定阶逻辑:ACF 和 PACF 怎么看
定阶是 ARIMA 里最玄学的环节,但也不是完全没章法。文档里的做法是:经过一次差分后,看 ACF(自相关函数)和 PACF(偏自相关函数)的截尾和拖尾情况,最后取 p=1,q=0,建立 ARIMA(1,0,0)(1,1,0)模型。
这里拆开说。小写 p=1 表示非季节自回归阶数取 1,q=0 表示非季节移动平均阶数取 0。大写 P=1 表示季节自回归阶数取 1,D=1 表示做了一次季节差分,Q=0 表示季节移动平均阶数取 0。合起来读就是:模型认为当前销量主要受上一期销量和去年同月销量的影响,不需要额外的移动平均项来修正。
实际操作中,ACF 如果在 q 阶后快速衰减到零附近,说明移动平均阶数可以取 q;PACF 如果在 p 阶后截尾,说明自回归阶数取 p。但真实数据很少这么干净,所以文档里也提到「按照 ACF 和 PACF 分析原理开展拟合过程」,言下之意是结合拟合效果反复试。我自己的习惯是先用 AIC 或 BIC 网格搜一遍 p 和 q 的组合,再拿 ACF/PACF 的结果做交叉验证,两边对上了才敢定。
2.3 用 Python 复现一遍建模流程
文档用的是 SPSS,但一线干活更多用 Python。下面这段代码把数据读入、差分、定阶、建模、预测串起来,你可以直接抄。
import pandas as pd import numpy as np import matplotlib.pyplot as plt from statsmodels.tsa.statespace.sarimax import SARIMAX from statsmodels.tsa.stattools import adfuller from statsmodels.graphics.tsaplots import plot_acf, plot_pacf # 读取数据:假设 csv 有两列 month 和 sales df = pd.read_csv('nev_sales.csv', parse_dates=['month'], index_col='month') series = df['sales'].asfreq('MS') # 月度频率,月初对齐 # 一阶普通差分 + 一阶季节差分(周期 12) series_diff = series.diff(1).diff(12).dropna() # ADF 检验:p 值小于 0.05 才算平稳 adf_result = adfuller(series_diff) print(f'ADF Statistic: {adf_result[0]:.4f}, p-value: {adf_result[1]:.4f}') # 画 ACF 和 PACF 辅助定阶 fig, axes = plt.subplots(2, 1, figsize=(10, 6)) plot_acf(series_diff, ax=axes[0], lags=24) plot_pacf(series_diff, ax=axes[1], lags=24) plt.tight_layout() plt.show() # 拟合 SARIMA(1,1,0)(1,1,0,12) model = SARIMAX(series, order=(1, 1, 0), seasonal_order=(1, 1, 0, 12), enforce_stationarity=False, enforce_invertibility=False) results = model.fit(disp=False) print(results.summary()) # 预测未来 3 个月 forecast = results.get_forecast(steps=3) pred_mean = forecast.predicted_mean pred_ci = forecast.conf_int() print(pred_mean)逻辑说明:diff(1)做一次普通差分消除趋势,diff(12)做一次季节差分消除年度周期。ADF 检验的 p 值如果小于 0.05,说明差分后的序列已经平稳,可以往下走。SARIMAX里的order对应小写 p,d,q,seasonal_order对应大写 P,D,Q 加周期长度。enforce_stationarity=False是为了让模型在差分后仍能正常估计,避免因为残余趋势报错。
参数怎么改:如果 ADF 检验没过,把diff(1)改成diff(2)再试;如果 ACF 在滞后 12 期还有明显尖峰,说明季节项没处理干净,检查seasonal_order里的 D 是否该取 1。预测步长steps=3对应文档里说的「最近 3 个月」,超过这个范围误差会明显放大。
3. 模型检验与预测结果:数字背后的门道
3.1 参数显著性:Sig 值和 R 方怎么读
文档里提到,AR(1)的参数估计 Sig 小于 0.05,平稳 R 方为 0.538,考虑季节变动的整体 R 方为 0.932。这三个数字要连起来看。
Sig 小于 0.05 说明自回归项系数显著不为零,模型里这个变量是有用的。平稳 R 方 0.538 衡量的是差分后序列的拟合程度,不算高,但时间序列模型里这个值能到 0.5 以上已经能用。整体 R 方 0.932 是把季节变动考虑进去后的拟合优度,接近 1,说明模型对原始销量水平的解释力很强。
这里有个容易误读的地方:整体 R 方高不代表预测准。因为销量本身在涨,模型只要抓住趋势就能拿到高 R 方,但真正考验模型的是它在淡旺季转折点的表现。文档里也承认,2018 年 12 月销量冲到 22.5 万辆,最低月份只有 3.4 万辆,极值处误差会变大。
3.2 预测验证:三个月相对误差说明了什么
文档给出的验证结果是这样的:
| 时间 | 实际销量(万辆) | ARIMA 预测值(万辆) | 相对误差 |
|---|---|---|---|
| 2019 年 3 月 | 12.6 | 11.5 | 9% |
| 2019 年 4 月 | 9.7 | 9.2 | 5% |
| 2019 年 5 月 | 10.1 | 9.5 | 6% |
三个月平均相对误差在 6% 到 7% 之间,对于月度销量预测来说属于可接受范围。但注意 3 月的误差明显大于 4 月和 5 月,为什么?因为 3 月是淡季向旺季过渡的月份,销量波动本身就不规则,模型对转折点的捕捉能力有限。
我一般会额外算一个指标:预测值和实际值的方向是否一致。如果实际在涨、预测在跌,哪怕数值误差不大,这个模型也不能用来指导备货。文档里的预测值和实际值方向一致,这点比单纯的误差百分比更有参考价值。
3.3 置信区间:别只看点预测
上面 Python 代码里forecast.conf_int()输出的是置信区间。文档里的图 3 也画了 UCL 和 LCL(上下置信限)。很多人只看预测均值,忽略区间宽度,这是典型的踩坑。
如果置信区间很宽,说明模型对这次预测没把握,你拿这个数去做生产计划就是赌。我一般会要求预测区间的上下限差距不超过均值的 30%,超过了就说明模型需要重新定阶或者加变量。文档里没有给出具体的区间数值,但从图 3 的走势看,越往后预测,区间越宽,这也印证了「超出 3 个月预测意义不大」的判断。
4. 避坑与排查:这份文档没写但你会遇到的问题
4.1 数据频率不统一导致季节周期错位
现象:用月度数据建模,但季节周期设成了 4 或者 52,模型跑出来结果完全不对。
原因:ARIMA 的季节周期 s 必须和数据频率匹配。月度数据 s=12,季度数据 s=4,周度数据 s=52。文档里用的是月度数据,所以季节差分周期是 12。
解决:建模前先确认asfreq('MS')或asfreq('M')有没有把频率设对。用 pandas 的pd.infer_freq()检查一下索引频率,不对就先重采样。
4.2 差分过度导致信息丢失
现象:ADF 检验过了,但模型拟合出来的预测值几乎是一条直线,完全跟不上波动。
原因:差分次数过多。一阶差分消趋势,二阶差分消趋势的变化率,再往上就把信号也消掉了。文档里只做了一次普通差分和一次季节差分,这是比较稳妥的做法。
解决:每次差分后都画图看一眼,如果序列已经围绕零上下波动且没有明显趋势,就不要再差了。ADF 检验通过是必要条件,不是差分越多越好。
4.3 极值月份拉高整体误差
现象:大部分月份预测误差在 5% 以内,但某一个月误差突然跳到 20% 以上。
原因:销量数据里的极端值,比如政策补贴退坡前的抢购、春节假期导致的销售停滞,这些是模型无法从历史模式中推断的。文档里也提到 2018 年 12 月销量 22.5 万辆,最低月份 3.4 万辆,极值处误差偏大。
解决:两种做法。一是对极值做平滑处理,用前后几个月的均值替换;二是引入外生变量,比如政策发布月份、节假日天数,用 SARIMAX 的exog参数传进去。文档里没做这一步,但实际工作中我建议加上。
4.4 用旧数据预测新周期导致精度下降
现象:模型在训练集上表现很好,但用来预测半年后的销量,误差越来越大。
原因:时间序列有「近大远小」效应,越靠近训练集末尾的数据对预测影响越大,越远的越弱。文档里明确说了「超出 3 个月范围的预测结果不具有预测意义」。
解决:建立滚动更新机制。每拿到一个月的新数据,就把它加入训练集,重新拟合模型,再预测下三个月。不要拿一个模型反复用一年。
4.5 忽略政策变量导致趋势判断失误
现象:模型预测销量继续上涨,但实际销量因为补贴政策调整突然下滑。
原因:ARIMA 只从历史销量数据里找规律,不知道政策什么时候变。文档结语里也承认「政策的改变必然会造成销量的改变」。
解决:把政策发布、补贴退坡、限行变化这些事件做成哑变量,作为外生变量传入模型。如果不想改模型结构,至少在解读预测结果时,手动标注哪些月份可能有政策影响,提醒决策方注意。
5. 进阶技巧:把 ARIMA 从单点预测变成滚动监控
文档里的建模流程是一次性的:拿历史数据训练,预测三个月,对比完就结束。但实际业务里,销量预测是持续动作,你需要一套滚动机制。我一般会写一个循环,每月自动更新数据、重新拟合、输出预测和误差,形成一个监控看板。
import pandas as pd from statsmodels.tsa.statespace.sarimax import SARIMAX def rolling_forecast(series, train_end, horizon=3): """ series: 完整销量序列,月度频率 train_end: 训练集截止时间字符串,如 '2019-05' horizon: 预测步长 """ train = series[:train_end] test = series[train_end:train_end + pd.DateOffset(months=horizon)] model = SARIMAX(train, order=(1, 1, 0), seasonal_order=(1, 1, 0, 12), enforce_stationarity=False, enforce_invertibility=False) results = model.fit(disp=False) pred = results.get_forecast(steps=horizon).predicted_mean # 计算相对误差 error = ((test.values - pred.values) / test.values) * 100 result_df = pd.DataFrame({ 'actual': test.values, 'predicted': pred.values, 'error_pct': error }, index=test.index) return result_df # 示例:用 2014-01 到 2019-05 训练,验证 2019-03 到 2019-05 df = pd.read_csv('nev_sales.csv', parse_dates=['month'], index_col='month') series = df['sales'].asfreq('MS') result = rolling_forecast(series, '2019-02', horizon=3) print(result)这段代码的关键在train_end参数。你把它设成'2019-02',模型就用 2019 年 2 月之前的数据训练,预测 3 到 5 月,和文档里的验证方式一致。每个月把train_end往后推一格,就能得到滚动预测结果。
参数说明:horizon=3对应文档里说的「最近 3 个月」,如果你要预测更长,把 horizon 调大,但误差会上升。order和seasonal_order沿用文档定好的 (1,1,0)(1,1,0,12),如果你换了数据集,这两个参数需要重新定阶。
还有一个技巧:把预测误差按月画成折线图。如果某个月的误差突然跳高,回去查那个月有没有政策发布、节假日异常或者数据录入错误。误差图比预测图更能暴露问题。
从那以后我每次做销量预测,都会强制走一遍「差分图 → ADF → ACF/PACF → 拟合 → 残差检验 → 滚动验证」这六步,少一步都不敢把结果交给业务方。希望帮到你。
本文还有配套的精品资源,点击获取