想象你在海边开了一家小餐厅,每天记下客流人数,已经记了五年。你发现一个铁律:每年夏天游客爆满,冬天门可罗雀。普通 ARIMA 模型就像一位只记得“最近三天”的临时店员——用它预测明天的客流,它只会说“今天跟昨天差不多”。可它不知道去年七月发生了什么,所以每年六月它都预测“客流还会继续冷清”,结果七月一日突然人山人海,餐厅措手不及。把这种现象想象成“只有短期记忆、没有日历记忆”的店员,你就明白了 ARIMA 的痛点。而 SARIMA 要做的事,就是给这位店员配上一本厚厚的日历笔记,让他不仅记得昨天,还记得“去年同期发生了什么”。本文通过 1949—1960 年国际航线月度客运量数据,带你把 SARIMA 的季节差分、季节自回归/移动平均项(P,D,Q,m)、Box-Jenkins 建模流程、模型诊断与预测完整走一遍,让你从此面对旅游、零售、农业等强季节性数据时不再慌。
学会 SARIMA,你就能在面试和实战中自信地说:“我不仅能预测趋势,还能把季节性规律稳稳地接住。”这是时序预测岗位的核心加分项。
可视化演示
展示航空客流数据的SARIMA建模过程,包含趋势-季节分解、模型拟合与外推预测,通过滑块控制预测月数。
本节配有交互动效(进入视口后自动加载,约 3KB)。
SARIMA(p,d,q)(P,D,Q,m) 实际数据点 模型拟合线 预测与置信区间 m=12(年度季节性) 季节差分消除周期趋势
ARIMA的局限
老张的餐厅雇了一位叫“小A”的临时工,专门负责预测客流。小A有个特点:只记得最近三天的客流。如果昨天来了 300 人,今天来了 310 人,小A就会说明天大约 320 人。这套逻辑在平稳的日子里很好用,可一到夏天就翻车——每年六月,小A看着冷清的客流说“明天还是这个量”,结果七月一号游客涌进海边,后厨备的菜只够一半人吃。问题出在哪?小A没有“日历记忆”,它不知道去年七月的客流是今年的三倍。
这个“短期记忆”对应到数学上,就是 ARIMA 只建模相邻时刻之间的自相关。所谓 ARIMA(p,d,q),核心思想是先用 d 阶差分把不平稳的序列变得平稳,再用 p 阶自回归和 q 阶移动平均去描述平稳序列的线性依赖。它眼里的世界是“昨天的客流能解释今天”,但对“每个 12 个月就重复一次的旺季”完全没有概念。你可以把 ARIMA 理解成一个强大的近视眼:近处看得清清楚楚,远处一片模糊。
ARIMA 的数学方程长这样:
回到餐厅:老张终于意识到,小A再努力也不可能预测旺季,因为它压根不知道“一年”这个概念。想要在夏天游客来之前备足食材,必须给小A补上一课——把日历还给它。这正是 SARIMA 登场的理由。
- 差分后的序列 $y_t'$对原始序列做 $d$ 次差分后的结果,它剔除了趋势,让序列看起来“平稳”。
- 自回归项 $\phi_1 y_{t-1}'$如果把过去几个时刻的值按系数加权,用来预测当前值,这就是“用昨天解释今天”。
- 移动平均项 $\theta_1 \varepsilon_{t-1}$把过去几天的“意外误差”也纳入记忆,弥补纯自回归的盲区。
- 常数与当期噪声 $c + \varepsilon_t$$c$ 是序列的基线漂移,$\varepsilon_t$ 是今天无法解释的随机扰动。
SARIMA的构成
老张决定改造小A,给他装了一个“日历模块”。改造后的小A预测明天客流时,会额外问一句:“去年的今天,客流量是多少?”如果去年 7 月 15 日来了 800 人,今年 7 月 14 日来了 760 人,小A就会推断:明天大概率也接近 800。这个“和去年同期对比”的动作,就是 SARIMA 最核心的部件——季节差分。
季节差分的数学定义非常朴素:把当前值减去一个周期之前的值。对于月度数据,一个周期就是 12 个月:
除了季节差分,SARIMA 还引入了两个“季节记忆”零件:季节自回归项(Seasonal AR)和季节移动平均项(Seasonal MA)。季节自回归好比“去年同期的客流趋势会惯性延续”——去年暑假很火,今年暑假大概率也火;季节移动平均则允许去年同期的一些“意外波动”对今年产生影响。这三件套(季节差分、季节自回归、季节移动平均)一起,构成了小A的完整日历记忆。
老张很满意:小A现在既能看“眼前三天”,又能翻“去年同期”。不过这还只是零件清单,如何把它们组装成一个能用的预测机器,还需要一张完整的“组装图”——这就是下一节的乘法模型。
- 时间下标 $t$表示当前时刻,比如“今年 7 月”这个观测点。
- 季节周期 $m$一个完整季节轮回的长度。月度数据取 $m=12$,因为一年有 12 个月。
- 去年同期值 $y_{t-m}$向前翻 12 个月,找到“去年 7 月”的客流。
- 整体动作 $\Delta_m y_t$用当前值减去去年同期值,相当于在问:“和去年同一个时节比,今年是涨了还是跌了?”
乘法模型全貌
有了零件,老张开始组装。小A的预测逻辑分两层:第一层看“短期惯性”——昨天人多,今天人也不会少;第二层看“季节校准”——去年这个时节是旺季,所以今年也要把预测量往上抬。关键是,这两层不是简单相加,而是相乘。为什么?因为季节因素的影响是成倍放大的:旺季时,短期热度会被放大三倍;淡季时,短期热度也会被压缩。乘法的结构让季节成分既能放大又能缩小短期预测。
SARIMA 的完整数学表达式记作 $SARIMA(p,d,q)(P,D,Q)_m$,前面括号是短期部分,后面括号是季节部分,$m$ 是季节周期。它的紧凑写法是:
老张把这张组装图贴在了厨房。现在他知道了:要配出一份完整的 SARIMA 菜谱,需要回答 7 个数字——$p,d,q,P,D,Q,m$。接下来最难的问题来了:这些数字到底填多少?总不能瞎猜。老张决定翻开客流日记,用 ACF 和 PACF 两张图来寻找线索。
- 短期间 $p,d,q$短期自回归阶数、差分阶数、移动平均阶数,对应“看最近几天”。
- 季节阶数 $P,D,Q$季节自回归、季节差分、季节移动平均的阶数,对应“翻去年同期”。
- 滞后算子 $B^m$把时间向后拨 $m$ 个周期,$B^{12}y_t = y_{t-12}$。它是“翻日历”这个动作的数学表达。
- 左侧组装短期部分和季节部分相乘,共同作用在差分后的序列上,构成完整的“预测引擎”。
季节参数定参
老张把 5 年的客流日记摊在桌上,画出“客流与过去每一天的相关图”(ACF 图)。他惊讶地发现:除了相邻几天有强相关,在第 12 个月、第 24 个月的位置上,也各冒出一个高峰。这就像日历上每隔 12 格就被画了一个红圈——季节周期的证据写在图里。$m$ 的确定其实就是“看数据里多久重复一次”,不是拍脑袋决定的。
ACF(自相关函数)衡量的是序列与自身滞后 $k$ 期的相关性:
定参准则可以概括为几句话:看 ACF 的季节滞后处若呈“拖尾”(缓慢衰减),则季节 MA 阶数 $Q$ 可能为 1;看 PACF 季节滞后处若呈“截尾”(突然断掉),则季节 AR 阶数 $P$ 可能为 1。短期阶数 $p,q$ 则在低滞后区间用同样的逻辑判断。$m$ 则直接从数据周期确定:月数据看 $m=12$,季度数据看 $m=4$,周数据看 $m=7$。
老张的墙上现在多了一张“定参地图”:先画 ACF/PACF,找红圈,再定 $m$,最后定 $P,D,Q$。但定了参数还不算完,他还需要一套规范的“出菜流程”,确保每一步都不走样——这就是 Box-Jenkins 方法论。
- 分子 $k$ 期协方差把“今天的客流与 $k$ 天前客流的协同变化”累加起来,反映两者是否同涨同跌。
- 分母 $k$ 期方差以总方差做基准,把相关性归一化到 $[-1,1]$ 的区间。
- 系数 $\hat{\rho}_k$接近 1 表示强正相关(今天多明天也多),接近 0 表示无关系。当 $k=12$ 处出现高峰,说明存在“年度同期”的强关联。
Box-Jenkins流程
Box-Jenkins 不是什么高深的公式,而是一套做时序建模的“标准后厨流程”。老张做一道新菜有四个步骤:先看食材(观察数据),再定菜单(识别模型),接着试做(估计参数),然后请顾客试吃(诊断检验),满意了才正式上市(预测)。这四个步骤环环相扣,就是 Box-Jenkins 的灵魂。
模型识别阶段的任务是确认序列是否平稳。如果序列整体在上升(有趋势),先做普通差分;如果还有周期起伏,再做季节差分。识别工具正是上一节的 ACF/PACF 图。参数估计阶段则用极大似然估计或最小二乘法,把刚才定好的 $p,d,q,P,D,Q$ 的具体系数值算出来。诊断检验阶段要检查残差——也就是“模型没解释掉的部分”——是否还残留规律。任何阶段的结论不对,就要回到识别阶段重新定阶。
在模型比较时,最常用的“裁判”是 AIC 准则:
老张严格按照四个步骤出菜,每一道模型都透明可复查。他慢慢体会到:时序建模与其说是“套公式”,不如说是“按流程做实验”。现在,理论准备完毕,老张决定拿一份真实的大数据来检验这套方法论——航空公司的月度客流数据。
- 参数个数 $k$模型里所有自由参数的数量,$k$ 太大表示模型膨胀、容易过拟合。
- 极大似然值 $\hat{L}$在当前参数下,模型生成这份数据的概率。$-\ln(\hat{L})$ 越小,说明拟合越好。
- 总分 $AIC$两股力量相加。比较多个模型时,AIC 最小的模型胜出。
航空数据实战
老张的朋友在航空公司做收益管理,抱怨说乘客量忽高忽低,排班总是靠运气。老张拿到一份经典数据集:1949 年到 1960 年国际航线月度客运量。这组数据完美地展示了三个特征:长期向上的趋势(航空业蓬勃发展)、明显的年度季节性(暑假、寒假出行高峰)、以及随机噪声。这正是 SARIMA 的“主场”。
老张按照 Box-Jenkins 流程一步步来。第一步观察数据,确认有趋势和季节;第二步做一次普通差分消除趋势,再做一次周期 12 的季节差分消除年度波动;第三步观察 ACF/PACF,初步定下 $SARIMA(2,1,1)(1,1,1)_{12}$;第四步用极大似然估计拟合模型。拟合完成后,最关键的诊断环节到来了:残差必须像“白噪声”一样干净,也就是没有任何可提取的规律。判断标准用 Ljung-Box 检验:
在航空数据的实战中,$SARIMA(2,1,1)(1,1,1)_{12}$ 的残差 Ljung-Box $p$ 值远大于 0.05,模型顺利毕业。回头再看拟合曲线,它几乎完美地踩中了每年的旺季高峰。老张感叹:SARIMA 就像一位真正读懂航空业“日历”的老师傅,而不仅仅是按最近几天猜未来的临时工。
- 样本量 $n$ 修正因子$n(n+2)$ 和 $n-k$ 是给短样本打的“折扣”,避免小样本误判。
- 残差自相关 $\hat{\rho}_k^2$把每个滞后阶的残差相关性平方后累加,突出那些“不该有的相关”。
- 判定逻辑 $Q$$Q$ 统计量越大,残差越不干净;反之若 $p$ 值大于 0.05,则残差通过白噪声检验。
预测与业务落地
模型在历史数据上表现优秀,可老张知道:预测的价值不在过去,而在未来。航空公司的朋友问:“你能提前告诉我明年 7 月的乘客量吗?”老张给出的回答不是一个孤零零的数字,而是一个区间:明年 7 月大概率在 5800 到 6600 人之间。这个区间就是预测区间,它反映了不确定性——未来越远,区间越宽,就像车灯照得越远,光斑越模糊。
预测区间的数学基础来自预测误差的方差累积。$h$ 步预测的区间可以写成:
拿到预测区间后,航空公司的朋友直接把它用于业务决策:旺季提前增加航班频次、动态调整票价、安排机组轮休;淡季则削减运力、推出旅游套餐。老张的“四季餐厅”也早已用同样的方法提前囤好夏日食材。预测的意义从来不在于“算得准”,而在于“让决策者提前拿到一眼能看懂的确定性边界”。
- 点预测 $\hat{y}_{t+h}$模型对 $h$ 个时刻之后客流量的最佳猜测,是区间的中心。
- 随机波动 $\hat{\sigma}^2$残差的方差,衡量模型“平时犯错的幅度”。
- 脉冲响应权重 $\psi_j$过去一个冲击对未来第 $j$ 步的传染力度,权重平方说明不确定性像“涟漪”一样逐层扩散。
- 置信系数 $z_{\alpha/2}$决定区间的宽窄,95% 置信度对应 1.96,90% 对应 1.645。
AI 应用场景
旅游平台与酒店房价预测
阶段:预测与定价决策
解决的问题:酒店预订量有极强的季节性(节假日、寒暑假、旅游旺季),传统手工定价靠经验,旺季低估需求导致收益流失,淡季又容易空房。SARIMA 能捕捉“去年同期 + 近期趋势”的双重规律,提前 3 个月给出预订量预测区间,为动态定价提供依据。
具体案例:某 OTA 平台对三亚、大理等热门目的地按“城市 × 酒店星级”分别训练 SARIMA 模型,输入过去 3 年月度预订数据,输出未来 6 个月预订量预测。平台据此在旺季前上调房价约 15%,淡季自动生成促销方案,整体收益率提升了 8%。
零售连锁的智能补货
阶段:库存规划与供应链决策
解决的问题:便利店饮料、雪糕等商品销量随季节剧烈波动:夏天冰饮销量翻倍,冬天热饮走俏。人工备货容易凭感觉,导致旺季缺货、淡季积压。SARIMA 把“商品 × 门店”的月度销量序列分别建模,自动识别 12 个月周期,给出未来补货建议区间。
具体案例:某连锁便利店对 200 家门店的 50 个核心 SKU 使用 SARIMA 预测月度销量,系统每周自动生成补货单。上线一个季度后,整体缺货率下降 12%,临期报废率下降 9%。
航空公司运力与航班规划
阶段:中长期资源规划
解决的问题:航线客流有春运、暑运、国庆等多个年度高峰,飞机排班和机组配备需要提前 6—12 个月确定。SARIMA 擅长把“年度周期性”从客流中拆出来,为航线申请、运力分配和机票定价提供量化依据。
具体案例:某航空公司用 SARIMA 对 30 条国内航线建模,预测未来 12 个月各月客运量。结果显示暑运高峰预测误差仅 3.2%,公司据此提前锁定暑运红眼航班时刻,边际利润提升约 1200 万元。
Python 演示
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom statsmodels.tsa.statespace.sarimax import SARIMAXfrom statsmodels.stats.diagnostic import acorr_ljungbox # 生成一份带趋势和年度季节性的月度客流数据(航空风格)rng = np.random.default_rng(42)n = 144t = pd.date_range('1949-01-01', periods=n, freq='MS')trend = np.linspace(120, 620, n)season = 90 * np.sin(2 * np.pi * np.arange(n) / 12 + 0.5) \ + 20 * np.sin(2 * np.pi * np.arange(n) / 6)noise = rng.normal(0, 25, n)y = pd.Series(trend + season + noise, index=t, name='Passengers') # 季节差分:观察一年前的差值是否让序列平稳y_diff12 = y.diff(12).dropna() # 拟合 SARIMA(2,1,1)x(1,1,1,12)model = SARIMAX(y, order=(2, 1, 1), seasonal_order=(1, 1, 1, 12))result = model.fit(disp=False) # 残差白噪声检验(Ljung-Box)lb = acorr_ljungbox(result.resid, lags=[12], return_df=True)print('Ljung-Box p 值 =', lb['lb_pvalue'].iloc[0]) # 预测未来 24 个月并画图fore = result.get_forecast(steps=24)mean = fore.predicted_meanci = fore.conf_int()ax = y.plot(figsize=(10, 5), label='历史')mean.plot(ax=ax, label='预测', color='#F43F5E')ax.fill_between(ci.index, ci.iloc[:, 0], ci.iloc[:, 1], color='#F43F5E', alpha=0.15, label='95% 置信区间')ax.set_title('SARIMA 航空客流预测')ax.legend()plt.show()
y.diff(12).dropna()这一步是季节差分,相当于“今年客流减去年客流”,把 12 个月的周期从数据里剥离出来。SARIMAX(y, order=(2,1,1), seasonal_order=(1,1,1,12))指定短期部分 (2,1,1) 和季节部分 (1,1,1,12),后者中的 12 就是季节周期 $m$。result.fit(disp=False)用极大似然估计训练模型,disp=False表示不打印迭代过程。acorr_ljungbox(result.resid, lags=[12], return_df=True)对残差做 Ljung-Box 白噪声检验,$p$ 值大于 0.05 说明残差干净。fore.conf_int()输出预测区间上下界,为业务决策提供“不确定性边界”。
常见误区
误区我总以为 SARIMA 里的 D 就是普通差分做几次,跟 d 是一回事,写代码时 season_order 里的 D 填 1 就够了,管它是不是季节差分。
正解d 是普通差分阶数,负责消除“长期趋势”;D 是季节差分阶数,负责消除“周期性水位差”。两者作用对象完全不同:d 对应“今天比昨天”,D 对应“今年比去年同期”。就像打扫房间:d 是擦桌子(去趋势),D 是给地板打蜡(去季节),不能混为一谈。
为何常见:因为 SARIMA 写法里两处都出现数字 1,初学者很容易把两个括号里的参数当成同一类操作,忽视了季节性这个维度。
误区季节周期 m 是不是设得越大越精确?比如月数据我设 m=24 或 m=36,是不是能多学几个周期的规律?
正解m 必须等于数据真实的季节频率,不是参数搜索的旋钮。月度数据一个季节轮回就是 12 个月,设 m=24 会把“两年周期”当作季节,导致模型学习到不存在的规律,反而破坏预测。就像餐厅备年货,你按“每两年备一次”来准备春节食材,必然会错乱。
为何常见:把 m 理解成“记忆长度”而不是“周期长度”,看到模型里有个可调数字就下意识认为越大越强。
误区我画了 ACF 图,看到前几阶衰减很快,就判断数据不需要季节项,结果模型误差一直下不来。
正解ACF 不仅要看前几阶,还要盯住滞后 12、24、36 的位置——如果那里出现“同相”高峰,说明数据存在年度自相关。只盯着短期滞后,就像只看见店里今天客人少,却看不见日历上写着“下个月是暑期”。
为何常见:ACF 图信息密集,新手习惯只看最左边几根柱子,不知道季节信号藏在大滞后位置上。
误区SARIMA 自带季节差分,是不是普通差分就不需要了?反正都是差分。
正解SARIMA 是“短期×季节”的组合,二者各司其职。如果序列还有明显的长期上升趋势,不做普通差分的话,趋势仍会让模型有偏。正确做法是像 Box-Jenkins 流程说的:先观察序列,趋势用 d 消除,季节波动用 D 消除,两者常常都要做。
为何常见:因为 SARIMA 的公式看起来“已经包含了差分”,初学者误以为它是替代关系而不是叠加关系。
误区模型在训练集上 R² 很高、和历史曲线贴得很紧,我就直接拿去预测了,从没检查过残差是不是白噪声。
正解拟合得好不代表预测得好。如果残差里还残留周期规律,说明模型没有把季节性信息“吸干”,预测阶段照样会翻车。Ljung-Box 检验就是专门来查这项的:残差必须干净得像没有味道的白开水,模型才算合格。
为何常见:人天然偏爱“曲线重合度高”的直观反馈,却忽略了时序建模真正重要的是“残差无信息”。
面试题
Q1. SARIMA 中的 m 表示什么?
- A.移动平均阶数
- B.季节周期的长度← 正确答案
- C.差分次数
- D.自回归阶数
答案:B。m 是季节周期的长度,比如月度数据 m=12、季度数据 m=4、周数据 m=7。它决定“季节记忆”翻多少期对比一次。A、C、D 分别是 MA、差值和 AR 的概念,与 m 无关。
Q2. 季节差分 $\Delta_m y_t = y_t - y_{t-m}$ 的含义是?
- A.用今天的值减昨天
- B.用今年的值减去年同期← 正确答案
- C.用平均值减今年的值
- D.用今天的值乘季节指数
答案:B。季节差分是把当前时刻与往前 $m$ 期的值相减,本质是“今年 7 月比去年 7 月高多少”,从而消除年度周期。A 是普通差分,C 是去均值化,D 是季节乘法分解。
Q3. Box-Jenkins 建模流程的第一步是什么?
- A.参数估计
- B.模型预测
- C.模型识别← 正确答案
- D.残差诊断
答案:C。Box-Jenkins 四步是识别→估计→诊断→预测。识别阶段要观察数据平稳性和 ACF/PACF 图来定阶。先识别才能估计,先估计才能诊断,最后才能预测,顺序不能乱。
Q4. 在 ACF 图上,若滞后 12、24 处出现显著高峰,说明什么?
- A.序列是白噪声
- B.存在 12 个月的季节周期← 正确答案
- C.模型需要更高阶差分
- D.数据没有趋势
答案:B。滞后 12、24 出现显著峰,说明每隔 12 个周期数据显著相关,这是典型的年度季节性信号。白噪声的 ACF 应该全部不显著;趋势通常体现在 ACF 缓慢衰减,与本例的周期性峰不同。
Q5. 以下哪些迹象说明时序数据可能需要 SARIMA 而不是普通 ARIMA?
- A.ACF 在滞后 12 处有明显峰值← 正确答案
- B.数据呈现每年重复的旺季周期← 正确答案
- C.序列完全是随机噪声
- D.过去几年同一月份的数值高度相似← 正确答案
答案:ABD。季节性信号的核心是“相同月份跨年相关”,所以 A、B、D 都对。C 随机噪声既没有趋势也没有周期,任何 ARIMA 都不适用。
Q6. 模型残差的 Ljung-Box 检验 p 值很小(如 0.001),应该怎么理解?
- A.模型拟合得非常好
- B.残差中还残留自相关,需要改进模型← 正确答案
- C.残差是白噪声
- D.模型参数过多
答案:B。Ljung-Box 检验的原假设是“残差为白噪声”,p 值很小意味着拒绝原假设,说明残差里还藏着自相关规律。这就像厨师试吃发现汤里还有未融开的盐粒——还要继续调味。A、C 恰好说反了,D 与检验无关。
Q7. SARIMA(p,d,q)(P,D,Q)m 中,D=1 表示什么?
- A.做 1 次普通差分
- B.做 1 次季节差分← 正确答案
- C.季节自回归阶数为 1
- D.周期长度为 1
答案:B。D 是季节差分阶数,D=1 表示“今年减去年”做一次。普通差分是 d,季节自回归是 P,周期是 m。四个字母各管一摊,别混淆。
Q8. 关于 AIC 准则在 SARIMA 模型选择中的使用,下列哪些说法正确?
- A.AIC 越小模型越优← 正确答案
- B.AIC 会惩罚参数过多的模型← 正确答案
- C.AIC 越大说明模型越简单
- D.比较两个 SARIMA 模型时必须使用同一份数据← 正确答案
答案:ABD。AIC = 2k − 2ln(L̂),前半部分惩罚参数数量,后半部分奖励拟合优度,所以 A、B 正确。C 说反了。D 正确:不同数据集上比较 AIC 没有意义。
Q9. 为什么 SARIMA 的预测区间会随预测步长增加而变宽?
- A.因为点预测值越来越大
- B.因为不确定性逐期累积,脉冲响应权重平方叠加← 正确答案
- C.因为季节差分阶数太高
- D.因为残差方差在衰减
答案:B。预测区间的宽度由 $\hat{\sigma}^2 \sum \psi_j^2$ 决定,预测越远累加的项越多,不确定性像涟漪一样扩散,所以区间变宽。这好比车灯照得越远光斑越模糊。与点预测大小、差分阶数无关。
Q10. 航空月度客流数据适合用 SARIMA 建模的原因有哪些?
- A.数据存在逐年上升的趋势← 正确答案
- B.数据有明确的年度季节性(暑期、寒假高峰)← 正确答案
- C.数据完全平稳且无周期
- D.样本覆盖多个完整季节周期← 正确答案
答案:ABD。SARIMA 擅长处理“趋势+季节”的组合场景,A、B 正是它的能力范围;D 确保我们能估计出稳定的季节参数。C 说数据完全平稳,那就不需要 SARIMA 了。