时间序列基础:构成要素与平稳性
大家好,我是老张。今天咱们聊聊时间序列的基础知识。说实话,很多做预测的朋友一上来就上模型,结果效果惨不忍睹。为什么?因为连数据的基本特征都没搞清楚。我刚开始做滚动预测时也犯过这毛病,后来被现实狠狠教育了一回。
时间序列分析,说白了就是研究数据随时间变化的规律。你想想看,股票价格、网站流量、设备温度,这些都是时间序列。但它们的规律各不相同。我们需要先拆解这些规律,才能对症下药。
时间序列的四大构成要素
我个人习惯把时间序列拆成四个部分:趋势、季节、周期、噪声。这就像做菜,你得知道食材里有什么,才能决定怎么烹饪。
1. 趋势(Trend)
趋势是长期的变化方向。上升、下降、或者持平。比如我做过一个电商销售预测项目,数据明显呈现逐年上升趋势——用户量在涨嘛。趋势可以是线性的,也可以是非线性的。
关键点:趋势是长期、单调的。它不会来回波动。
2. 季节性(Seasonality)
季节性是指固定周期内的重复模式。周期是已知且固定的,比如一天、一周、一年。
举个例子。我做过一个电力负荷预测项目,每天都有明显的早晚高峰。这就是以24小时为周期的季节性。再比如,零售数据每年12月销量飙升——这是以年为周期的季节性。
我的经验:季节性周期必须是固定的。如果周期长度不固定,那叫周期性,不是季节性。很多人把这两个搞混,我刚开始也踩过这个坑。
3. 周期性(Cyclical)
周期性也是重复模式,但周期长度不固定。比如经济周期,繁荣-衰退-复苏,这个周期可能是3年,也可能是7年。你没法提前知道确切长度。
我曾经做过一个宏观经济指标预测,数据有明显的周期性波动,但周期长度在4-6年之间浮动。这就不能用季节性模型来处理了。
| 特征 | 季节性 | 周期性 |
|---|---|---|
| 周期长度 | 固定(如24小时、12个月) | 不固定(如3-7年) |
| 驱动因素 | 日历、气候、制度 | 经济、市场、政策 |
| 可预测性 | 高 | 低 |
4. 噪声(Noise / Residual)
噪声是去掉趋势、季节、周期后剩下的随机波动。说白了就是「解释不了的部分」。噪声是随机的,没有规律可循。
嗯,这里要注意:噪声不是错误。它是数据固有的随机性。比如传感器读数的小幅抖动,或者某天突然有个客户下了大单。这些你没法精确预测。
避坑指南:我曾经试图用复杂模型去拟合噪声,结果模型过拟合得一塌糊涂。记住,噪声就是噪声,别跟它较劲。
知识体系结构图
下面这张图帮你理清时间序列的构成要素和它们之间的关系:
平稳性:为什么它这么重要
平稳性,是时间序列建模的基石。很多模型(比如ARIMA)都要求数据是平稳的。为什么?
说白了,平稳性意味着数据的统计性质不随时间变化。均值不变、方差不变、自相关结构不变。这样模型才能从历史中学习到稳定的规律。
我举个例子。你拿过去10年的气温数据训练模型,如果气候没突变,那模型学到的规律明年还能用。但如果全球变暖导致均值逐年上升,模型就废了——它学的是「过去的规律」,不是「未来的规律」。
什么是平稳时间序列?
严格来说,平稳性分两种:
- 严平稳:联合分布不随时间平移而改变。这个条件太强,实际中很少用。
- 弱平稳(宽平稳):均值恒定、方差恒定、自协方差只与时间间隔有关。这是实际中最常用的。
弱平稳的三个条件:
- 均值 E(X_t) = μ,常数
- 方差 Var(X_t) = σ²,常数
- 自协方差 Cov(X_t, X_{t-k}) 只与 k 有关,与 t 无关
如何判断平稳性?
我一般用两种方法:
1. 肉眼观察法
画个图看看。如果数据有明显的趋势或季节性,那肯定不平稳。这个方法虽然粗糙,但很直观。我每次拿到数据第一件事就是画图。
2. 统计检验法
最常用的是ADF检验(Augmented Dickey-Fuller Test)。原假设是「序列存在单位根(不平稳)」。p值小于0.05,就拒绝原假设,认为序列平稳。
from statsmodels.tsa.stattools import adfuller
# 假设 data 是你的时间序列
result = adfuller(data)
print(f'ADF统计量: {result[0]}')
print(f'p值: {result[1]}')
if result[1] < 0.05:
print('序列平稳,可以建模')
else:
print('序列不平稳,需要差分')
我的习惯:不要只看p值。结合图形和业务知识一起判断。有时候p值显示平稳,但图形明显有趋势——那可能是样本量太小导致的误判。
差分:让不平稳变平稳的利器
如果数据不平稳怎么办?最常用的方法就是差分。
差分,就是计算相邻时间点的差值。一阶差分:ΔX_t = X_t - X_{t-1}。如果一阶差分后还不平稳,就做二阶差分。
为什么差分有效?因为很多不平稳的来源是趋势。差分可以消除线性趋势。你想想看,如果数据是直线上升,那相邻点的差值就是常数——这不就平稳了吗?
# 一阶差分示例
import numpy as np
data = [10, 12, 15, 13, 18, 20]
diff_1 = np.diff(data)
print(f'原始数据: {data}')
print(f'一阶差分: {diff_1}')
# 输出: [2, 3, -2, 5, 2]
避坑指南:我曾经在一个项目中对数据做了三次差分,结果模型预测值全是负数——因为过度差分丢失了原始数据的量纲信息。记住,差分次数不是越多越好。一般不超过2次。
实战中的选择策略
拿到一个时间序列,我一般按这个流程走:
- 画图观察:看有没有趋势、季节、周期
- 做ADF检验:确认是否平稳
- 如果不平稳:先差分,再检验
- 如果还不行:考虑对数变换或Box-Cox变换,稳定方差
- 分解成分:用STL或X13-ARIMA把趋势、季节、残差拆开
嗯,这个流程我用了好多年,基本没出过大问题。当然,具体场景要灵活调整。
好了,时间序列的基础就聊到这儿。记住一句话:理解数据的构成,是做好预测的第一步。别急着上模型,先看看你的数据里有什么。