一、从 ARMA 到 ARIMA:为什么需要 “差分”?
在之前的文章中,我们学习了 ARMA 模型如何通过历史观测值和误差项预测未来。但 ARMA 有个致命短板——它只能处理平稳时间序列。
什么是平稳序列?简单说,就是序列的均值、方差不随时间变化。但现实中,多数时间序列都带有趋势或季节性(如股票价格、GDP 增长、月度销量),这些序列明显非平稳,直接用 ARMA 会导致严重偏差。
举个例子:预测某公司的销售额(逐年增长),若忽略增长趋势,模型会把 “增长” 误判为随机波动,预测结果将严重滞后于实际值。
ARIMA 模型的核心创新:通过差分操作消除趋势,将非平稳序列转化为平稳序列,再用 ARMA 建模。这就像给模型装了个 “趋势过滤器”,让它专注于捕捉数据的本质规律。
二、ARIMA 的三要素:(p, d, q)
ARIMA 模型由三个参数定义:ARIMA(p, d, q),每个参数都有明确的物理意义:
- p:自回归阶数(AR 部分),表示使用过去 p 期的观测值;
- d:差分阶数,表示需要对原始数据进行 d 次差分以达到平稳;
- q:移动平均阶数(MA 部分),表示使用过去 q 期的误差项。
差分操作详解
差分是 ARIMA 的灵魂,它通过计算相邻数据点的差值来消除趋势。例如:
- 一阶差分:Δxt=xt−xt−1\Delta x_t = x_t - x_{t-1}Δxt=xt−xt−1(消除线性趋势)
- 二阶差分:Δ2xt=Δxt−Δxt−1\Delta^2 x_t = \Delta x_t - \Delta x_{t-1}Δ2xt=Δxt−Δxt−1(消除二次趋势)
直观理解:如果原始数据是 “销售额”,一阶差分后就变成了 “销售额的增长量”,而增长量通常比原始值更平稳。
三、ARIMA 模型的数学原理
核心公式
ARIMA(p, d, q) 的完整表达式可以拆分为两部分:
-
差分过程:将原始序列 xtx_txt 转换为平稳序列 yty_tyt
yt=Δdxt y_t = \Delta^d x_t yt=Δdxt -
ARMA 建模:对平稳序列 yty_tyt 应用 ARMA(p, q)
yt=ϕ1yt−1+⋯+ϕpyt−p+θ1εt−1+⋯+θqεt−q+εt y_t = \phi_1 y_{t-1} + \cdots + \phi_p y_{t-p} + \theta_1 \varepsilon_{t-1} + \cdots + \theta_q \varepsilon_{t-q} + \varepsilon_t yt=ϕ1yt−1+⋯+ϕpyt−p+θ1εt−1+⋯+θqεt−q+εt
其中,ϕi\phi_iϕi 是 AR 系数,θj\theta_jθj 是 MA 系数,εt\varepsilon_tεt 是白噪声误差。
参数估计方法
ARIMA 模型的参数估计分为两步:
- 确定 d:通过 ADF 检验(单位根检验)判断序列是否平稳,逐步增加差分次数直到平稳;
- 确定 p 和 q:对差分后的平稳序列,使用 ACF/PACF 图或信息准则(AIC/BIC)选择最优阶数。
四、ARIMA 建模实战:Python 实现
下面通过一个完整案例,展示如何使用 ARIMA 模型预测带趋势的时间序列数据:
案例:预测公司季度营收(带增长趋势)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# 设置随机种子,确保结果可复现
np.random.seed(42)
# 1. 生成带趋势的季度营收数据(2018-2022年)
dates = pd.date_range(start='2018-01-01', periods=20, freq='Q')
trend = np.linspace(100, 300, 20) # 线性增长趋势
noise = np.random.normal(0, 20, 20) # 随机噪声
revenue = trend + noise # 季度营收 = 趋势 + 噪声
# 创建DataFrame
df = pd.DataFrame({'revenue': revenue}, index=dates)
# 2. 可视化原始数据
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.plot(df.index, df['revenue'], color='blue', linewidth=2)
plt.title('原始季度营收数据(非平稳)', fontsize=14)
plt.grid(True)
# 3. 平稳性检验(ADF检验)
def adf_test(series):
result = adfuller(series)
print(f'ADF Statistic: {result[0]}')
print(f'p-value: {result[1]}')
print('Critical Values:')
for key, value in result[4].items():
print(f'\t{key}: {value}')
if result[1] <= 0.05:
print("序列平稳(拒绝原假设)")
else:
print("序列非平稳(接受原假设)")
print("原始数据的ADF检验:")
adf_test(df['revenue'])
# 4. 一阶差分并检验平稳性
df['diff1'] = df['revenue'].diff().dropna()
plt.subplot(2, 2, 2)
plt.plot(df.index[1:], df['diff1'][1:], color='green', linewidth=2)
plt.title('一阶差分后数据(平稳)', fontsize=14)
plt.grid(True)
print("\n一阶差分后的ADF检验:")
adf_test(df['diff1'].dropna())
# 5. 绘制ACF和PACF图(确定p和q)
plt.subplot(2, 2, 3)
plot_acf(df['diff1'].dropna(), lags=10, ax=plt.gca())
plt.title('差分后序列的ACF图', fontsize=14)
plt.subplot(2, 2, 4)
plot_pacf(df['diff1'].dropna(), lags=10, ax=plt.gca())
plt.title('差分后序列的PACF图', fontsize=14)
plt.tight_layout()
plt.show()
# 6. 拟合ARIMA(2,1,2)模型
model = ARIMA(df['revenue'], order=(2, 1, 2)) # p=2, d=1, q=2
model_fit = model.fit()
# 7. 预测未来8个季度的营收
forecast_steps = 8
forecast = model_fit.forecast(steps=forecast_steps)
forecast_index = pd.date_range(start=df.index[-1] + pd.DateOffset(months=3), periods=forecast_steps, freq='Q')
# 8. 可视化预测结果
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['revenue'], label='历史营收', color='blue', linewidth=2)
plt.plot(forecast_index, forecast, label='预测营收', color='red', linestyle='--', linewidth=2)
plt.title('季度营收预测(ARIMA模型)', fontsize=14)
plt.xlabel('日期')
plt.ylabel('营收(万元)')
plt.legend()
plt.grid(True)
plt.show()
五、ARIMA 建模全流程解析
1. 数据生成与探索
我们创建了一个带线性增长趋势的季度营收数据,从图中可以明显看出均值随时间增加,属于非平稳序列。
2. 平稳性检验
通过 ADF 检验判断序列是否平稳:
- 原假设:序列非平稳
- 若 p-value > 0.05,则接受原假设,序列非平稳
原始数据的 ADF 检验 p-value ≈ 0.99,说明非平稳,需要差分。
3. 差分转换
对原始数据进行一阶差分后,再次进行 ADF 检验,此时 p-value ≈ 0.0001,说明已平稳,故 d=1。
4. 确定 p 和 q
通过 ACF/PACF 图判断阶数:
- ACF 图:在滞后 2 阶后截尾 → q=2
- PACF 图:在滞后 2 阶后截尾 → p=2
因此,选择 ARIMA(2, 1, 2) 模型。
5. 模型拟合与预测
使用选定的参数拟合模型,并预测未来 8 个季度的营收。从预测结果可以看到,模型成功捕捉了原始数据的增长趋势,并给出了合理的预测区间。
六、ARIMA 模型的优缺点与适用场景
优点
- 适用性广:能处理各种趋势的非平稳序列(线性、非线性)
- 理论成熟:有严格的数学基础和统计检验方法
- 可解释性强:参数具有明确的物理意义
- 短期预测精准:在处理 1-12 期预测时表现优异
缺点
- 不适合长期预测:超过一定期限后,预测值会收敛到均值
- 无法处理季节性:对季节性波动大的数据效果不佳(需用 SARIMA)
- 参数调优复杂:需要反复尝试不同的 (p, d, q) 组合
适用场景
- 具有趋势但无明显季节性的数据(如 GDP、人口增长)
- 短期预测需求(如未来 1 年的销售额)
- 需要明确解释变量影响的场景
七、ARIMA 的进阶技巧与注意事项
1. 差分次数 d 的选择
- 多数情况下,d=0 或 1 即可
- 若序列有二次趋势(如指数增长),可能需要 d=2
- 极少需要 d≥3,因为过度差分会导致信息丢失
2. 自动定阶工具
除了手动观察 ACF/PACF,还可以使用自动定阶函数:
import pmdarima as pm
# 自动寻找最优(p,d,q)参数
model = pm.auto_arima(df['revenue'],
start_p=0, start_q=0,
max_p=5, max_q=5,
d=None, # 自动确定差分阶数
seasonal=False, # 暂不考虑季节性
trace=True) # 打印搜索过程
3. 模型评估指标
常用指标包括:
- AIC/BIC:越小越好
- MAE/MSE/RMSE:衡量预测误差
- Ljung-Box 检验:检验残差是否为白噪声
八、总结与展望
ARIMA 模型通过 “差分 + ARMA” 的组合,成功解决了非平稳时间序列的预测难题。其核心在于通过差分消除趋势,让模型专注于捕捉数据的本质波动规律。
但 ARIMA 仍有局限——它无法直接处理季节性数据。在下一篇文章中,我们将学习 SARIMA 模型(季节性 ARIMA),看看如何同时处理趋势和季节性,敬请期待!
如果本文对你有帮助,欢迎分享给更多需要的朋友~ 有任何疑问或建议,欢迎在评论区留言交流!