ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ARIMA销量预测实战:从平稳化定阶到每月三次滚动预测

ARIMA销量预测实战:从平稳化定阶到每月三次滚动预测 简介这份资源是面向Python数据分析初学者、统计学课程学习者及毕业设计/期末大作业需求者的一套ARIMA时间序列销量预测完整方案重点解决如何用statsmodels完成数据平稳化、模型定阶、参数估计与模型检验等建模流程。压缩包共13个文件约254KB包含4个py脚本建模与预测主逻辑、1个xls与1个xlsx数据表原始销量与预测对比结果、5个png图表时序图、差分后自相关与偏相关图、上线效果等、1个md说明及1个txt依赖清单结构紧凑便于直接运行复现。资源采用每月上、中、下旬三次预测策略将月上旬与中旬实际销量作为先验知识提升准确率并配有requirements.txt与sales.py入口方便快速跑通。目前已有2053人学习下载适合作为课程设计参考、建模练手与预测结果对照的实战素材。1. 拿到这份 ARIMA 销量预测包先搞清楚它能替你干什么电商运营月底被问「下个月能卖多少」答不上来课程设计要交一份带完整数据、能跑通、有图表的时间序列作业翻遍 GitHub 全是半成品。这份salesPredict-master就是冲着这两个场景来的它把一份真实销量表sales.xls、ARIMA 建模脚本arimaModel.py、入口sales.py、依赖清单requirements.txt和五张结果图时序图、一阶差分后的自相关/偏相关、上线效果、预测对比全打包在一起解压就能跑。技术栈是 Python statsmodels核心是 ARIMA 的平稳化、定阶、参数估计与检验。适合做毕业设计、期末大作业、课程设计的人也适合想给业务加个轻量预测模块的工程师。它不承诺预测多准但把「一条时间序列怎么从原始销量走到预测值」这条链路完整摊开了。2. 拆开目录看结构每个文件在链路里干什么2.1 目录清单与职责划分先把包解开别急着python sales.py。目录结构大致是这样salesPredict-master/ ├── data/ │ └── sales.xls # 原始销量数据按时间排列 ├── model/ │ ├── __init__.py │ ├── arimaModel.py # ARIMA 建模核心差分、定阶、拟合、预测 │ └── settings.py # 路径、参数、预测点配置 ├── test/ │ └── 某企通预测值与实际值对比_正式版.xlsx ├── pictures/ │ ├── 销量时序图.png │ ├── 一阶差分后序列自相关情况.png │ ├── 一阶差分后序列偏相关情况.png │ ├── 上线效果.png │ └── 销量预测测试情况.png ├── sales.py # 程序入口 ├── requirements.txt └── README.mddata/sales.xls是唯一的数据源所有建模都从它读。model/arimaModel.py是真正干活的地方差分、ADF 检验、ACF/PACF 定阶、拟合、预测都在这里。model/settings.py把路径和预测参数抽出来改配置不用动主逻辑。sales.py只负责串流程。pictures/里那五张图不是装饰是你验证模型有没有跑对的参照物——尤其「一阶差分后自相关/偏相关」两张直接对应定阶环节。2.2 数据长什么样决定了后面怎么建模sales.xls是月度销量序列一行一个时间点。ARIMA 对数据的要求是单变量、等间隔、按时间升序。如果你的表里有多列比如多个 SKU得先拆成单列再喂进去否则 statsmodels 会报维度错误。常见做法是先用 pandas 读进来确认索引是时间类型、没有缺失值、没有重复时间点import pandas as pd # 读原始销量表指定时间列解析为 datetime df pd.read_excel(data/sales.xls, parse_dates[date]) df df.sort_values(date).set_index(date) # 按时间升序并设为索引 series df[sales].astype(float) # 只取销量列转 float print(series.head()) print(缺失值:, series.isna().sum()) print(时间间隔:, series.index.to_series().diff().value_counts().head())这段代码做三件事解析时间列、按时间排序、检查缺失和间隔。parse_dates保证时间列不是字符串set_index让后续 statsmodels 能识别时间轴diff().value_counts()看间隔是否统一——如果出现多种间隔说明数据有断月得先补全或重采样。参数上astype(float)不能省Excel 读出来常是 object 或 intARIMA 拟合时对类型敏感。2.3 依赖装不对后面全是玄学报错requirements.txt里主要是 statsmodels、pandas、numpy、matplotlib、xlrd读 .xls 用。装的时候注意版本statsmodels 不同版本ARIMA和SARIMAX的接口有差异老代码常用ARIMA新版本推荐SARIMAX。稳妥做法是建虚拟环境再装python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt如果pip install卡在 statsmodels 编译多半是缺 C 编译环境Windows 上直接装预编译 wheel 即可。装完先python -c import statsmodels; print(statsmodels.__version__)确认能导入再往下走。这一步翻车的概率比建模本身还高别跳过。3. ARIMA 建模全流程从平稳化到定阶的每一步3.1 平稳性检验与差分d 参数怎么定ARIMA 的 p、d、q 三个参数里d 是差分阶数作用是让序列平稳。原始销量序列通常有趋势或季节性不平稳直接建模会得到虚假回归。先做 ADF 检验from statsmodels.tsa.stattools import adfuller def adf_test(series, nameseries): result adfuller(series.dropna(), autolagAIC) print(f{name} ADF统计量: {result[0]:.4f}) print(fp值: {result[1]:.4f}) print(f临界值: {result[4]}) return result[1] p_original adf_test(series, 原始序列) if p_original 0.05: series_diff1 series.diff(1).dropna() # 一阶差分 p_diff1 adf_test(series_diff1, 一阶差分)ADF 的原假设是「存在单位根不平稳」。p 值大于 0.05 就不能拒绝原假设说明不平稳需要差分。autolagAIC让 statsmodels 自动选滞后阶数比手动指定稳。一阶差分后如果 p 值仍大于 0.05再差一次但 d 一般不超过 2——差太多会把序列里的有效信息也差没。pictures/一阶差分后序列自相关情况.png就是这一步的可视化结果对照着看差分后 ACF 是否快速衰减到零附近。3.2 ACF/PACF 定阶p 和 q 怎么读图差分把 d 定下来后p自回归阶数和 q移动平均阶数靠 ACF 和 PACF 图判断。规则是ACF 拖尾、PACF 截尾用 AR(p)p 取 PACF 截尾处的滞后ACF 截尾、PACF 拖尾用 MA(q)q 取 ACF 截尾处的滞后两个都拖尾用 ARMA。代码from statsmodels.graphics.tsaplots import plot_acf, plot_pacf import matplotlib.pyplot as plt fig, axes plt.subplots(2, 1, figsize(10, 8)) plot_acf(series_diff1, lags20, axaxes[0]) # 自相关 plot_pacf(series_diff1, lags20, axaxes[1]) # 偏自相关 plt.tight_layout() plt.savefig(pictures/acf_pacf.png)lags20是看前 20 个滞后点月度数据一般看 12 到 24 就够。读图时别死磕单点看整体形态ACF 在几个滞后后落进置信带蓝色区域内就算截尾。pictures/里那两张差分后的自相关/偏相关图就是标准参照。如果图上看不准用 AIC/BIC 网格搜索兜底import warnings from statsmodels.tsa.arima.model import ARIMA warnings.filterwarnings(ignore) best_aic float(inf) best_order None for p in range(0, 4): for q in range(0, 4): try: model ARIMA(series, order(p, 1, q)) result model.fit() if result.aic best_aic: best_aic result.aic best_order (p, 1, q) except Exception: continue print(最优阶数:, best_order, AIC:, best_aic)这段网格搜索把 p、q 各试 0 到 3d 固定为 1取 AIC 最小的组合。warnings.filterwarnings(ignore)是因为部分阶数会触发收敛警告不影响搜索。AIC 越小越好但别只看 AIC——阶数太高会过拟合p、q 超过 3 就要警惕。3.3 拟合、检验与预测模型能不能用看残差定好阶数后拟合然后必须做残差检验。残差应该是白噪声否则说明模型没把信息提取干净from statsmodels.stats.diagnostic import acorr_ljungbox model ARIMA(series, orderbest_order) result model.fit() print(result.summary()) # Ljung-Box 检验残差是否为白噪声 lb acorr_ljungbox(result.resid, lags[10], return_dfTrue) print(lb)result.summary()里看系数显著性P|z| 小于 0.05和 AIC。Ljung-Box 的 p 值大于 0.05 才说明残差没有自相关模型合格。如果 p 值很小回去调阶数或加差分。预测用result.forecast(stepsn)或result.get_forecast(stepsn)后者能拿置信区间。test/某企通预测值与实际值对比_正式版.xlsx就是预测值和真实值的对照表pictures/上线效果.png是可视化跑完自己的结果可以跟它对一下量级。4. 每月分上中下旬三次预测这个策略怎么落地4.1 为什么拆成三个预测点这是这份资源里最值得抄的设计。传统做法是月初一次性预测整月误差全压在模型上。它改成每月上旬、中旬、下旬各预测一次当月销量上旬预测时用上月末为止的历史中旬预测时上旬的实际销量已经拿到作为已知值补进序列下旬同理。越往后已知信息越多预测越准。本质是把「纯外推」变成「外推 当月已实现部分」对月度销量这种受促销节奏影响大的序列特别有效。4.2 在代码里怎么实现滚动预测核心是把当月已发生的实际值拼到历史序列尾部再预测剩余部分。伪代码逻辑def predict_by_period(series, order, period_day): series: 截至当前已知的历史销量 order: ARIMA 阶数 period_day: 当前是上旬(10)/中旬(20)/下旬(月底) model ARIMA(series, orderorder).fit() # 预测当月剩余天数对应的销量这里按月粒度简化为预测当月总量 forecast model.get_forecast(steps1) pred forecast.predicted_mean.iloc[0] return pred # 上旬用上月末数据预测 pred_early predict_by_period(series_until_last_month, best_order, 10) # 中旬把上旬实际值拼进去再预测 series_mid series_until_last_month.append(pd.Series([actual_early])) pred_mid predict_by_period(series_mid, best_order, 20)关键在series_mid这一步把上旬实际销量作为新数据点追加序列变长模型重新拟合。settings.py里通常会有预测点配置比如哪几天触发改周期不用动arimaModel.py。注意每次追加后要重新拟合不能复用旧模型——参数会变。4.3 预测结果怎么评估评估指标用 MAE、RMSE、MAPE。MAPE 对销量这种正值序列最直观import numpy as np def mape(actual, pred): actual, pred np.array(actual), np.array(pred) return np.mean(np.abs((actual - pred) / actual)) * 100 print(MAPE: %.2f%% % mape(actual_list, pred_list))test/里的对比表可以直接拿来算。一般月度销量预测 MAPE 在 10% 到 20% 算可用超过 30% 要回头看数据质量或阶数。pictures/销量预测测试情况.png是现成的评估图对照自己的输出看趋势是否一致。5. 避坑与排查这几个地方最容易翻车5.1 现象ADF 检验 p 值一直大于 0.05差分也不管用原因通常是序列有季节性普通差分消不掉。月度数据常见 12 期周期一阶差分后仍有季节性自相关。解决改用季节差分series.diff(12)或者直接上 SARIMA在 order 里加季节性参数(p,d,q)(P,D,Q,12)。别硬差到 d3那样序列只剩噪声。5.2 现象模型拟合报「LinAlgError: Singular matrix」原因多是数据里有重复时间点或常量段导致矩阵奇异。解决先series series[~series.index.duplicated()]去重再检查有没有连续相同的值——如果有考虑加极小扰动或换数据段。另外 p、q 设太大也会触发网格搜索时把上限压到 3 以内。5.3 现象预测值是一条直线完全不波动原因通常是 d 设太大把序列差成了白噪声模型只能预测均值。解决回退差分阶数重新做 ADF确认 d 刚好让序列平稳即可不要多差。另一个可能是 p、q 都是 0等于没建模检查网格搜索有没有真的跑起来。5.4 现象pip install -r requirements.txt报 xlrd 相关错误原因新版 xlrd 只支持 .xls不支持 .xlsx而 pandas 读 Excel 的引擎选择跟版本绑定。解决确认sales.xls确实是 .xls 格式如果报「Excel xlsx file; not supported」说明文件其实是 xlsx 改了后缀用openpyxl读或另存为真 xls。requirements 里 xlrd 版本建议锁 1.2.0 附近。5.5 现象每月三次预测的结果反而比一次预测差原因上旬实际值样本太少拼进去后引入噪声模型被带偏。解决中旬、下旬再启用滚动上旬仍用纯历史预测或者给新拼入的值做平滑。这个策略不是无脑三次都滚得看当月已实现数据量够不够。6. 进阶把 ARIMA 当基线用残差和滚动窗口再榨一点精度跑通基础流程后真正拉开差距的是两件事滚动窗口重拟合和残差利用。固定用全历史拟合模型对近期变化反应迟钝改成滑动窗口比如只用最近 24 个月能让参数跟着最新趋势走def rolling_forecast(series, order, window24, horizon1): preds, actuals [], [] for i in range(window, len(series) - horizon 1): train series.iloc[i-window:i] # 滑动窗口训练集 test series.iloc[i:ihorizon] # 待预测点 model ARIMA(train, orderorder).fit() pred model.get_forecast(stepshorizon).predicted_mean preds.extend(pred.values) actuals.extend(test.values) return actuals, predswindow24是经验值月度数据两年窗口通常够覆盖一个完整业务周期。窗口太小比如 6参数抖动大太大比如全历史又失去适应性。跑完用 MAPE 对比固定窗口和滚动窗口选误差小的那个。另一个技巧是把 ARIMA 的残差喂给一个简单模型做二次修正。ARIMA 假设残差是白噪声但真实销量里常有促销脉冲残差里会残留结构。常见做法是对残差再跑一次 ARIMA 或阈值判断把大残差对应的月份标记为异常点预测时单独处理。这不是标准 ARIMA 流程但业务上往往有效。验证方法上别只看一张上线效果.png。自己切分训练集和测试集用滚动预测跑一遍把 MAPE、RMSE 和test/里的对比表对齐。如果差异大先查数据时间范围是否一致再查阶数是否被settings.py里的默认值覆盖了。血泪经验是每次改完settings.py里的预测点或窗口参数我都会强制重跑一遍 ADF 和残差检验确认模型没被配置改动带偏。ARIMA 这东西参数之间是联动的动一个地方d、p、q 可能都得重看。希望这份拆解帮到你少走几个我踩过的坑。本文还有配套的精品资源点击获取
返回列表