3. 时间序列分析:平稳性检验、ACF/PACF与ARIMA模型

各位同学,今天我们来啃一块硬骨头——时间序列分析。说实话,我刚入行那会儿,觉得这玩意儿就是一堆数学公式堆砌出来的玄学。直到我在一个园区多能互补项目里,被负荷预测的误差折磨得够呛,才真正意识到:不懂时间序列,你连数据的大门都摸不着

咱们今天要聊的三个核心:平稳性检验(ADF)自相关与偏自相关函数(ACF/PACF)、以及ARIMA模型。说白了,就是一套从数据清洗到建模预测的完整流水线。

3.1 平稳性:时间序列的“定海神针”

什么叫平稳?我打个比方。你站在海边看浪,如果浪高基本稳定在一个范围,没有突然涨潮退潮,那就是平稳。如果海啸来了,浪高瞬间翻倍,那就是非平稳。

在数学上,平稳性要求序列的均值、方差、自协方差不随时间变化。为什么要这么严格?因为ARIMA模型本质上是在“学习”数据的统计规律,如果规律本身一直在变,模型就学了个寂寞。

核心要点: 非平稳数据直接建模,大概率得到“伪回归”——看着拟合得很好,一预测就翻车。

3.1.1 ADF检验:给平稳性“体检”

ADF(Augmented Dickey-Fuller)检验,是我最常用的平稳性检测工具。它的原理不复杂:假设数据存在单位根(非平稳),然后看能不能推翻这个假设。

我个人习惯用Python的statsmodels库,一行代码搞定:

from statsmodels.tsa.stattools import adfuller

# 假设data是你的负荷序列
result = adfuller(data, autolag='AIC')
print(f'ADF统计量: {result[0]:.4f}')
print(f'p值: {result[1]:.4f}')
print(f'临界值: {result[4]}')

# 判断逻辑
if result[1] < 0.05:
    print('数据平稳,可以继续建模')
else:
    print('数据非平稳,需要差分处理')

避坑指南: 我曾经在一个光伏出力预测项目里,p值刚好0.051,差一点点就平稳了。当时我偷懒没做差分,结果模型在晴天表现完美,一到阴雨天就崩。后来老老实实做了一阶差分,才稳住。记住:p值小于0.05才算平稳,别卡着边界赌运气

3.2 ACF与PACF:模型的“指纹识别”

数据平稳了,下一步就是确定ARIMA模型的阶数。这时候ACF和PACF就派上用场了。

  • ACF(自相关函数):衡量当前值与过去值的相关性。比如今天负荷和昨天、前天的关系。
  • PACF(偏自相关函数):剔除中间变量干扰后,当前值与特定滞后值的“纯”相关性。

怎么用?我总结了一个口诀:

口诀:
ACF拖尾,PACF截尾 → 用AR模型
ACF截尾,PACF拖尾 → 用MA模型
两者都拖尾 → 用ARIMA模型

举个例子。我在一个冷热电三联供项目里,分析建筑负荷的ACF/PACF图:

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(data_diff, lags=20, ax=ax1)
plot_pacf(data_diff, lags=20, ax=ax2)
plt.show()

当时我看到ACF在滞后1阶后迅速衰减(截尾),PACF则缓慢下降(拖尾)。嗯,这明显是MA(1)的特征。但实际建模时,我建议你不要完全依赖肉眼判断,结合AIC/BIC准则自动选阶更靠谱。

3.3 ARIMA模型:从原理到实战

ARIMA(p,d,q)三个参数,分别对应:

参数 含义 如何确定
p 自回归阶数 看PACF截尾位置
d 差分阶数 ADF检验确定,通常0或1
q 移动平均阶数 看ACF截尾位置

建模步骤其实就五步,我习惯叫它“五步成诗法”:

  1. 可视化:先画图,看趋势、季节性和异常值。
  2. 平稳化:ADF检验,不平稳就差分。
  3. 定阶:画ACF/PACF,或者用自动搜索(比如pmdarima库)。
  4. 拟合:用ARIMA函数训练模型。
  5. 诊断:检查残差是否为白噪声。

来看一段完整的代码:

from statsmodels.tsa.arima.model import ARIMA
import pmdarima as pm

# 自动搜索最优参数(强烈推荐)
model = pm.auto_arima(data, seasonal=False, trace=True,
                      error_action='ignore', suppress_warnings=True)
print(model.summary())

# 手动建模
model = ARIMA(data, order=(1, 1, 1))
model_fit = model.fit()
print(model_fit.summary())

# 预测未来24小时
forecast = model_fit.forecast(steps=24)
print('预测结果:', forecast)
注意: 自动搜索虽然方便,但计算量大。我一般先用ACF/PACF缩小搜索范围,比如p和q都限制在0~3之间,再让机器去跑。这样既快又准。

3.4 知识体系总览

为了让你更直观地理解整个流程,我画了一张图:

时间序列分析流程 原始数据 ADF平稳性检验 p值 < 0.05? ACF/PACF定阶 确定p, q ARIMA建模 差分处理 d = d + 1 残差诊断 白噪声? 负荷预测 图例: 数据准备 检验/判断 建模

这张图把整个流程串起来了。你从原始数据出发,先做ADF检验。如果平稳,直接画ACF/PACF定阶;如果不平稳,差分后再回来检验。最后建模、诊断、预测,一气呵成。

我的经验: 在实际的多能互补系统中,负荷数据往往有很强的周期性(比如24小时、7天)。这时候可以考虑季节性ARIMA(SARIMA),效果会好很多。不过那是下一阶段的内容了,今天先把基础打牢。

好了,时间序列分析的核心就这些。记住:平稳性是前提,ACF/PACF是工具,ARIMA是武器。下次你拿到负荷数据,别急着建模,先问问自己:数据平稳了吗?阶数选对了吗?残差检查了吗?

嗯,今天就到这里。代码多跑几遍,你会有感觉的。


专注资料整理