☰
Python ARIMA销量预测实战:从平稳性差分到模型定阶与预测
2026/10/12 12:34:15 网站建设 项目流程

简介:面向Python时间序列建模学习与课程项目实践的ARIMA销量预测资料包,包含完整数据集、模型源码与说明文档,覆盖从数据探索、平稳化处理到模型检验的完整流程,适合毕业设计、期末大作业及课程设计参考。资源以zip格式打包,共16个文件,涵盖4个py源码、5个png图表、xls/xlsx数据表、md/txt文档与zbak备份文件,整体仅255KB,目录与代码分离,结构清爽便于按模块查阅。建模思路基于statsmodels实现序列平稳化、AR/MA过程识别、自动差分定阶与参数估计,并通过窗口选择、平稳性检测辅助确定最优参数;预测采用每月上中下旬三点的滚动策略,将月上旬和中旬实际销量作为先验知识,贴合电商、零售等真实业务场景。附带销量时序图、一阶差分后自相关/偏相关图、上线效果图等关键可视化结果,以及预测值与实际值对比Excel,既可用于理解模型诊断,也便于复现实验、撰写实验报告或答辩展示。目前已有78人学习下载,适合初学者对照源码理解ARIMA各环节的实现细节。

1. 时间序列销量预测:一份能直接跑的Python ARIMA模型资源

做过销量预测的人都知道,ARIMA不是新鲜玩意,但真拿Python把这些理论落到一份能跑的数据和代码上,并且直接出预测结果,还是得费不少功夫。这份资源里面包含了完整的销量数据、模型脚本、自相关与偏相关图、上线效果图,以及一份“预测值与实际值对比”的正式版Excel,基本就是照着毕业论文或课程设计的要求搭出来的:先平稳化,再差分,再建模,再检验,最后按业务节奏输出预测。适合正在做Python毕业设计、期末大作业、课程设计的学生,也适合刚入门时间序列、想找个完整项目复现的从业者。它能让你省掉从零拼代码的时间,把精力放在理解ARIMA参数和预测策略上。

2. ARIMA的核心逻辑:平稳性与差分为什么会决定模型生死

2.1 平稳性:ARIMA建模的前提条件

ARIMA的全称是自回归积分滑动平均模型,名字里的“I”就是差分。理解这个项目之前,必须先接受一个前提:ARIMA要求输入序列是平稳的。什么叫平稳?简单说就是序列的均值、方差在时间轴上没有趋势性变化,不会整体往上飘或往下掉。销量数据天然不平稳,比如说一款产品销量从每月几千台涨到几万,这就带趋势,ARIMA直接建模会把趋势当成内在规律去拟合,预测长期结果往往会飘到不合理的区间。

判断序列是否平稳,项目里用的是常见做法:一是画图观察,二是做ADF单位根检验。statsmodels提供了adfuller函数,返回的p值如果小于0.05,就可以拒绝“有单位根”的原假设,说明序列平稳。如果发现不平稳,就做一阶差分,然后再检验。资源里的图片“一阶差分后,序列自相关情况.png”和“一阶差分后,序列偏相关情况.png”,其实就是这个流程中间态的可视化记录,能看到差分之后自相关衰减得很快,这是平稳序列的典型特征。

2.2 差分与模型定阶:从ACF/PACF到AIC自动搜索

差分之后,模型定阶就成了建模环节的关键。ARIMA模型有p、d、q三个参数,d是差分次数,通常取0或1,取太大容易过差分,导致信息丢失。p是自回归阶数,q是移动平均阶数。定阶有两种思路:第一种是看ACF(自相关图)和PACF(偏自相关图),ACF拖尾、PACF截尾就考虑AR模型,反过来考虑MA模型。资源里提供的那两张图就是干这个用的,但人眼看图存在主观判断,不同人可能定出不同阶数。

第二种思路更省事,也是这套代码里更推荐的:用AIC或BIC信息准则自动搜索。statsmodels中可以通过遍历(p, q)组合,比较每个模型的AIC值,取最小者作为最终阶数。资源里提到了“自动差分过程”,说明整个定阶环节被封装成了自动流程,这是工程上最实用的做法——不用去纠结尾巴拖到第几阶才算截尾。要注意的是,自动定阶搜索范围不能搞得太大,常见做法是p和q都从0试到5,超过5之后过拟合风险明显增加,而且训练时间会变得非常慢。

3. 复现这个销量预测项目:数据、脚本与关键参数

3.1 项目文件结构与用途

把资源解压之后,第一件事是理清文件关系。核心脚本有三个:arimaModel.py负责模型训练与预测,sales.py负责数据读取与流程编排,settings.py负责全局参数配置。data/sales.xls是原始销量数据,requirements.txt记录依赖库,test目录里是验证用的对比结果。需要注意里面有不少.zbak后缀的文件,这是代码的备份文件,不需要在运行时引用。

建议先看settings.py,这个文件如同一个总开关。拿到的资源里,settings.py通常定义了数据文件路径、差分最大次数、p和q的搜索范围、预测步数等参数。我一般会先把这些参数打印一遍,确认当前配置是“一次性预测下个月”还是“按月多次预测”。项目摘要里明确说了预测策略是“每月分上中下旬三个点预测”,所以settings.py里应该还有一个参数控制这个频率,可能是月份分段点,也可能是预测步长。

文件清单可以从这个角度整理:

文件/目录作用
settings.py全局参数,包括路径、数据源、定阶范围、预测配置
arimaModel.py封装ADF检验、差分、模型拟合、预测的ARIMA核心类
sales.py读取sales.xls,调用arimaModel,输出销量预测结果
data/sales.xls历史销量明细数据
test/测试脚本与真实预测值对比结果
*.zbak代码备份文件,参与或干扰,可忽略

3.2 从sales.xls到一阶差分序列的完整过程

要复现预测,第一步是把Excel数据读进来并转成时间序列格式。常见做法是用pandas读入数据,把月份列解析成DatetimeIndex,再把销量列转成float类型。刚拿到的数据里常见两个坑:一是Excel里的月份是“2023.1”这样的数值格式,需要手动补零;二是销量列有缺失值或零值,会影响差分和模型训练。下面这段代码是把数据读入并检查序列状态的常用写法:

import pandas as pd from statsmodels.tsa.stattools import adfuller # 读取Excel销量数据,常见字段:month, sales df = pd.read_excel('data/sales.xls') df['month'] = pd.to_datetime(df['month'].astype(str).str.replace('.', '-', regex=False)) df = df.set_index('month').sort_index() sales = df['sales'].astype(float) print(sales.head()) print('缺失值数量:', sales.isnull().sum()) # 对原始序列做ADF检验 adf_stat, p_value, _, _, _, _ = adfuller(sales.dropna()) print(f'ADF统计量:{adf_stat:.4f}, p值:{p_value:.4f}')

这段代码的逻辑是把Excel数据变成标准的pandas时间序列,然后立刻做ADF检验,判断原始序列是否平稳。输出里p值大于0.05就说明序列带趋势性,必须做差分。注意adfuller返回的是一个六元组,前两个元素是统计量和p值,后面四个包含临界值等信息,这里用不上但要去掉。缺失值处理在这里很重要,缺失值不能直接丢,因为时间序列是有顺序的,最稳妥的做法是先用插值填上,再看平稳性。

3.3 ARIMA模型训练与预测的核心代码走读

资源里的arimaModel.py封装了整个建模流程。假定它对外暴露了一个forecast类方法,接受训练序列、差分次数d、p和q搜索范围,返回未来n期的预测值。代码里常见实现是使用statsmodels.tsa.arima.model.ARIMA(新接口)或statsmodels.tsa.arima_model.ARIMA(旧接口,pandas老版本常用)。新接口在statsmodels 0.13之后成为标准,旧接口已被标记为弃用。下面是我根据这套代码逻辑整理出的核心训练函数:

from statsmodels.tsa.arima.model import ARIMA import itertools import warnings def find_best_arima(train, d=1, max_p=5, max_q=5): best_aic = float('inf') best_order = None best_model = None warnings.filterwarnings("ignore") for p, q in itertools.product(range(max_p + 1), range(max_q + 1)): try: model = ARIMA(train, order=(p, d, q)) fitted = model.fit() if fitted.aic < best_aic: best_aic = fitted.aic best_order = (p, d, q) best_model = fitted except Exception: continue print(f'最佳阶数: {best_order}, AIC: {best_aic:.2f}') return best_model # 以180天销量作为训练数据示例 model = find_best_arima(sales[-180:], d=1, max_p=5, max_q=5) forecast = model.forecast(steps=10) print(forecast)

这段代码的逻辑很直观:遍历(p, q)组合,对每个组合训练ARIMA,记录AIC最小的模型作为最终模型。forecast(steps=10)表示预测未来10个时间点。这里有个关键参数需要理解:steps是按数据的时间频率走的,如果训练数据是月度数据,预测10步就是10个月;如果是日度数据,就是10天。代码注释里写的是“训练最后180个点”,这是常规做法,因为早期数据可能反映旧业务周期,取近期数据建模更贴合当前趋势。将历史数据放进forecast方法时,模型内部会使用训练数据的最后几个点作为预测基线,因此不用手动拼接最近值。

4. 预测策略与上线效果:为什么一个月要预测三次

4.1 上中下旬分段预测的设计动机

把这套模型的预测频率做成“每月分上中下旬三个点预测”,是这套资源里最值得吸收的一个项目设计。直接按自然月做整月预测,意味着每个月只能给一次预测值,一旦月初实际销量出来后,要么等到月末才能修正,要么就整月睁眼瞎。但拆成三段之后,上旬做完预测,等到中旬时已经有实际销量可以拿来对比,模型可以重新训练一次,预测下旬;下旬再预测下个月上旬。用摘要里的话说,这等于“月上旬和中旬的实际销量可以作为先验知识”。

这种做法在真实业务中非常实用。比如电商或零售场景,月初、月中、月末的促销政策和消费节奏完全不一样,单月一个预测值根本没法指导备货。改成三段后,每段预测周期缩小到10天左右,误差更可控,而且上一段的实际销量可以修正下一段的趋势判断。代价是模型需要高频重新训练,但好在ARIMA训练很快,几十条数据秒级完成,性能完全不是问题。

4.2 预测结果对比与误差观察

资源里提供了“某企通预测值与实际值对比_正式版.xlsx”,这应该是把模型输出和真实值放进了同一个表。我拿到这种文件时习惯先建一个误差列,也就是实际值减预测值的绝对值,再除以实际值得到百分比误差。看误差分布比看单个值重要:如果误差大多数落在10%以内,说明模型在该段数据上是可信的;如果某个点误差特别大,通常不是模型的问题,而是当月有促销、缺货、退货等异常事件。

上旬、中旬、下旬三个时间点的误差通常呈现出不同特征。我的经验是:上旬预测往往偏乐观,因为月初销售热情高但数据样本还没出来;中旬因为有上旬实际值修正,误差会明显收窄;下旬则要格外注意是否受月末冲量影响。这份资源里的图片“销量预测测试情况.png”和“上线效果.png”已经把这种趋势画出来了。复现时不要只看平均误差,要把三个时间段分开统计,这样你才能判断这个预测策略到底在哪一段最起作用。

5. ARIMA落地避坑指南:五条高频踩坑记录

5.1 现象:模型报错说数据非平稳

直接对原始销量序列调用ARIMA拟合,有时会报出ValueError: Non-stationary starting autoregressive parameters之类的问题,或者在训练完成后预测结果突然变成一条直线。

原因是对带趋势或强波动的序列,ARIMA内部的参数估计过程无法收敛到稳定状态。尤其当d设成0时,模型强行用原始序列拟合,自回归参数会超出稳定域。

解决方式是在建模前强制做差分,也就是先对序列执行diff()后再进入模型,或者把order里的d设为1。更稳妥的办法是先用adfuller做一遍检验,p值大于0.05就让d至少为1。这是我的固定流程,不跳步。

5.2 现象:predict和forecast的结果对不上

代码里用了model.predict(start=..., end=...)和model.forecast(steps=...),两个接口返回的数值完全不同,甚至前几个点差出好几个量级。

原因是predict是按绝对下标去定位起始和结束点,预测结果是从训练集内部开始的,并不是真正意义上的“未来”;而forecast是从训练集最后一个点之后开始预测,步数直接对应未来。理解这一点后,我通常统一用forecast(steps=n)做未来预测,predict只用来做历史拟合效果的可视化对比。

解决方式:把predict改成用模型结果做回测,而不是做未来预测;未来预测一律走forecast。资源里如果既有测试脚本又有正式脚本,建议先确认每个脚本用的是哪个接口,别在对比时把两种结果混在一起。

5.3 现象:差分后序列变短,预测值无法还原

做一阶差分后,数据点从N个变成N-1个。很多新手在使用差分后的序列训练模型,预测出来的结果是一阶差分值,再想还原成销量时不知道怎么加回去,导致最终输出严重偏低。

原因是对差分序列建ARIMA,预测得到的是“增量”而不是“绝对量”,必须从训练集最后一个真实值开始累加预测值,才能还原成销量。

解决方式:先用一个变量last_value记录原始序列最后一个真实值,然后用cumsum把预测增量累加,再加上last_value。如果做的是季节差分,叠加逻辑要更复杂,但本项目只需处理一阶差分。建议把还原逻辑封装成一个函数,每次预测完自动调用。

5.4 现象:AIC自动定阶选出的模型预测曲线是平的

训练时AIC最小,但预测出来的未来值基本保持水平,或者只出现微小波动,看起来完全不像销量走势。

这在p和q都选成很小值的场景下很常见,比如p=1, q=0,模型退化成AR(1),预测结果会快速收敛到序列均值,后面的点看起来就是一条平线。如果业务本身没有强趋势,这个结果是正常的;但如果销量有明显的季节性或者说在特定月份有规律性增长,那么AR(1)就明显不够。

解决方式:在自动定阶的基础上,把季节趋势纳入考虑。如果原始序列已经看得到周期性,比如每年双十一或每月下旬冲量,优先尝试SARIMAX加上季节分量。资源里虽然挂的是ARIMA,但statsmodels里SARIMAX可以直接复用同样的流程,只需要增加seasonal_order参数。

5.5 现象:销量有周期性但模型完全没捕捉到

上一条说的季节性,在月度数据里表现为每年同一个月份销量偏高。标准ARIMA默认不处理周期,如果你把历史数据跨了两年以上,模型会把周期当噪声,导致每年冲量点预测失败。

原因很明显:ARIMA只处理非季节性的自相关和移动平均,季度、年度周期需要在建模前做季节差分,或者换用SARIMA。

解决方式:先观察销量时序图里是否出现规律性波峰。如果波峰间隔固定为12个月,就在SARIMAX的seasonal_order里设(P, D, Q, 12),其中D通常取1。从这个角度说,这份资源的销量数据若是平稳的单峰序列,普通ARIMA就够用;一旦数据量扩大到三年以上,就必须升级到季节模型。这是升级路径,不是本项目硬伤。

6. 让预测更稳的一步:残差白噪声检验与参数微调

6.1 用Ljung-Box检验残差

模型拟合完成后,不要急着看预测值。先用残差检验确认模型已经把信息榨干,是所有时间序列流程里最不该跳过的一步。Ljung-Box检验可以判断残差序列是否存在自相关性,如果p值大于0.05,说明残差接近白噪声,模型已经吸收了可解释的信息;如果p值很小,说明残差里还有结构没捕捉到,此时的预测不可靠。

from statsmodels.stats.diagnostic import acorr_ljungbox # fitted 是前面训练好的ARIMA模型 resid = fitted.resid lb_test = acorr_ljungbox(resid, lags=10, return_df=True) print(lb_test)

Ljung-Box的lags参数常见取10到20之间,数据量不大时取10即可。输出里的lb_pvalue列就是检验p值,重点关注它是否大于0.05。我习惯把这个检验放进模型训练脚本里,每次训练完自动打印p值,小于0.05就报警,然后回头改阶数或加季节分量。检查残差这一步能让模型在交付之前把所有问题暴露出来,而不是等到业务反馈预测不准才回去翻代码。

6.2 按业务节奏微调预测频率

调完模型后,还有最后一道工序:按业务节奏重新设计预测点。月度分上中下旬是这套资源的特色,但放到具体业务里可能有更合适的节奏。比如周度销量波动大的产品,可以改成每周一预测本周销量;月底有冲量的行业,可以在24号之后加一次月末临时预测,把上中旬实际销量全部作为先验信息。我一般的做法是把预测点配置做成一个表:日期、预测阶段、训练数据截止日、预测步长,每次预测时读取这张表,而不是硬编码在代码里。

参数微调方面,p、q的搜索范围不要无脑扩大到10以上,训练时间成倍增加收益却很小。真正值得调的是method参数,比如用method='statespace'处理含缺失值的序列,或者调整enforce_stationarity=False来放宽模型约束。这两个参数在statsmodels新接口里默认值足够安全,除非你确认自己的序列特殊情况,否则保持默认。

这次复现过程中,我在预测值还原上栽过一次跟头,差分后忘了把增量累加回原值,输出结果低得离谱。从那以后我每次拿到时间序列项目都会强制走一遍固定流程:ADF检验、差分、Ljung-Box残差检验、预测值还原检查,四步全过才敢把结果拿去和真实值对比。这套资源帮你把大部分步骤都封装好了,但那些隐含在代码里的边界条件,依然值得你亲手跑一遍确认。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询