第一章:时间序列基础

大家好,我是你们这门课的主讲。今天咱们聊聊时间序列最基础的东西。说实话,这部分内容看起来简单,但我在实际项目中见过太多人在这里翻车了。你想想看,如果连数据是不是平稳的都搞不清楚,后面那些花里胡哨的模型,跑出来全是废的。

1.1 时间序列到底是什么?

时间序列,说白了就是按时间顺序排列的一组数据点。比如股票每天的收盘价、某个城市每小时的温度、网站每秒钟的访问量——这些都是时间序列。

我个人习惯把时间序列拆成三个要素来看:

  • 时间索引:数据点对应的时间戳,必须是有序的
  • 观测值:每个时间点上的具体数值
  • 采样频率:数据点之间的时间间隔,比如日频、小时频、分钟频

我在项目中遇到过一件事:有个同事拿到的数据看起来是日频的,结果仔细一看,周末的数据全丢了,而且没有任何标记。他直接用这个数据跑ARIMA模型,结果预测值全偏了。嗯,这里要注意——时间序列的第一个坑,就是时间索引必须完整且连续。

1.2 平稳性——这个坎你必须过

平稳性这个概念,我刚开始学的时候也觉得挺抽象的。后来做多了就明白了:平稳性就是数据的统计性质不随时间变化。

具体来说,一个时间序列如果是严格平稳的,它的联合分布在任何时间偏移下都保持不变。但实际应用中我们更常用的是弱平稳(也叫宽平稳),要求三条:

  1. 均值恒定:E(X_t) = μ,不随时间变化
  2. 方差恒定:Var(X_t) = σ²,不随时间变化
  3. 协方差只与时间间隔有关:Cov(X_t, X_{t-k}) = γ(k),与具体时间点t无关

为什么平稳性这么重要?

因为大多数时间序列模型(ARIMA、GARCH等)都假设数据是平稳的。如果数据不平稳,模型会学到虚假的规律,预测结果基本就是扯淡。

我曾经接手过一个项目,对方用非平稳的GDP数据直接跑回归,R²高达0.95,看起来完美极了。结果一做样本外测试,预测值和实际值差了十万八千里。这就是典型的伪回归——两个不相关的非平稳序列,只是因为都有上升趋势,就产生了虚假的相关性。

1.3 自相关与偏自相关

自相关(ACF)这个概念,说白了就是看当前时刻的值和过去某个时刻的值之间有没有线性关系。比如今天的温度和昨天的温度肯定有关系,这就是自相关。

偏自相关(PACF)稍微绕一点。它衡量的是,在剔除了中间所有滞后项的影响之后,当前值和某个滞后值之间的直接相关性。

我举个例子你就明白了:假设今天的股价受昨天影响,昨天又受前天影响。那么今天和前天之间其实是有间接相关的。ACF会把这种间接相关也算进去,而PACF只保留直接的那部分。

我的经验之谈:

看ACF和PACF图的时候,别光盯着那些显著性阈值线。我习惯先看整体衰减模式——是快速衰减还是缓慢衰减?快速衰减通常意味着平稳,缓慢衰减往往暗示非平稳。这个判断比看几个点是否超出阈值要靠谱得多。

1.4 白噪声检验

白噪声,就是纯随机序列。它的均值是0,方差恒定,而且不同时间点的值之间没有任何相关性。说白了,就是完全不可预测的噪声。

为什么要做白噪声检验?因为如果你的模型已经把数据中的规律都提取干净了,剩下的残差就应该是白噪声。如果不是,说明模型还有信息没捕捉到。

常用的检验方法有:

检验方法 原假设 适用场景
Ljung-Box检验 数据是白噪声 最常用,小样本也适用
Box-Pierce检验 数据是白噪声 大样本下近似
Durbin-Watson检验 无一阶自相关 只检查滞后1期

注意:Ljung-Box检验的p值如果大于0.05,说明不能拒绝原假设,即残差是白噪声。但别只看p值——我建议同时画个ACF图看看,有时候p值通过了,但ACF图上某个滞后项明显异常,这种情况也要警惕。

下面我用Python演示一下完整的流程:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller, acf, pacf
from statsmodels.stats.diagnostic import acorr_ljungbox

# 生成一个非平稳序列(带趋势)
np.random.seed(42)
t = np.arange(100)
y = 0.5 * t + np.random.randn(100)

# 1. 平稳性检验(ADF检验)
result = adfuller(y)
print(f'ADF统计量: {result[0]:.4f}')
print(f'p值: {result[1]:.4f}')
# p值大于0.05,说明非平稳

# 2. 做一阶差分
y_diff = np.diff(y)

# 再次检验
result_diff = adfuller(y_diff)
print(f'差分后ADF统计量: {result_diff[0]:.4f}')
print(f'差分后p值: {result_diff[1]:.4f}')
# p值小于0.05,说明差分后平稳了

# 3. 计算ACF和PACF
lag_acf = acf(y_diff, nlags=20)
lag_pacf = pacf(y_diff, nlags=20)

# 4. 白噪声检验
lb_result = acorr_ljungbox(y_diff, lags=[10, 20], return_df=True)
print(lb_result)
# p值大于0.05,说明差分后的序列是白噪声

这段代码我用了很多次,基本套路就是:先检验平稳性 → 不平稳就差分 → 再检验 → 看ACF/PACF → 最后检查残差是不是白噪声。

知识体系总览

下面这张图把本章的核心逻辑串起来了,你可以对照着看:

时间序列基础 - 知识体系 时间序列基础 时间序列定义 平稳性概念 自相关与偏自相关 白噪声检验 时间索引 观测值 采样频率 均值恒定 方差恒定 协方差稳定 ACF(总相关) PACF(直接相关) 模型定阶依据 Ljung-Box检验 残差诊断 四个核心概念层层递进,构成时间序列分析的基础框架

这张图把四个核心概念的关系画清楚了。你看,从定义出发,到平稳性判断,再到自相关分析,最后用白噪声检验收尾——这是一个完整的分析链条。我在实际项目中,基本就是按这个流程走的。

一个小建议:刚开始学的时候,别急着上复杂模型。先把这四步走扎实了,后面学什么模型都顺手。我见过太多人一上来就调ARIMA的参数,结果连数据是不是平稳的都没搞清楚——这种习惯要不得。

专注资料整理