时间序列平稳性:从理论到实战检验指南

张开发
2026/4/10 12:14:31 15 分钟阅读

分享文章

时间序列平稳性:从理论到实战检验指南
1. 为什么时间序列需要平稳性想象一下你每天记录体重变化。如果体重在60kg上下小幅波动比如59.5kg到60.5kg我们很容易预测明天的体重大概率也在60kg附近。但如果体重每周增加1kg从60kg持续增长到70kg用过去的数据预测未来就会产生系统性偏差——这就是非平稳序列带来的核心问题。平稳性的三大基石在技术层面表现为均值稳定就像体重秤的指针不会长期偏向某一侧方差恒定波动幅度不会忽大忽小今天±0.5kg下周突然变成±2kg自协方差一致今天和昨天体重的关联度与下周任意两天之间的关联度相同实际建模中90%以上的经典时间序列模型ARIMA、VAR等都依赖平稳性假设。我曾用非平稳的销售数据直接训练模型结果预测误差比随机猜测还大30%。后来发现当序列存在趋势时模型会错误地将历史趋势外推而真实世界的数据趋势往往不会无限延续。2. 平稳性检验的四大实战方法2.1 肉眼观察法先看再算我习惯先用Python画三个关键图形import matplotlib.pyplot as plt from statsmodels.tsa.seasonal import seasonal_decompose # 原始序列观察 plt.figure(figsize(12,6)) plt.plot(data) plt.title(Raw Time Series) # 滚动统计量检测 rolling_mean data.rolling(window12).mean() rolling_std data.rolling(window12).std() plt.plot(rolling_mean, colorred, labelRolling Mean) plt.plot(rolling_std, colorblack, labelRolling Std) # 季节性分解 decomposition seasonal_decompose(data, modeladditive) decomposition.plot()典型非平稳特征包括滚动均值线呈明显上升/下降趋势均值不稳定滚动标准差持续扩大方差时变季节性分解后的残差项仍存在规律性波动2.2 ADF检验最常用的定量检测Augmented Dickey-Fuller检验通过python的statsmodels实现from statsmodels.tsa.stattools import adfuller result adfuller(data[value], autolagAIC) print(fADF Statistic: {result[0]}) print(fp-value: {result[1]}) print(Critical Values:) for key, value in result[4].items(): print(f {key}: {value})结果解读三要点当p-value ≤0.05时我们有95%把握拒绝非平稳的原假设ADF统计量比临界值更负时如-3.5-2.9表明平稳性显著注意选择适当的autolag参数AIC/BIC防止过拟合去年分析电商数据时一个季节性序列的ADF检验p值为0.12看似不平稳。但经过季节性差分后p值降到了0.003——这说明原始序列是季节性非平稳。2.3 KPSS检验ADF的黄金搭档KPSS检验的假设与ADF相反from statsmodels.tsa.stattools import kpss result kpss(data[value], regressionc) print(fKPSS Statistic: {result[0]}) print(fp-value: {result[1]})组合策略ADF平稳 KPSS平稳严格平稳可直接建模ADF不平稳 KPSS平稳趋势平稳需去趋势ADF平稳 KPSS不平稳差分平稳需差分处理双不平稳需综合转换如对数差分2.4 单位根检验的工程实践在物联网设备监测中遇到过温度传感器数据呈现伪平稳现象——ADF检验通过但实际存在周期性突变。后来采用组合检验先进行ADF/KPSS基础检验对通过检验的数据段进行滑动窗口验证最终结合领域知识如设备工作原理判断3. 从检验到处理的完整 pipeline3.1 差分处理的实战技巧一阶差分是万能药未必。我在金融数据预处理中踩过的坑# 错误做法盲目高阶差分 over_diff data.diff().diff().diff() # 正确做法基于ADF结果选择阶数 from pmdarima.arima.utils import ndiffs optimal_diff ndiffs(data, testadf) # 自动确定最佳差分阶数差分经验法则股价数据通常1阶差分即可经济指标可能需要季节性差分如月度数据做12期差分差分后务必检查是否过差分表现为ACF/PACF截尾3.2 趋势消除的三种武器多项式拟合适合明确趋势形态的场景from sklearn.preprocessing import PolynomialFeatures poly PolynomialFeatures(degree2) X np.arange(len(data)).reshape(-1,1) model LinearRegression().fit(poly.fit_transform(X), data) detrended data - model.predict(poly.transform(X))移动平均法对突变趋势更鲁棒window_size 12 # 根据业务周期设定 trend data.rolling(windowwindow_size).mean() detrended data - trendSTL分解适合复杂趋势季节性的组合from statsmodels.tsa.seasonal import STL res STL(data, period12).fit() detrended data - res.trend3.3 方差稳定的对数变换当序列存在指数趋势时我常用Box-Cox变换from scipy.stats import boxcox transformed, lam boxcox(data[value]) print(fOptimal lambda: {lam})λ值接近0时等价于对数变换这在处理金融量级数据时特别有效。4. 综合案例电商销量数据分析4.1 原始数据诊断拿到某品类3年日销量数据ADF检验p值0.87强烈非平稳KPSS检验p值0.01拒绝平稳假设滚动标准差显示季度性爆发黑五增长300%4.2 分阶段处理方案首阶处理对数变换压缩方差log_data np.log1p(data)二阶处理季节性差分diff_7 log_data.diff(7).dropna() # 周周期最终检验ADF p值降至0.003KPSS p值升至0.12滚动统计量呈现稳定波动4.3 建模效果对比使用处理前后的数据训练ARIMA(1,1,1)模型原始数据测试集MAPE62%平稳化数据MAPE降至18%加入外部变量促销信息后MAPE11%这个案例让我深刻体会到平稳化处理虽然增加了前期工作量但能避免模型学到虚假规律。就像盖楼前打地基看似费时却是质量保证的关键。

更多文章