当ADF检验说‘不平稳’:时间序列预测前,你还可以试试这2种平稳化方法
2026/5/28 11:30:52 网站建设 项目流程

当ADF检验说‘不平稳’:时间序列预测前,你还可以试试这2种平稳化方法

面对时间序列分析时,许多数据科学家和业务分析师都曾经历过这样的挫败:精心收集的数据,经过ADF检验后却被告知"不平稳"。这就像准备烹饪一道大餐时,发现食材还没处理好。但别急着放弃——非平稳序列并非分析的终点,而是深度理解的起点。本文将带你突破单一检验的局限,探索两种更聪明的平稳化策略,让你的预测模型重获新生。

1. 为什么ADF检验的"不平稳"结论需要谨慎对待?

ADF检验(Augmented Dickey-Fuller test)作为最常用的单位根检验方法,其核心假设是序列非平稳源于单位根存在。但现实中,非平稳性可能来自多种复杂因素:

# 典型ADF检验Python实现 from statsmodels.tsa.stattools import adfuller def adf_test(timeseries): print("ADF检验结果:") dftest = adfuller(timeseries, autolag='AIC') dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used']) for key,value in dftest[4].items(): dfoutput['Critical Value (%s)'%key] = value print(dfoutput) return dfoutput

检验结果的三大盲区

  • 趋势主导型非平稳:序列包含确定性趋势(如线性增长),但可能不存在单位根
  • 结构突变问题:2008年金融危机前后的经济数据往往呈现均值突变
  • 季节性伪非平稳:电商数据在"双十一"期间的峰值可能被误判为单位根效应

提示:当ADF检验p值接近0.05阈值时(如0.06),建议结合下文方法进行交叉验证

2. 方法一:确定性成分分解——像外科医生般精准剥离非平稳因素

这种方法的核心思想是将序列分解为确定性成分(趋势、周期)和随机成分,处理后再重组。比起粗暴的差分,它保留了更多原始信息。

2.1 操作步骤详解

  1. 趋势提取与剔除
    • 移动平均法:rolling_mean = series.rolling(window=12).mean()
    • 多项式拟合:np.polyfit配合np.polyval实现
# 使用STL分解的Python示例 from statsmodels.tsa.seasonal import STL stl = STL(series, period=12) res = stl.fit() trend_removed = series - res.trend
  1. 季节性调整

    • 经典分解法:seasonal_decompose(series, model='additive')
    • STL分解:更适合复杂季节模式
  2. 残差诊断

    • 对处理后的残差序列重新进行ADF检验
    • 检查ACF/PACF图确认自相关结构

2.2 业务场景应用案例

某零售企业2015-2023年月度销售额数据呈现明显上升趋势和年末峰值:

处理方法趋势R²季节强度残差平稳性
一阶差分0.820.15平稳
趋势剔除0.910.22平稳
完整分解0.950.05平稳

结果显示,完整分解法在保留业务解释性的同时,达到了更好的平稳化效果。

3. 方法二:KPSS+ADF联合诊断——构建双重检验防火墙

KPSS检验与ADF检验形成互补关系,就像医学诊断中的"阴性阳性"双确认:

检验假设对比

  • ADF:原假设为存在单位根(非平稳)
  • KPSS:原假设为趋势平稳(无单位根)

3.1 联合诊断决策矩阵

ADF结果KPSS结果真实状态处理建议
不拒绝拒绝含单位根非平稳需要差分
拒绝不拒绝趋势平稳移除趋势即可
拒绝拒绝差分过度减少差分阶数
不拒绝不拒绝可能含结构突变需进行断点检验
# KPSS检验实现 from statsmodels.tsa.stattools import kpss def kpss_test(timeseries): print("KPSS检验结果:") kpsstest = kpss(timeseries, regression='c', nlags='auto') kpss_output = pd.Series(kpsstest[0:3], index=['Test Statistic','p-value','Lags Used']) for key,value in kpsstest[3].items(): kpss_output['Critical Value (%s)'%key] = value print(kpss_output) return kpss_output

3.2 实际应用中的注意事项

  • 检验参数选择
    • ADF:autolag='AIC'自动选择最佳滞后阶数
    • KPSS:regression='ct'包含截距和趋势项
  • 样本量影响
    • 小样本(<50)时KPSS容易过度拒绝
    • 大样本(>1000)时ADF过于敏感
  • 临界值调整
    • 经济数据建议使用10%显著性水平
    • 高频金融数据可使用5%水平

4. 进阶技巧:当常规方法失效时的应对策略

即使经过上述处理,某些"顽固"序列仍可能表现非平稳特征。这时需要更专业的工具箱:

4.1 结构突变检测与处理

使用Bai-Perron检验检测多个断点:

from statsmodels.tsa.regime_switching.tests.test_markov_regression import breakvar_heteroskedasticity # 检测结构突变 break_points = breakvar_heteroskedasticity(series) print(f"检测到的断点位置:{break_points}")

4.2 分数差分技术

对于长记忆过程,传统整数差分可能过度:

# 分数差分实现 from statsmodels.tsa.statespace.tools import cfa_loglikelihood def fractional_diff(series, d): # ...实现分数差分算法... return diff_series

4.3 非线性变换组合

有时简单的对数变换就能解决问题:

# 常用非线性变换 transformed = np.log1p(series) # 对数变换 transformed = np.sqrt(series) # 平方根变换 transformed = boxcox(series) # Box-Cox变换

5. 模型构建前的最终检查清单

在将处理后的序列投入ARIMA等模型前,建议完成以下验证:

  1. 视觉确认

    • 绘制处理前后序列对比图
    • 观察ACF/PACF衰减模式
  2. 统计验证

    • ADF/KPSS双检验一致性
    • Ljung-Box检验残差自相关
  3. 业务合理性

    • 处理后的波动幅度是否符合业务认知
    • 季节性因素是否被适当保留/剔除
# 综合诊断函数示例 def final_check(processed_series): # 绘制图形 fig, axes = plt.subplots(3, 1, figsize=(12, 8)) axes[0].plot(processed_series) plot_acf(processed_series, ax=axes[1]) plot_pacf(processed_series, ax=axes[2]) # 统计检验 adf_result = adf_test(processed_series) kpss_result = kpss_test(processed_series) return { 'visual_inspection': 'Pass' if ... else 'Fail', 'statistical_tests': { 'ADF': adf_result['p-value'], 'KPSS': kpss_result['p-value'] } }

实践中发现,许多业务指标经过适当处理后,虽然统计检验仍显示轻微非平稳,但模型预测效果已经很好。这时不必过度追求完美的统计显著性,而应关注模型的实际预测能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询