3. 平稳性检验:平稳性的定义与重要性、ADF检验、KPSS检验、差分操作

3.1 平稳性——时间序列分析的“地基”

做时间序列分析,第一个绕不开的概念就是平稳性

说白了,平稳性就是要求你的数据在时间轴上“表现稳定”。具体来说,一个平稳的时间序列,它的均值、方差、自协方差都不会随着时间推移而发生系统性变化。

举个例子,你每天记录办公室的温度。如果空调一直开着,温度在22度上下波动,这就是平稳的。但如果从冬天记录到夏天,温度从零下升到三十多度,那就不平稳了——均值在变。

为什么平稳性这么重要?

我个人习惯把时间序列模型想象成一个“模式识别器”。模型从历史数据中学习规律,然后外推到未来。如果数据本身都不稳定,规律一直在变,模型学到的就是“假规律”。

我在项目中遇到过不少新手,拿到数据就直接套ARIMA模型,结果预测结果一塌糊涂。回头一看,数据压根没做平稳性检验。嗯,这坑我踩过,所以今天重点讲清楚。

核心要点: 平稳性是时间序列建模的前提条件。非平稳数据会导致“伪回归”问题,模型看似拟合得很好,实则毫无意义。

3.2 平稳性的严格定义

平稳性有两种定义,我们常用的是弱平稳(也叫宽平稳)。

一个时间序列 {Xt} 满足以下三个条件,就认为是弱平稳的:

  1. 均值恒定: E(Xt) = μ,与时间 t 无关
  2. 方差恒定: Var(Xt) = σ²,与时间 t 无关
  3. 自协方差只与时间间隔有关: Cov(Xt, Xt+k) = γ(k),与起始时间 t 无关

你想想看,第三条其实很关键。它意味着序列的“记忆模式”是稳定的。比如今天和明天的相关性,跟昨天和今天的相关性应该是一样的,不会因为时间推移而改变。

还有一种叫强平稳,要求整个概率分布都不随时间变化。这个条件太苛刻,实际应用中很少用。

3.3 为什么要检验平稳性?

我总结了几条血的教训:

  • 避免伪回归: 两个毫无关系的非平稳序列,可能计算出很高的相关系数。比如“中国GDP”和“美国某地降雨量”,你硬算相关性可能很高,但这完全是虚假的。
  • 模型可解释: 平稳序列的统计特性(均值、方差)是有实际意义的。非平稳序列的均值一直在变,你算出来的“平均”毫无意义。
  • 预测更可靠: 平稳序列的波动模式是稳定的,模型可以捕捉到真正的规律,而不是被趋势带偏。
注意: 不要以为画个折线图看看趋势就能判断平稳性。肉眼判断非常不靠谱,必须用统计检验方法。

3.4 ADF检验——最常用的单位根检验

ADF检验(Augmented Dickey-Fuller Test)是检验平稳性的“标配”工具。它的核心思想是:检验序列是否存在单位根

什么是单位根?简单理解,如果序列的当前值完全由上一期的值决定(加上一个随机扰动),那这个序列就有一个单位根,是非平稳的。

ADF检验的假设是这样的:

  • 原假设 H₀: 序列存在单位根(非平稳)
  • 备择假设 H₁: 序列不存在单位根(平稳)

p值小于0.05,就拒绝原假设,认为序列是平稳的。反之,p值大于0.05,就不能拒绝原假设,序列是非平稳的。

我曾经在一个金融项目中,用ADF检验股票收益率序列。一开始p值0.3,明显非平稳。后来做了差分,p值降到0.001,这才放心建模。

Python代码实现很简单:

from statsmodels.tsa.stattools import adfuller

# 假设 data 是你的时间序列数据
result = adfuller(data)
print(f'ADF统计量: {result[0]}')
print(f'p值: {result[1]}')
print(f'临界值: {result[4]}')

# 判断
if result[1] < 0.05:
    print('序列是平稳的')
else:
    print('序列是非平稳的')
小技巧: ADF检验有3种模式:不带常数项、带常数项、带常数项和趋势项。一般建议先用带常数项和趋势项的版本,如果显著平稳,再逐步简化。我个人习惯直接用默认设置,大多数情况下够用。

3.5 KPSS检验——与ADF互补

ADF检验的缺点是“检验力”有限。有时候序列明明是非平稳的,ADF却判断为平稳。这时候就需要KPSS检验来帮忙。

KPSS检验(Kwiatkowski-Phillips-Schmidt-Shin Test)的假设正好反过来:

  • 原假设 H₀: 序列是平稳的
  • 备择假设 H₁: 序列存在单位根(非平稳)

你发现没有?ADF和KPSS是“对立的”。我建议两个检验一起做,交叉验证:

ADF结果 KPSS结果 结论
平稳 平稳 序列平稳
非平稳 非平稳 序列非平稳
平稳 非平稳 可能存在趋势平稳(需要去趋势)
非平稳 平稳 可能存在差分平稳(需要差分)

KPSS的Python代码:

from statsmodels.tsa.stattools import kpss

result = kpss(data, regression='c')
print(f'KPSS统计量: {result[0]}')
print(f'p值: {result[1]}')

if result[1] < 0.05:
    print('序列是非平稳的')
else:
    print('序列是平稳的')
注意: KPSS检验的 regression 参数可以选 'c'(常数项)或 'ct'(常数项+趋势项)。如果数据有明显趋势,建议用 'ct'。

3.6 差分操作——让非平稳变平稳的“手术刀”

如果检验发现序列非平稳,怎么办?最常用的方法就是差分

一阶差分的公式很简单:

ΔXt = Xt - Xt-1

说白了,就是把相邻两个时间点的值相减。这样做的效果是:消除趋势

你想想看,如果序列有线性趋势(比如每年增长5%),差分后就会变成围绕0波动的平稳序列。

有时候一阶差分还不够,需要二阶差分:

Δ²Xt = ΔXt - ΔXt-1

Python实现:

import numpy as np

# 一阶差分
diff_1 = np.diff(data, n=1)

# 二阶差分
diff_2 = np.diff(data, n=2)

# 或者用pandas
import pandas as pd
series = pd.Series(data)
diff_1_pd = series.diff().dropna()
经验之谈: 大多数经济金融数据,一阶差分就够了。二阶差分很少用,因为差分次数越多,信息损失越大。我曾经处理过某商品价格数据,差分到第3次才平稳,但模型预测效果反而更差了——因为过度差分把真实规律也“差”掉了。

3.7 本章知识体系

下面这张图总结了平稳性检验的核心逻辑:

平稳性检验知识体系 原始时间序列 平稳性检验 ADF检验(原假设:非平稳) | KPSS检验(原假设:平稳) ✅ 平稳 → 直接建模 ⚠️ 非平稳 → 需要处理 差分操作(一阶/二阶)

这张图把整个流程串起来了:拿到原始序列 → 做ADF和KPSS检验 → 判断是否平稳 → 平稳则建模,非平稳则差分 → 差分后再检验,直到平稳为止。

嗯,这就是平稳性检验的完整套路。我个人建议,每次建模前都走一遍这个流程,养成习惯。别嫌麻烦,这步省了,后面全是坑。


公众号:蓝海资料掘金营,微信deep3321