Day 56 时序数据的检验

文章目录

  • [Day 56 · 时序数据的检验](#Day 56 · 时序数据的检验)
    • 环境准备
    • 一、假设检验基础
      • [1.1 原假设与备择假设](#1.1 原假设与备择假设)
      • [1.2 统计量与P值](#1.2 统计量与P值)
    • 二、白噪声检验
      • [2.1 白噪声的定义](#2.1 白噪声的定义)
      • [2.2 ACF检验(自相关函数检验)](#2.2 ACF检验(自相关函数检验))
      • [2.3 PACF检验(偏自相关函数检验)](#2.3 PACF检验(偏自相关函数检验))
      • [2.4 Ljung-Box检验](#2.4 Ljung-Box检验)
    • 三、平稳性检验
      • [3.1 平稳性的定义](#3.1 平稳性的定义)
      • [3.2 ADF检验(单位根检验)](#3.2 ADF检验(单位根检验))
    • 四、季节性检验
      • [4.1 季节性的定义](#4.1 季节性的定义)
      • [4.2 通过ACF图检测季节性](#4.2 通过ACF图检测季节性)
      • [4.3 通过序列分解检测季节性](#4.3 通过序列分解检测季节性)
    • 五、总结
      • [5.1 检验流程](#5.1 检验流程)
      • [5.2 检验方法速查表](#5.2 检验方法速查表)

Day 56 · 时序数据的检验

在学习时间序列预测模型之前,我们需要掌握时序数据的检验方法。本节将系统介绍假设检验的基本概念,以及白噪声检验、平稳性检验和季节性检验的原理与实现。

环境准备

python 复制代码
# 导入必要的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf  # 绘制自相关/偏自相关图
from statsmodels.stats.diagnostic import acorr_ljungbox  # Ljung-Box检验
from statsmodels.tsa.stattools import adfuller  # ADF检验
from statsmodels.tsa.seasonal import seasonal_decompose  # 序列分解
import warnings
warnings.filterwarnings("ignore")

# 中文显示设置
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示为方块的问题

一、假设检验基础

1.1 原假设与备择假设

核心思想:在统计学中,我们不能直接证明一件事是什么,而是先假设它不是,然后用证据去推翻这个假设。

类比理解

  • 在法庭上,嫌疑人在被定罪前被假设为无罪(原假设 H0)
  • 检察官需要提供证据证明嫌疑人有罪(备择假设 H1)

原假设的特点

  • 通常是一个清晰、单一的状态
  • 用数学语言表示为等式形式(如:罪 = 0)
  • 是我们想要挑战或推翻的假设

备择假设的特点

  • 是原假设的对立面
  • 通常是我们期待证明的、有价值的发现

1.2 统计量与P值

统计量

  • 反映样本数据偏离原假设的程度
  • 统计量的值越大,说明两组数据的差异越明显

P值(p-value)

  • 证据强度的量化指标
  • 回答的核心问题:如果原假设是真的,我们现在看到的证据有多大可能性纯属巧合?
  • P值越小,说明证据越与原假设格格不入

显著性水平

  • 通常设定为 0.05(即5%)
  • p-value < 0.05:拒绝原假设(reject H0)
  • p-value >= 0.05:无法拒绝原假设(fail to reject H0)

置信区间

  • 落在置信区间内 -> 无法拒绝原假设
  • 落在置信区间外 -> 拒绝原假设

记忆口诀:p越小,落在置信区间外,越拒绝原假设。


二、白噪声检验

2.1 白噪声的定义

为什么要检验白噪声?

  • 时序预测的前提是数据本身具有可预测性
  • 完全随机的序列(白噪声)是不可预测的
  • 白噪声的未来值与过去值没有任何相关性

白噪声的三大特征

  1. 均值为0
  2. 方差恒定
  3. 自相关性为0(过去的值对未来的值没有影响)
python 复制代码
# 生成白噪声序列
np.random.seed(42)  # 设置随机种子,保证结果可复现
num_points = 200  # 序列长度

# 从标准正态分布(均值为0,方差为1)中抽取随机样本
random_sequence = np.random.randn(num_points)

print("生成的前10个数据点:")
print(random_sequence[:10])

# 可视化白噪声序列
plt.figure(figsize=(12, 6))
plt.plot(random_sequence, label='Random Sequence (White Noise)', alpha=0.8)
plt.axhline(y=0, color='r', linestyle='--', label='Mean')
plt.title('White Noise Sequence Visualization', fontsize=16)
plt.xlabel('Time Step', fontsize=12)
plt.ylabel('Value', fontsize=12)
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()
plt.show()
复制代码
生成的前10个数据点:
[ 0.49671415 -0.1382643   0.64768854  1.52302986 -0.23415337 -0.23413696
  1.57921282  0.76743473 -0.46947439  0.54256004]

2.2 ACF检验(自相关函数检验)

ACF(Autocorrelation Function)

  • 衡量序列与其滞后版本之间的相关性
  • 对于白噪声,只有lag=0时相关性为1,其他滞后的相关性都应在置信区间内

ACF图的解读

  • 蓝色阴影区域:95%置信区间
  • 如果所有滞后项都在置信区间内,说明序列可能是白噪声
python 复制代码
# 检验白噪声属性
print("--- Start White Noise Test ---")
print(f"1. Mean of sequence: {random_sequence.mean():.4f}")
print("   (Conclusion: Mean is very close to 0, condition satisfied.)\n")

print(f"2. Variance of sequence: {random_sequence.var():.4f}")
print("   (Conclusion: Variance is close to 1, condition satisfied.)\n")

print("3. Test autocorrelation (using ACF plot):")
print("   - ACF plot shows correlation between sequence and its lagged values.")
print("   - For white noise, only lag=0 has correlation=1, others should be within confidence interval.")

# 绘制ACF图
fig, ax = plt.subplots(figsize=(12, 5))
plot_acf(random_sequence, lags=40, ax=ax, alpha=0.05)  # alpha=0.05表示95%置信区间
ax.set_title('ACF Plot of White Noise Sequence', fontsize=14)
ax.set_xlabel('Lag', fontsize=12)
ax.set_ylabel('Autocorrelation', fontsize=12)
plt.tight_layout()
plt.show()
复制代码
--- Start White Noise Test ---
1. Mean of sequence: -0.0408
   (Conclusion: Mean is very close to 0, condition satisfied.)

2. Variance of sequence: 0.8624
   (Conclusion: Variance is close to 1, condition satisfied.)

3. Test autocorrelation (using ACF plot):
   - ACF plot shows correlation between sequence and its lagged values.
   - For white noise, only lag=0 has correlation=1, others should be within confidence interval.

2.3 PACF检验(偏自相关函数检验)

PACF(Partial Autocorrelation Function)

  • 衡量序列与其第k阶滞后之间的直接相关性
  • 直观理解:把中间滞后项(lag=1...k-1)的影响剔除后,看 y(t) 与 y(t-k) 是否仍有线性关系

ACF vs PACF

  • ACF:总体相关性(包含间接影响)
  • PACF:直接相关性(剔除间接影响)

对白噪声的判断

  • 如果各滞后阶(lag>0)都落在置信区间内,说明没有显著相关性,序列可能是白噪声
python 复制代码
# 绘制PACF图
fig, ax = plt.subplots(figsize=(12, 5))
plot_pacf(random_sequence, lags=40, ax=ax, alpha=0.05)  # alpha=0.05表示95%置信区间
ax.set_title('PACF Plot of White Noise Sequence', fontsize=14)
ax.set_xlabel('Lag', fontsize=12)
ax.set_ylabel('Partial Autocorrelation', fontsize=12)
plt.tight_layout()
plt.show()

2.4 Ljung-Box检验

检验目的:综合检验多个滞后阶的自相关性是否显著

假设设定

  • 原假设 (H0):序列是白噪声(各阶自相关系数都为0)
  • 备择假设 (H1):序列不是白噪声

判断标准

  • p-value >= 0.05 -> 无法拒绝原假设,认为序列是白噪声
  • p-value < 0.05 -> 拒绝原假设,认为序列不是白噪声
python 复制代码
# Ljung-Box检验
print("=" * 50)
print("Ljung-Box Test")
print("=" * 50)
print("   - H0: Sequence is white noise.")
print("   - Criterion: If p-value >= 0.05, cannot reject H0, sequence is white noise.")

# 执行Ljung-Box检验,检查前10、20、30个滞后项
ljung_box_result = acorr_ljungbox(random_sequence, lags=[10, 20, 30], return_df=True)

print("\nLjung-Box Test Results:")
print(ljung_box_result)

# 结论解释
print("\n--- Test Conclusion ---")
last_p_value = ljung_box_result.iloc[-1]['lb_pvalue']  # 获取最后一个滞后阶的p值

if last_p_value < 0.05:
    print(f"At lag 30, p-value ({last_p_value:.4f}) < 0.05.")
    print("Conclusion: Reject H0, sequence is NOT white noise.")
else:
    print(f"At lag 30, p-value ({last_p_value:.4f}) >= 0.05.")
    print("Conclusion: Cannot reject H0, sequence IS white noise.")
复制代码
==================================================
Ljung-Box Test
==================================================
   - H0: Sequence is white noise.
   - Criterion: If p-value >= 0.05, cannot reject H0, sequence is white noise.

Ljung-Box Test Results:
      lb_stat  lb_pvalue
10   8.849179   0.546474
20  18.264036   0.570020
30  21.000649   0.887868

--- Test Conclusion ---
At lag 30, p-value (0.8879) >= 0.05.
Conclusion: Cannot reject H0, sequence IS white noise.

结果解读

  • lb_stat:Ljung-Box统计量的值(证据强度)
  • lb_pvalue:p值(判断依据)
  • 行索引 10, 20, 30:综合考虑了前10个、前20个、前30个滞后项的自相关性

所有的p值都远大于0.05,代表无法拒绝原假设,序列是白噪声。


三、平稳性检验

3.1 平稳性的定义

为什么要检验平稳性?

  • 如果一个序列不是白噪声,说明它包含可预测的规律
  • 但在寻找规律前,我们需要确认这个规律本身是否稳定
  • 平稳性是很多经典模型(如ARIMA)能够有效工作的前提

平稳序列的特征

  • 统计特性(均值、方差)不随时间变化
  • 序列中的规律是可重复、可学习的

非平稳序列的例子

  • 持续上涨的股票价格(均值在变)
  • 夏天销量高、冬天销量低的冰淇淋销售数据(存在季节性)

注意:白噪声虽然看起来很乱,但实际上是平稳的(均值和方差恒定)。

3.2 ADF检验(单位根检验)

检验目的:判断时间序列是否平稳

假设设定

  • 原假设 (H0):序列是非平稳的(存在单位根)
  • 备择假设 (H1):序列是平稳的

判断规则

  • p-value < 0.05 -> 拒绝原假设,认为序列是平稳的
  • p-value >= 0.05 -> 无法拒绝原假设,认为序列是非平稳的

辅助判断

  • 如果ADF统计量 < 临界值(如5%临界值),也表明序列是平稳的
python 复制代码
# ADF平稳性检验
print("Starting ADF Stationarity Test...")

# 执行ADF检验
adf_result = adfuller(random_sequence)

# 提取并展示主要结果
adf_statistic = adf_result[0]  # ADF统计量
p_value = adf_result[1]  # p值
critical_values = adf_result[4]  # 临界值

print(f"ADF Statistic: {adf_statistic:.4f}")
print(f"p-value: {p_value:.4f}")
print("Critical Values:")
for key, value in critical_values.items():
    print(f'    {key}: {value:.4f}')

print("\n--- Test Conclusion ---")
# 根据p值进行判断
if p_value < 0.05:
    print(f"p-value ({p_value:.4f}) < 0.05, strongly reject H0.")
    print("Conclusion: Sequence is Stationary.")
else:
    print(f"p-value ({p_value:.4f}) >= 0.05, cannot reject H0.")
    print("Conclusion: Sequence is Non-stationary.")

# 通过比较ADF统计量和临界值来判断
if adf_statistic < critical_values['5%']:
    print("\nAdditional: ADF statistic < 5% critical value, also indicates stationarity.")
复制代码
Starting ADF Stationarity Test...
ADF Statistic: -14.7442
p-value: 0.0000
Critical Values:
    1%: -3.4636
    5%: -2.8762
    10%: -2.5746

--- Test Conclusion ---
p-value (0.0000) < 0.05, strongly reject H0.
Conclusion: Sequence is Stationary.

Additional: ADF statistic < 5% critical value, also indicates stationarity.

四、季节性检验

4.1 季节性的定义

什么是季节性?

  • 时间序列中以固定、已知的频率重复出现的模式或周期性波动
  • 可以理解为数据的心跳或呼吸,有规律、可预测

季节性的例子

  • 冰淇淋销量:每年夏天达到高峰,冬天降到谷底(周期:12个月)
  • 工作日用电量:每天早上8点开始攀升,晚上回落(周期:24小时)
  • 零售业销售额:每年第四季度(节假日)最高(周期:4个季度)

季节性 vs 周期性

  • 季节性:频率固定且已知(年、季度、月、周、日)
  • 周期性:模式长度可变且不固定(如商业周期)

为什么要检验季节性?

  • 季节性是数据中最强大、最明显的预测信号之一
  • 如果模型不能识别和利用季节性,预测结果将出现系统性的周期性误差

4.2 通过ACF图检测季节性

ACF图的季节性特征

  • 如果序列存在季节性,ACF图会在代表季节性周期的滞后点上出现显著的尖峰
  • 例如:月度数据(年度季节性,周期为12),在 lag=12, 24, 36, ... 的位置会看到很高的相关性
python 复制代码
# 生成具有季节性的序列
np.random.seed(42)
n = 120  # 10年的月度数据
time = np.arange(n)

# 创建季节性成分(周期为12个月)
seasonal_component = 10 * np.sin(2 * np.pi * time / 12)

# 创建趋势成分
trend_component = 0.1 * time

# 创建随机噪声
noise = np.random.randn(n) * 2

# 合成序列
seasonal_series = seasonal_component + trend_component + noise

# 可视化
fig, axes = plt.subplots(2, 1, figsize=(14, 8))

# 绘制时序图
axes[0].plot(seasonal_series, label='Seasonal Series', color='blue')
axes[0].set_title('Time Series with Seasonality', fontsize=14)
axes[0].set_xlabel('Time (Month)', fontsize=12)
axes[0].set_ylabel('Value', fontsize=12)
axes[0].legend()
axes[0].grid(True, linestyle='--', alpha=0.6)

# 绘制ACF图
plot_acf(seasonal_series, lags=40, ax=axes[1], alpha=0.05)
axes[1].set_title('ACF Plot of Seasonal Series', fontsize=14)
axes[1].set_xlabel('Lag', fontsize=12)
axes[1].set_ylabel('Autocorrelation', fontsize=12)

plt.tight_layout()
plt.show()

print("\n--- Seasonality Analysis ---")
print("Observe the ACF plot: significant spikes at lag=12, 24, 36...")
print("This indicates the series has seasonality with period=12 (annual seasonality).")
复制代码
--- Seasonality Analysis ---
Observe the ACF plot: significant spikes at lag=12, 24, 36...
This indicates the series has seasonality with period=12 (annual seasonality).

4.3 通过序列分解检测季节性

思路:把序列拆分为 趋势(Trend) + 季节性(Seasonal) + 残差(Residual)

解读要点

  • Seasonal部分是否呈现稳定重复的周期
  • Resid残差不一定是白噪声:如果残差仍有结构,说明还存在可学习的信息(可进一步对残差画ACF或做Ljung-Box检验)
python 复制代码
# 序列分解(加法模型)
series = pd.Series(seasonal_series)
decomposition = seasonal_decompose(series, model='additive', period=12)

fig = decomposition.plot()
fig.set_size_inches(14, 8)
plt.suptitle('Time Series Decomposition', y=1.02, fontsize=16)
plt.show()

# 可选:对残差画ACF,查看是否接近白噪声
resid = decomposition.resid.dropna()
fig, ax = plt.subplots(figsize=(12, 5))
plot_acf(resid, lags=40, ax=ax, alpha=0.05)
ax.set_title('ACF Plot of Residual', fontsize=14)
ax.set_xlabel('Lag', fontsize=12)
ax.set_ylabel('Autocorrelation', fontsize=12)
plt.tight_layout()
plt.show()

五、总结

5.1 检验流程

在进行时间序列分析前,建议按以下顺序进行检验:

  1. 白噪声检验:确认数据是否具有可预测性

    • 使用ACF/PACF图和Ljung-Box检验
    • 如果是白噪声,则无法进行有效预测
  2. 平稳性检验:确认数据的统计特性是否稳定

    • 使用ADF检验
    • 如果非平稳,需要进行差分等处理
  3. 季节性检验:识别数据中的周期性模式

    • 观察ACF图中的周期性尖峰,或使用序列分解
    • 如果存在季节性,需要在模型中考虑

5.2 检验方法速查表

检验类型 方法 原假设 判断标准
白噪声检验 ACF/PACF图 - 观察滞后项是否落在置信区间
白噪声检验 Ljung-Box 序列是白噪声 p >= 0.05 无法拒绝
平稳性检验 ADF 序列非平稳 p < 0.05 拒绝(平稳)
季节性检验 ACF图 - 观察周期性尖峰
季节性检验 序列分解 - 观察Seasonal是否周期重复

@浙大疏锦行

相关推荐
NAGNIP1 天前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab1 天前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab1 天前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP1 天前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年1 天前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼1 天前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS1 天前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区1 天前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈1 天前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang1 天前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx