news 2026/9/28 12:57:35

Python ARIMA时间序列销量预测:从平稳性检验到滚动预测实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python ARIMA时间序列销量预测:从平稳性检验到滚动预测实战

简介:这份资源是面向Python数据分析初学者、毕业设计及课程设计学生的ARIMA时间序列销量预测完整方案,帮助解决从数据平稳化处理、模型定阶到预测检验的全流程建模问题。包内共16个文件,以py脚本、png图表、zbak备份、xls与xlsx数据表及md说明为主,压缩包约255KB,涵盖建模代码、销量时序图、差分后自相关与偏相关图、上线效果图等关键素材。资源采用每月上中下旬三次预测策略,将月上旬与中旬实际销量作为先验知识,提升当月预测精度,并借助statsmodels完成窗口选择、自动定阶与平稳性检测。目前已有78人学习下载,适合需要完整赛题方案、可运行代码与图表参考的读者,便于快速复现实验、理解ARIMA建模思路并完成论文或作业撰写。

1. 销量预测这件事,为什么 ARIMA 依然是绕不开的起点

电商大促前两周,运营把过去 18 个月的日销量表甩过来,问下个月能卖多少。你打开一看,数据有缺失、有促销尖峰、有春节断崖,第一反应可能是上 LSTM。但真实情况是:样本量只有五百多行,特征工程还没做,业务方明天就要一个能解释的区间。这时候 ARIMA 反而是最稳的选择——它不需要大量数据,参数有明确的统计含义,残差可以检验,预测区间能直接给业务方看。

Python 做 ARIMA 时间序列销量预测模型,核心链路其实就四步:把销量整理成带时间索引的序列、做平稳性检验和差分、定阶拟合、滚动预测并评估。这套流程在 statsmodels 里都有现成实现,难点不在写代码,而在每个环节的参数判断和边界处理。这篇文章面向两类人:一类是刚学完 Python 基础、想找一个完整数据分析项目练手的;另一类是已经在做销量预测、但模型效果不稳定想回头补统计基础的。下面按真实落地顺序拆开讲,每一步都给可复现的代码和参数说明。

2. 数据准备与平稳性:销量序列能不能直接喂给 ARIMA

2.1 销量数据的三个硬性要求

ARIMA 对输入序列有隐含假设,很多人翻车就翻在这里。第一,时间索引必须等间隔。日销量就是每天一条,如果某天没卖出东西就缺行,必须补零而不是跳过,否则差分后的间隔就乱了。第二,序列要按时间升序排列,索引最好是 pandas 的 DatetimeIndex,这样 resample 和 shift 才不会出错。第三,单条序列长度建议不少于 50 个观测点,低于这个量级参数估计的方差会大到没法用。

我一般拿到原始表先做三件事:解析日期列、按日期聚合去重、用 asfreq 补齐缺失日期。补齐后缺失的销量填 0 还是插值,要看业务含义——零售日销缺记录通常是当天没交易,填 0 合理;如果是传感器采集缺失,才考虑插值。

import pandas as pd import numpy as np # 原始数据:date 列是字符串,sales 是当日销量 df = pd.read_csv("sales.csv", parse_dates=["date"]) df = df.sort_values("date").drop_duplicates("date") # 设为时间索引,补齐缺失日期 s = df.set_index("date")["sales"].asfreq("D") # 缺记录按业务含义填 0 s = s.fillna(0).astype(float) print(s.index.freq) # <Day>,确认频率已识别 print(len(s), s.isna().sum())

这段代码的关键在 asfreq("D"),它把不连续的日期索引强制变成每日连续,缺失位置引入 NaN,再由 fillna(0) 决定填充策略。parse_dates 保证 date 是 datetime 类型,否则 set_index 后频率推断会失败。drop_duplicates 防止同一天多条记录导致索引重复,重复索引在后续差分时会直接报错。

2.2 平稳性检验:ADF 怎么看、p 值多大才算稳

ARIMA 的 I 就是差分阶数,差分几次取决于序列平稳性。判断平稳性最常用 ADF 检验,原假设是「序列存在单位根,即不平稳」。p 值小于 0.05 就拒绝原假设,认为平稳。但实操里不能只看 p 值,还要看检验统计量和临界值的关系,以及序列图有没有明显的趋势或季节波动。

from statsmodels.tsa.stattools import adfuller def adf_report(series, name="series"): result = adfuller(series.dropna(), autolag="AIC") print(f"{name} ADF统计量: {result[0]:.4f}") print(f"{name} p值: {result[1]:.4f}") for k, v in result[4].items(): print(f" 临界值 {k}: {v:.4f}") return result[1] p0 = adf_report(s, "原始销量") s_diff1 = s.diff().dropna() p1 = adf_report(s_diff1, "一阶差分")

autolag="AIC" 让 statsmodels 自动选择滞后阶数,比手动指定 maxlag 更省事。如果原始序列 p 值大于 0.05,做一阶差分再检验;一阶差分还不稳就做二阶。但差分不是越多越好,每差一次就丢一个观测点,而且过差分会让序列方差变大、引入负相关。销量数据一般一阶差分就够,带明显年度周期的才考虑季节差分。

注意:ADF 对结构性突变很敏感。如果序列中间有促销导致的水平跳变,ADF 可能误判为不平稳,这时候要先做突变点处理或分段建模,而不是无脑差分。

3. 定阶与拟合:p、d、q 三个参数到底怎么定

3.1 用 ACF 和 PACF 图做初步定阶

d 由上一章的差分次数确定,剩下 p 和 q 看自相关函数 ACF 和偏自相关函数 PACF。经验规则是:ACF 拖尾、PACF 截尾,用 AR(p),p 取 PACF 最后一个显著非零的滞后阶;ACF 截尾、PACF 拖尾,用 MA(q),q 取 ACF 最后一个显著滞后;两个都拖尾,用 ARMA(p,q),这时候图上看不出来,得靠信息准则搜。

import matplotlib.pyplot as plt from statsmodels.graphics.tsaplots import plot_acf, plot_pacf fig, axes = plt.subplots(2, 1, figsize=(10, 6)) plot_acf(s_diff1, lags=30, ax=axes[0]) plot_pacf(s_diff1, lags=30, ax=axes[1], method="ywm") plt.tight_layout() plt.savefig("acf_pacf.png", dpi=120)

lags 一般取序列长度的十分之一到四分之一,日销量五百条取 30 到 50 都行。method="ywm" 是偏自相关的估计方法,样本量不大时比默认方法稳定。看图时关注蓝色置信带以外的柱子,带内的小波动不用管,否则容易过拟合。

3.2 网格搜索加 AIC 定阶,比肉眼靠谱

图只能给个范围,真正定阶我习惯用网格搜索配合 AIC。AIC 同时惩罚拟合优度和参数个数,值越小越好。statsmodels 的 ARIMA 在拟合失败时会抛异常,所以循环里要 try 住,把不收敛的组合跳过。

import warnings from statsmodels.tsa.arima.model import ARIMA warnings.filterwarnings("ignore") best_aic, best_order = np.inf, None for p in range(0, 4): for q in range(0, 4): try: model = ARIMA(s, order=(p, 1, q)) res = model.fit() if res.aic < best_aic: best_aic, best_order = res.aic, (p, 1, q) except Exception: continue print("最优阶数:", best_order, "AIC:", round(best_aic, 2))

order 里的 d 固定为 1,因为前面已经确认一阶差分平稳。p 和 q 搜到 3 基本够用,再大容易过拟合且训练变慢。fit() 默认用最大似然,数据量大时可以加 method_kwargs 控制优化器。搜完之后不要只看 AIC,还要把最优模型的残差拿出来做白噪声检验,残差还有自相关说明阶数没定够。

3.3 拟合结果怎么读,哪些参数必须看

拟合完的 summary 信息量很大,但新手容易只看 AIC。必须看的还有三项:系数的显著性(P>|z| 小于 0.05)、残差的 Ljung-Box 检验 p 值(大于 0.05 说明残差接近白噪声)、以及根是否在单位圆外(保证模型平稳可逆)。

res = ARIMA(s, order=best_order).fit() print(res.summary()) from statsmodels.stats.diagnostic import acorr_ljungbox lb = acorr_ljungbox(res.resid, lags=[10], return_df=True) print(lb)

如果某个系数不显著,可以考虑去掉对应阶数重新拟合。Ljung-Box 的 lags 取 10 或 20,p 值小于 0.05 说明残差还有结构没被模型抓住,需要加阶或换模型。残差图也要看一眼,有没有明显的异方差或离群点,这些都会影响预测区间的可靠性。

4. 预测与评估:滚动预测才是真实场景的照妖镜

4.1 静态预测和滚动预测的区别

很多人拟合完直接 forecast(30) 就交差了,这是静态预测,用的是训练集末尾的信息外推。真实业务里模型是每天更新的,所以评估必须用滚动预测:每次用历史数据预测下一天,然后把真实值加进历史再预测下一天。这样得到的误差才反映上线后的表现。

train_size = int(len(s) * 0.8) train, test = s[:train_size], s[train_size:] history = list(train) preds = [] for t in test: model = ARIMA(history, order=best_order).fit() yhat = model.forecast()[0] preds.append(yhat) history.append(t) # 把真实值并入历史,滚动前进 preds = pd.Series(preds, index=test.index)

这段循环每步都重新拟合,计算量大但最接近真实。如果数据很长,可以改成固定参数只更新状态,但销量预测数据量通常不大,重拟合完全扛得住。history.append(t) 用的是真实值而不是预测值,这叫一步滚动,评估的是模型在已知前一天真实销量后的预测能力。

4.2 三个评估指标和它们的适用场景

MAE、RMSE、MAPE 是最常用的三个。MAE 直观,单位跟销量一致;RMSE 对大误差惩罚重,关心极端偏差时用它;MAPE 是百分比,跨品类对比方便,但销量接近 0 时会爆炸,这时候改用 sMAPE 或直接看 MAE。

from sklearn.metrics import mean_absolute_error, mean_squared_error mae = mean_absolute_error(test, preds) rmse = np.sqrt(mean_squared_error(test, preds)) mape = np.mean(np.abs((test - preds) / test.replace(0, np.nan))) * 100 print(f"MAE={mae:.2f} RMSE={rmse:.2f} MAPE={mape:.2f}%")

test.replace(0, np.nan) 是为了避开除零,代价是 MAPE 会忽略真实值为 0 的点,所以报告 MAPE 时要说明剔除了多少点。评估完把预测值和真实值画在一张图上,肉眼看一下相位有没有滞后、尖峰有没有被削平,这比单看数字更能发现问题。

4.3 预测区间:给业务方的后悔药

点预测不够用,业务方要的是「大概在什么范围」。ARIMA 的 get_forecast 能直接给置信区间,宽度随预测步长增加而变宽,这符合直觉——预测越远越不确定。

forecast_res = res.get_forecast(steps=30) mean = forecast_res.predicted_mean ci = forecast_res.conf_int(alpha=0.05) # 95% 区间 print(mean.head()) print(ci.head())

alpha=0.05 对应 95% 置信区间,要 90% 就设 0.1。区间宽度受残差方差影响,如果残差有异方差,区间会失真,这时候可以考虑对销量取对数再建模,预测完再指数还原。

5. 避坑与排查:销量预测里最常见的五个翻车现场

5.1 现象:预测曲线整体平移,系统性偏高或偏低

原因通常是差分还原时漏掉了原始水平。ARIMA 建模的是差分后的序列,预测值需要累加回原始尺度,statsmodels 的 forecast 会自动处理,但如果你手动做了差分又手动还原,很容易漏掉最后一个训练值的基准。解决方法是直接用原序列拟合、让模型内部处理差分,或者手动还原时确认累加起点是训练集最后一个真实值。

5.2 现象:AIC 很小但预测一塌糊涂

这是过拟合的典型。p 或 q 定得太大,模型把训练集的噪声也学进去了,样本外就崩。排查方法是看残差 Ljung-Box 是否通过、系数是否显著,以及把 p、q 限制在 3 以内重搜。销量数据信噪比低,阶数宁小勿大。

5.3 现象:遇到促销尖峰,预测完全跟不上

ARIMA 是线性模型,对突发尖峰没有外生解释能力。如果促销有规律,可以加季节项或 SARIMA;如果促销时间不固定,应该把促销标记作为外生变量,改用 SARIMAX 的 exog 参数。硬用 ARIMA 拟合尖峰只会让残差方差变大,拖累整体预测。

5.4 现象:MAPE 高得离谱,检查发现真实值有 0

销量为 0 的天数不少时,MAPE 会被除零放大。解决方法是改用 MAE 或 sMAPE,或者在计算前过滤掉真实值为 0 的点并说明。不要为了指标好看去改数据,那是在骗自己。

5.5 现象:模型每次跑结果都不一样

ARIMA 的优化器有随机初值,数据量小或阶数高时可能收敛到不同局部最优。解决方法是固定随机种子、多跑几次取 AIC 最小的,或者换用更稳定的优化方法。如果结果波动很大,说明数据本身信息量不足,该考虑加特征或换模型了。

6. 把 ARIMA 用稳的一个习惯:残差监控与滚动重训

模型上线不是终点。我自己的习惯是每次预测后把残差存下来,按周看残差的均值和方差有没有漂移。销量预测最怕的是业务模式变了但模型没跟着变,残差监控就是最便宜的报警器。具体做法是维护一个残差队列,用滚动窗口算残差的标准差,超过历史分位数就触发重训。

# 残差监控:滚动窗口标准差超过阈值就告警 resid_series = pd.Series(res.resid) roll_std = resid_series.rolling(14).std() threshold = roll_std.quantile(0.95) if roll_std.iloc[-1] > threshold: print("残差波动异常,建议重新定阶或重训")

rolling(14) 是两周窗口,阈值取历史 95 分位,这两个参数按业务节奏调——日销用 14 天,周销用 8 周。重训频率不用太高,数据量小的时候每月一次就够,大促前手动触发一次。

另一个实用技巧是给预测值加一个简单的偏差校正。滚动预测跑一段时间后,统计预测值和真实值的平均偏差,如果系统性偏高就减掉这个偏差。这不是什么高级方法,但在业务侧往往比调模型参数见效快。

最后说个我踩过的坑:早期我总想把所有品类用一个模型批量跑,结果每个品类的平稳性和周期都不一样,参数根本没法统一。后来改成按品类聚类、分组定阶,工作量大了但效果稳了。ARIMA 不是万能锤,它适合的是单序列、中短周期、有统计规律可循的销量预测。数据够多、特征够丰富的时候,LSTM 那类模型确实有优势,但前提是你得先把 ARIMA 这套基线跑通,不然连模型有没有变好都判断不了。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 12:56:53

Oracle NULL防坑指南:从三值逻辑到NVL、聚合排序与数据同步

NULL这个家伙&#xff0c;我愿称之为Oracle里最防不胜防的坑。前两天一个朋友发来一条SQL&#xff0c;说月度报表统计人数莫名其妙少了一大截&#xff0c;我扫了一眼就发现问题了&#xff1a;WHERE条件里写了NOT IN&#xff0c;子查询结果里带了一个NULL&#xff0c;于是整张表…

作者头像 李华
网站建设 2026/9/28 12:54:41

UltraScale+ GTH DRP接口实战:时序、地址映射与Verilog控制器实现

1. 为什么GTH的DRP接口值得单独拎出来讲搞过UltraScale系列FPGA高速收发器的同行都清楚&#xff0c;GTH这玩意儿功能强归强&#xff0c;但配置项多到让人头皮发麻。平时我们用IP核向导&#xff08;Wizard&#xff09;点点鼠标就能生成一个能跑的收发器&#xff0c;大部分场景确…

作者头像 李华
网站建设 2026/9/28 12:53:50

Android 13多路录音实战:AudioRecord 6通道PCM采集与拆分

1. 多路录音到底难在哪&#xff1a;从AudioRecord的底层逻辑说起Android录音这件事&#xff0c;看起来简单——调个AudioRecord&#xff0c;传个AudioFormat&#xff0c;startRecording()就完事了。但一旦你需要的不是"一路混音后的立体声"&#xff0c;而是"同时…

作者头像 李华
网站建设 2026/9/28 12:53:11

卡口过车数据实时流量预测:LSTM融合模型落地与90%准确率实战

简介&#xff1a;这份资源面向智能交通、深度学习方向的学习者与开发者&#xff0c;围绕卡口实时过车数据展开交通流量预测实践&#xff0c;核心采用LSTM循环神经网络并引入融合预测思路&#xff0c;宣称准确率可达90%以上。内容覆盖时间序列预测的完整链路&#xff1a;卡口数据…

作者头像 李华
网站建设 2026/9/28 12:52:35

RK3588部署PyTorch模型:ONNX转RKNN全流程与避坑指南

1. 为什么要在RK3588上折腾PyTorch转RKNN这件事手里有一块RK3588的板子&#xff0c;跑通了Ubuntu系统&#xff0c;连上了摄像头&#xff0c;然后想把训练好的PyTorch模型塞进去跑推理——这个流程听起来顺理成章&#xff0c;但真正动手的人都知道&#xff0c;从.pt文件到板子上…

作者头像 李华