📑 查看全课大纲(第 14 / 20 节)

差分平稳化与 ARIMA 模型

约 65 分钟

📺 正在播放小象官方高清录播(支持倍速与清晰度调节)

小象实战讲义 · 时间序列分析

在上一章,我们学习了如何通过确定性分解(如趋势拟合、季节指数)来提取非平稳序列中的确定性信息。然而,这些方法往往提取不够充分,序列的残差中仍可能蕴含重要的随机性结构。本章我们将开启非平稳序列的随机分析之旅,核心思想是:先通过差分运算提取确定性信息,再对平稳化的残差序列建立成熟的 ARMA 模型进行分析。本节作为开篇,将重点讲解如何利用差分运算实现序列平稳化,并在此基础上构建经典的 ARIMA 模型。学完本节,你将掌握处理具有趋势或季节性的非平稳序列的标准建模流程。

💡 核心导读

  • 差分运算的实质:差分不仅是相邻观测值的简单相减,其数学本质是基于 Cramer 分解定理,通过自回归的方式提取序列中的确定性趋势和季节信息。
  • 差分方式的选择:针对线性趋势、曲线趋势和固定周期,分别采用一阶差分、高阶差分和步长差分,目标是使差分后的序列变得平稳。
  • 警惕过差分:并非差分阶数越高越好,过度的差分会浪费有效信息,导致估计精度下降。
  • ARIMA 模型结构:ARIMA(p,d,q) 模型是对原序列进行 d 阶差分后,对得到的平稳序列拟合 ARMA(p,q) 模型。它是处理差分平稳序列的强大工具。
  • 从建模到预测:掌握完整的 ARIMA 建模步骤(平稳化 -> 白噪声检验 -> ARMA 建模 -> 检验与预测)及其在 Python 中的实现。

差分运算:提取确定性信息的利器

面对一个非平稳序列,我们的首要任务是将其转化为平稳序列,以便应用成熟的 ARMA 模型理论。差分运算因其简便、高效而成为首选方法。

差分运算的数学实质

差分运算的强大,在理论上由 Cramer 分解定理 所保证。该定理指出,任何时间序列 XtX_t 都可以分解为一个确定性部分和一个随机性部分:

Xt=j=0dβjtj+Ψ(B)atX_t = \sum_{j=0}^{d} \beta_j t^j + \Psi(B) a_t

其中,βjtj\sum \beta_j t^j 是确定性多项式趋势(最高阶为 dd),ata_t 是零均值的白噪声序列,Ψ(B)\Psi(B) 是延迟算子 BB 的系数多项式。

差分的实质就是对这个确定性部分进行“求导”。对于离散序列,dd 阶差分定义为:

dXt=(1B)dXt=i=0d(1)i(di)Xti\nabla^d X_t = (1 - B)^d X_t = \sum_{i=0}^{d} (-1)^i \binom{d}{i} X_{t-i}

如果原序列的确定性趋势是 dd 次多项式,那么经过 dd 阶差分后,该趋势将被完全消除,差分后的序列 dXt\nabla^d X_t 将只包含平稳的随机成分。这也解释了差分为何能服务于 ARIMA 建模:dd 阶差分把 dd 次多项式趋势消去后,剩余的平稳随机序列可再用 ARMA 刻画。

如何选择差分方式?

选择正确的差分方式是成功平稳化的关键。我们可以根据序列时序图展现的特征来决定:

  1. 线性趋势:序列呈现出明显的直线上升或下降趋势。此时,一阶差分足以提取趋势,使序列平稳。
    • 示例Xt=a+bt+εtX_t = a + bt + \varepsilon_t,则 Xt=b+(εtεt1)\nabla X_t = b + (\varepsilon_t - \varepsilon_{t-1}),消除了时间 tt
  2. 曲线趋势:序列趋势是二次或更高次的曲线。通常需要二阶或三阶差分来提取。
    • 示例Xt=a+bt+ct2+εtX_t = a + bt + ct^2 + \varepsilon_t,一阶差分后仍包含 tt,二阶差分后方为平稳。
  3. 固定周期(季节性):序列存在以固定周期 SS(如 S=12S=12 为月度数据)波动的模式。此时应采用步长为周期长度 SS 的差分(即 SS 步差分)来提取季节效应。
    • 定义SXt=XtXtS=(1BS)Xt\nabla_S X_t = X_t - X_{t-S} = (1 - B^S) X_t
    • 实践中,常将趋势差分和季节差分结合使用,例如 (1阶差分, 12步差分) 来处理既有年趋势又有月季节性的数据。

过差分:当“好刀”用过了头

差分运算虽好,但需谨防“过犹不及”。过差分是指对序列进行了超出必要次数的差分。

考虑一个具有线性趋势和白噪声的序列:Xt=β0+β1t+atX_t = \beta_0 + \beta_1 t + a_t,其中 atWN(0,σa2)a_t \sim WN(0, \sigma_a^2)

  • 一阶差分Xt=β1+(atat1)\nabla X_t = \beta_1 + (a_t - a_{t-1})。方差为 Var(Xt)=2σa2Var(\nabla X_t) = 2\sigma_a^2
  • 二阶差分(过差分)2Xt=(atat1)(at1at2)=at2at1+at2\nabla^2 X_t = (a_t - a_{t-1}) - (a_{t-1} - a_{t-2}) = a_t - 2a_{t-1} + a_{t-2}。方差为 Var(2Xt)=6σa2Var(\nabla^2 X_t) = 6\sigma_a^2

虽然二阶差分后的序列也是平稳的,但其方差(6σa26\sigma_a^2)远大于一阶差分后的方差(2σa22\sigma_a^2)。过差分无谓地增大了序列的方差,相当于浪费了有效信息,会导致模型参数估计的精度下降。因此,建模时应遵循“在保证平稳的前提下,使用最低阶差分”的原则。

ARIMA 模型:差分与 ARMA 的完美结合

当序列通过 dd 阶差分后变得平稳,我们就可以对这个平稳序列 dXt\nabla^d X_t 拟合 ARMA(p,q) 模型。这个“先差分,后 ARMA”的模型,就是 ARIMA(AutoRegressive Integrated Moving Average) 模型,记为 ARIMA(p, d, q)。

模型结构与含义

ARIMA(p, d, q) 模型的标准形式为:

Φ(B)dXt=Θ(B)εt\Phi(B) \nabla^d X_t = \Theta(B) \varepsilon_t

其中:

  • d=(1B)d\nabla^d = (1-B)^ddd 阶差分算子。
  • Φ(B)=1ϕ1BϕpBp\Phi(B) = 1 - \phi_1 B - \cdots - \phi_p B^ppp 阶自回归系数多项式。
  • Θ(B)=1θ1BθqBq\Theta(B) = 1 - \theta_1 B - \cdots - \theta_q B^qqq 阶移动平均系数多项式。
  • εtWN(0,σε2)\varepsilon_t \sim WN(0, \sigma_\varepsilon^2),且与过去的历史观测值 Xs(s<t)X_s (s < t) 不相关。

模型解读:该模型表示,对原序列 XtX_t 进行 dd 阶差分后得到的新序列 Wt=dXtW_t = \nabla^d X_t,是一个均值为零的 ARMA(p, q) 过程。

为什么叫“求和”(Integrated)? 因为差分运算 d\nabla^d 的逆运算是求和(累加)运算。ARIMA 模型可以理解为先对序列做差分化(I),再对差分后的序列做自回归移动平均(ARMA)分析。

特例:随机游走模型

d=1,p=0,q=0d=1, p=0, q=0 时,ARIMA(0,1,0) 模型简化为著名的随机游走模型

Xt=Xt1+εtX_t = X_{t-1} + \varepsilon_t

该模型描述了一个醉汉的行走路径:每一步的位置等于上一步的位置加上一个完全随机的位移。它在金融学中常被用作有效市场假说下资产价格运动的基准模型。随机游走序列是非平稳的,但其一阶差分 Xt=εt\nabla X_t = \varepsilon_t 是平稳的白噪声。

ARIMA 模型的性质

  1. 平稳性:ARIMA(p,d,q) 模型本身(指 XtX_t)是非平稳的,因为差分算子 (1B)d(1-B)^d 引入了 dd 个单位根。但经过 dd 阶差分后的序列 dXt\nabla^d X_t 是平稳的,要求 Φ(B)=0\Phi(B)=0 的根都在单位圆外。
  2. 方差齐性:当 d>0d > 0 时,原序列 XtX_t 的方差通常随时间增长(如随机游走),即具有异方差性。但差分后的序列 dXt\nabla^d X_t 满足方差齐性假定。

ARIMA 建模五步法

ARIMA 模型的建模遵循一个清晰的流程,下图概括了其核心步骤:

flowchart TD
    A[获得观察值序列] --> B{平稳性检验};
    B ----> C[差分运算];
    C --> B;
    B ----> D{白噪声检验};
    D ----> E[分析结束];
    D ----> F[拟合ARMA模型];
  1. 序列获取与观察:绘制时序图,初步判断趋势性和季节性。
  2. 平稳性检验:使用ADF检验等方法。若不平稳,进入步骤3;若平稳,跳至步骤4。
  3. 差分运算:根据时序图特征,尝试一阶、二阶或季节差分。重复步骤2,直至差分后序列通过平稳性检验。注意避免过差分。
  4. 白噪声检验:对平稳化后的序列进行Ljung-Box检验。若已是白噪声,则无需进一步建模(例如,可能就是一个随机游走)。若拒绝白噪声假设,则进入步骤5。
  5. ARMA模型建模:对平稳非白噪声序列 dXt\nabla^d X_t 进行ARMA建模,包括:
    • 模型识别:观察自相关图(ACF)和偏自相关图(PACF)初步定阶 (p, q)。
    • 参数估计:使用最大似然估计等方法。
    • 模型检验:检验残差是否为白噪声(模型显著性),并检验参数是否显著。
    • 模型优化:比较不同 (p,q) 组合的 AIC、BIC 准则,选择最优模型。
    • 预测:利用拟合好的模型进行未来值的预测。

Python 实战:从差分平稳化到 ARIMA 建模

下面,我们通过 Python 代码完整演示如何对一个具有趋势的非平稳序列进行差分平稳化处理,并验证差分的可逆性。

"""
时间序列分析 5.1 课时配套实战代码
内容:差分运算与非平稳序列平稳化 (一阶差分、ADF 检验对比与差分逆运算)
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.stats.diagnostic import acorr_ljungbox

# 设置随机种子,确保结果可复现
np.random.seed(42)
n = 200

# 1. 构建具有线性漂移项的非平稳随机游走过程: Y_t = 0.3 + Y_{t-1} + e_t
print("1. 生成具有线性趋势的非平稳序列...")
drift = 0.3  # 漂移项,即线性趋势的斜率
innovations = np.random.normal(0, 1.0, n)  # 白噪声扰动
y = np.cumsum(drift + innovations) + 50.0  # 累积求和,并设置初始水平为50
original_series = pd.Series(y, name='原始价格序列')

# 2. 原始序列单位根 (ADF) 检验
print("\n2. 对原始序列进行ADF检验...")
adf_result_raw = adfuller(original_series, autolag='AIC')
print(f"   ADF统计量: {adf_result_raw[0]:.4f}")
print(f"   P值: {adf_result_raw[1]:.4f}")
print(f"   结论: {'序列平稳' if adf_result_raw[1] < 0.05 else '序列非平稳'}")

# 3. 一阶常规差分: ∇Y_t = Y_t - Y_{t-1}
print("\n3. 对序列进行一阶差分...")
diff_series = original_series.diff().dropna()
print(f"   差分后序列长度: {len(diff_series)}")
print(f"   差分序列均值: {diff_series.mean():.4f} (理论漂移项为 {drift})")
print(f"   差分序列方差: {diff_series.var():.4f}")

# 4. 对差分后序列进行ADF检验
print("\n4. 对一阶差分序列进行ADF检验...")
adf_result_diff = adfuller(diff_series, autolag='AIC')
print(f"   ADF统计量: {adf_result_diff[0]:.4f}")
print(f"   P值: {adf_result_diff[1]:.4e}")
print(f"   结论: {'序列平稳' if adf_result_diff[1] < 0.05 else '序列非平稳'}")

# 5. 差分逆运算 (通过累加还原原始序列)
print("\n5. 验证差分运算的可逆性...")
initial_value = original_series.iloc[0]
# 通过初始值 + 差分序列的累积和来还原
recovered_series = pd.Series([initial_value] + list(initial_value + np.cumsum(diff_series.values)),
                              index=original_series.index)
# 计算还原误差
recovery_error = np.abs(original_series - recovered_series)
max_abs_error = recovery_error.max()
print(f"   最大绝对还原误差: {max_abs_error:.10f}")
print(f"   差分运算是否完美可逆: {max_abs_error < 1e-6}")

# 6. 可视化
print("\n6. 生成分析图表...")
fig, axes = plt.subplots(3, 2, figsize=(14, 10))
# 6.1 原始序列与差分序列时序图
axes[0, 0].plot(original_series, label='原始序列')
axes[0, 0].set_title('原始非平稳序列时序图')
axes[0, 0].set_xlabel('时间')
axes[0, 0].set_ylabel('值')
axes[0, 0].legend()
axes[0, 0].grid(True, linestyle='--', alpha=0.7)

axes[0, 1].plot(diff_series, label='一阶差分序列', color='orange')
axes[0, 1].axhline(y=diff_series.mean(), color='red', linestyle='--', label=f'均值={diff_series.mean():.2f}')
axes[0, 1].set_title('一阶差分后序列时序图 (已平稳)')
axes[0, 1].set_xlabel('时间')
axes[0, 1].set_ylabel('差分值')
axes[0, 1].legend()
axes[0, 1].grid(True, linestyle='--', alpha=0.7)

# 6.2 原始序列与还原序列对比
axes[1, 0].plot(original_series, label='原始序列', alpha=0.8)
axes[1, 0].plot(recovered_series, label='还原序列', linestyle='--', alpha=0.8)
axes[1, 0].set_title('原始序列 vs. 差分逆运算还原序列')
axes[1, 0].set_xlabel('时间')
axes[1, 0].set_ylabel('值')
axes[1, 0].legend()
axes[1, 0].grid(True, linestyle='--', alpha=0.7)

axes[1, 1].plot(recovery_error, label='还原误差', color='green')
axes[1, 1].axhline(y=0, color='black', linestyle='-', linewidth=0.5)
axes[1, 1].set_title('还原误差序列 (应接近0)')
axes[1, 1].set_xlabel('时间')
axes[1, 1].set_ylabel('绝对误差')
axes[1, 1].legend()
axes[1, 1].grid(True, linestyle='--', alpha=0.7)

# 6.3 差分序列的ACF和PACF (为后续ARMA建模做准备)
plot_acf(diff_series, lags=40, ax=axes[2, 0], title='差分序列自相关图 (ACF)')
plot_pacf(diff_series, lags=40, ax=axes[2, 1], title='差分序列偏自相关图 (PACF)')

plt.tight_layout()
plt.show()

# 7. 对平稳的差分序列进行白噪声检验 (Ljung-Box检验)
print("\n7. 对平稳的差分序列进行白噪声检验...")
lb_test_result = acorr_ljungbox(diff_series, lags=[10, 20], return_df=True)
print(lb_test_result)
if (lb_test_result['lb_pvalue'] > 0.05).all():
    print("   检验结果: 在常用滞后阶数下,不能拒绝原假设,差分序列可视为白噪声。")
    print("   提示: 这可能意味着原序列是一个带漂移的随机游走,无需进一步拟合ARMA模型。")
else:
    print("   检验结果: 拒绝原假设,差分序列不是白噪声,蕴含自相关结构。")
    print("   下一步: 可以依据ACF/PACF图,对该差分序列拟合ARMA(p,q)模型,即ARIMA(p,1,q)模型。")

代码输出与解读

原始非平稳序列点数: 200, 初始值: 50.7967, 终值: 101.8458
原始序列 ADF 统计量: 0.5917, p值: 0.9874 (平稳: False)
一阶差分后均值: 0.2565 (接近漂移系数 0.3), 方差: 0.8697
一阶差分后 ADF 统计量: -14.6918, p值: 3.0415e-27 (平稳: True)
差分逆运算最大还原绝对误差: 0.00000000 (完美保真: True)
  1. 平稳性检验:原始序列 ADF 检验 p 值高达 0.9874,强烈接受“存在单位根”的原假设,确认为非平稳序列。一阶差分后,p 值变为极小的 3.04e-27,强烈拒绝原假设,差分序列已变得平稳
  2. 差分效果:差分序列的均值 0.2565 接近我们构造数据时设定的漂移项 0.3,说明差分成功提取了线性趋势信息。
  3. 可逆性验证:最大还原误差为 0,证明差分运算是完全可逆的数学操作。这保证了我们在用 ARIMA 模型进行预测后,可以通过累加将差分后的预测值还原回原始序列的尺度。
  4. 后续建模指引:生成的 ACF/PACF 图和白噪声检验结果,将指导我们对平稳的差分序列进行 ARMA 模型定阶(即确定 ARIMA(p,1,q) 中的 p 和 q)。如果检验发现差分序列已是白噪声,则原序列可简单用随机游走模型描述。

📝 动手练一练

  1. 趋势识别与差分选择:假设你拿到一个公司近 10 年的季度营收数据,时序图显示其增长趋势先加速后放缓,同时每年第四季度都有一个明显的峰值。你认为应该采用哪种差分组合来处理这个序列?请说明理由。
  2. 过差分的影响:在上面的 Python 实战代码中,我们只做了一阶差分。请你修改代码,计算并对比该序列的二阶差分后的方差,并与一阶差分的方差进行对比,直观感受过差分如何“浪费信息”。

参考答案

  1. 建议采用 (1阶差分, 4步差分) 的组合。1阶差分用于提取可能的曲线趋势(对于复杂曲线趋势,有时一阶差分也能使其近似平稳,否则可尝试二阶),4步差分(因为季度数据周期为4)用于提取每年第四季度的固定季节效应。
  2. 在代码中增加 diff_series_2 = original_series.diff().diff().dropna(),然后计算其方差 diff_series_2.var()。该实战序列为带漂移的随机游走,其一阶差分方差约为 σ2=1\sigma^2=1,二阶差分方差约为 2σ2=22\sigma^2=2,二阶方差更大,直观体现了过差分会增大方差、浪费信息。

本章小结

本节我们深入探讨了分析非平稳序列的基石性方法。差分运算是基于严谨的 Cramer 分解定理,通过自回归形式提取确定性信息的强大工具。根据序列蕴含的线性趋势、曲线趋势或季节周期,我们需灵活选择一阶、高阶或步长差分。核心目标是用最低的必要差分阶数实现序列的平稳化,同时警惕过差分带来的信息浪费。

ARIMA 模型 完美地融合了差分运算与 ARMA 模型,形成了处理“差分平稳序列”的完整框架 ARIMA(p,d,q)。其建模遵循严格的五步流程:观察 -> 差分平稳化 -> 白噪声检验 -> ARMA建模 -> 检验预测。随机游走模型作为 ARIMA 的特例,为我们理解价格等序列的随机性提供了经典视角。

行动清单

  1. 实战演练:运行本节提供的 Python 代码,理解差分如何将非平稳序列变为平稳序列,并观察 ACF/PACF 图的变化。
  2. 数据诊断:找一组你感兴趣的真实时间序列数据(如股票日收盘价、月度销售额),绘制其时序图,并尝试回答:它是否需要差分?可能需要几阶差分或哪种季节差分?
  3. 模型思考:如果对一个序列进行一阶差分后,其 ACF/PACF 图显示出一阶截尾的特征,那么最适合它的 ARIMA 模型可能是什么?

— 小象教研组

配套学习资源与课件
  • 第5章课件:非平稳序列的随机性分析
    下载
  • 第5章配套代码
    下载
  • 时间序列分析推荐书籍(打包)(经典时序分析参考书合集)
    下载
  • 课程配套数据集(全课程实战数据)
    下载
🎁 免费学习资源

领取《小象 11GB VIP 课件资料包与大厂真题手册》

包含全套实战 Jupyter 源码、清洗后数据集、大厂高频面试真题与专属学员答疑交流群。

  • 完整 Python / 数据分析 Jupyter 实战源码
  • 大厂真实业务数据集与练习题
  • 微信扫码添加顾问免费领取;想学什么,直接告诉顾问
微信二维码:扫码添加课程顾问微信扫码添加顾问