3、经典统计模型:ARIMA模型原理与实战、SARIMA季节性模型、模型诊断与残差分析
说到时间序列预测,很多人一上来就上深度学习。但我个人习惯,先拿经典统计模型试试水。为什么?因为ARIMA这类模型,说白了就是帮你把「时间」这个维度拆解得明明白白。你想想看,如果连数据里的趋势和周期都看不清楚,直接上黑盒模型,很容易翻车。
我在项目中遇到过好几次,用LSTM跑出来的结果,还不如一个调参调好的ARIMA。嗯,这里要注意,不是说深度学习不好,而是经典模型更「透明」——你能看到每一步在做什么。
3.1 ARIMA模型:从直觉到公式
ARIMA的全称是自回归积分滑动平均模型。名字挺长,但拆开看就三部分:
- AR(自回归):用过去的值预测现在的值。比如今天的气温,跟昨天、前天有关。
- I(差分):让非平稳数据变平稳。说白了就是「减一减」,把趋势去掉。
- MA(滑动平均):用过去的预测误差来修正当前的预测。
ARIMA模型有三个关键参数:p、d、q。
| 参数 | 含义 | 怎么定 |
|---|---|---|
| p | 自回归阶数 | 看PACF图,截尾处 |
| d | 差分阶数 | 做单位根检验,直到平稳 |
| q | 滑动平均阶数 | 看ACF图,截尾处 |
数学表达式长这样:
ARIMA(p,d,q):
(1 - φ₁B - ... - φₚBᵖ)(1-B)ᵈ yₜ = (1 + θ₁B + ... + θₙBᵠ) εₜ
别被公式吓到。你只要记住:B是滞后算子,φ是AR系数,θ是MA系数。剩下的交给代码。
3.2 实战:用Python实现ARIMA
我们拿股票日收益率数据来演示。注意,收益率序列通常已经接近平稳,省去了很多麻烦。
import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt
# 加载数据
df = pd.read_csv('stock_returns.csv', index_col='date', parse_dates=True)
y = df['return'].dropna()
# 画ACF和PACF图
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(y, lags=30, ax=ax1)
plot_pacf(y, lags=30, ax=ax2)
plt.show()
# 拟合ARIMA(2,0,2)模型
model = ARIMA(y, order=(2, 0, 2))
result = model.fit()
print(result.summary())
输出结果里,重点关注两件事:
- 系数是否显著(看P值,小于0.05就算显著)
- AIC和BIC值(越小越好,用于模型对比)
3.3 SARIMA:给模型加上「日历」
ARIMA处理不了周期性。比如电商销量,每周五都会冲高。这时候就需要SARIMA——在ARIMA基础上加了季节性成分。
SARIMA的参数变成7个:(p,d,q)×(P,D,Q,s)。其中s是周期长度,比如周数据s=7,月数据s=12。
举个例子,如果你做的是日频数据,发现每周都有规律:
from statsmodels.tsa.statespace.sarimax import SARIMAX
# SARIMA(1,1,1)×(1,1,1,7)
model = SARIMAX(y, order=(1,1,1), seasonal_order=(1,1,1,7))
result = model.fit()
print(result.summary())
为什么是(1,1,1,7)?
- 季节性AR阶数P=1:用上周同一天的值
- 季节性差分D=1:去掉周级别的趋势
- 季节性MA阶数Q=1:用上周的预测误差
- 周期s=7:一周7天
我在做电商销量预测时,发现SARIMA的效果比纯ARIMA提升了30%以上。尤其是节假日效应,SARIMA能自动捕捉到「去年双11前后销量暴涨」这种模式。
3.4 模型诊断:别急着用,先看看残差
模型拟合完了,别急着预测。先做诊断——说白了就是检查残差(真实值-预测值)是不是「白噪声」。
好的残差应该满足三个条件:
- 均值为0:没有系统性偏差
- 无自相关:残差之间不相关
- 正态分布:方便做置信区间
诊断代码:
# 残差分析
residuals = result.resid
# 1. 画残差图
plt.figure(figsize=(10, 4))
plt.plot(residuals)
plt.title('残差序列')
plt.show()
# 2. 画残差ACF图
plot_acf(residuals, lags=30)
plt.title('残差自相关检验')
plt.show()
# 3. Ljung-Box检验
from statsmodels.stats.diagnostic import acorr_ljungbox
lb_test = acorr_ljungbox(residuals, lags=[10, 20, 30], return_df=True)
print(lb_test)
Ljung-Box检验的p值如果大于0.05,说明残差没有显著自相关,模型OK。如果p值小于0.05,说明残差里还有信息没被提取,需要重新调整参数。
3.5 知识体系总览
下面这张图,把ARIMA和SARIMA的核心逻辑串起来了。建议你保存下来,调参时对照着看。
这张图展示了从原始数据到最终预测的完整流程。每一步都有对应的统计检验和可视化工具。我个人建议,新手先按这个流程走一遍,再考虑优化。
好了,这一章的内容就到这里。ARIMA和SARIMA虽然经典,但用好了威力不小。下一章我们会聊更进阶的模型——但在此之前,建议你把今天的内容动手跑一遍。代码我都贴出来了,复制到Jupyter里就能用。