时间序列:ARIMA 与 SARIMA 从原理到实战
1. 先回答一个问题:ARIMA 解决什么
ARIMA 不是“万能预测器”,它专门处理单变量时间序列里由自相关结构驱动的可预测成分。
核心思想是把序列写成“差分后的平稳过程 + 误差修正项”。
当你需要:
- 解释性强于黑箱精度;
- 样本量中小、特征工程有限;
- 业务需要可审计的模型诊断;
ARIMA 往往是第一选择。
2. 模型结构与数学形式
ARIMA$(p,d,q)$:
$$ \phi(B)(1-B)^d y_t = c + \theta(B)\varepsilon_t $$
其中:
- $p$ 是自回归阶数;
- $d$ 是差分阶数;
- $q$ 是移动平均阶数;
- $B$ 是滞后算子。
若存在季节项,使用 SARIMA$(p,d,q)\times(P,D,Q)_s$:
$$ \Phi(B^s)\phi(B)(1-B)^d(1-B^s)^D y_t = c + \Theta(B^s)\theta(B)\varepsilon_t $$
3. 建模流程(原则优先)
- 先画序列图与季节分解,不要直接网格搜索。
- 通过 ADF/KPSS 判断是否需要差分。
- 用 ACF/PACF 给 $p,q,P,Q$ 初值。
- 用 AIC/BIC 做候选比较。
- 对残差做白噪声检验(Ljung-Box)。
4. Python 参考实现
import pandas as pd
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.stats.diagnostic import acorr_ljungbox
# y: DatetimeIndex 的单变量序列
train = y.iloc[:-24]
test = y.iloc[-24:]
model = SARIMAX(
train,
order=(1, 1, 1),
seasonal_order=(1, 1, 1, 12),
enforce_stationarity=False,
enforce_invertibility=False,
)
res = model.fit(disp=False)
pred = res.get_forecast(steps=len(test)).predicted_mean
lb = acorr_ljungbox(res.resid.dropna(), lags=[12], return_df=True)
print(lb)
5. 常见误区
- 过度差分:把可预测信号差掉。
- 只看训练集拟合优度,不做滚动预测。
- 残差有显著自相关却直接上线。
- 忽略结构突变(政策、疫情、价格机制变化)。
6. 实务建议
- 把 ARIMA 作为可解释基线,再与树模型/深度模型对比。
- 业务里优先报告区间预测,不只报点预测。
- 当残差长期偏态或厚尾,考虑 GARCH 或状态空间扩展。
ARIMA 的价值不只是“预测值”,而是它把时间依赖结构显式化,便于你定位误差来源并迭代系统。