4.2 ACF 与周期图:识别周期


4.2 ACF 与周期图:识别周期

本节摘要:自相关函数(ACF)和周期图是识别季节性周期的两把标尺。ACF 在时间域告诉你"相隔 k 天的两个值有多相关";周期图在频率域告诉你"哪个频率的能量最强"。本节深入两者的数学原理,并用合成数据演示"周期峰有多显著才算强"。

本节学习地图

阅读完本节,你应当能够:

  1. 写出 ACF 的数学定义,并解释为什么季节性会让 ACF 在固定 lag 处出现峰。
  2. 解释周期图的横轴(频率)含义,并能根据最强峰反推周期。
  3. 给出 ACF 周期峰"显著"的工程判据:|ACF(lag=k)| > 2/√n。

本节是双路对照的第二路:ACF + 周期图(看周期长度)。读完后你能从 lag=7/12/24 处的局部峰确认季节性的存在,并用显著性判据避免把噪声当信号。

一、ACF 的数学定义

自相关函数(Autocorrelation Function, ACF)定义为:

ρ(k) = Cov[y(t), y(t+k)] / Var[y(t)]

直观理解:把序列平移 k 个时间点再与原序列做相关。ρ(0) = 1(自己与自己完全相关),ρ(k) 随 k 增大应当衰减。

如果序列有季节性(周期 m),那么**ρ(m) 通常显著大于 0**——因为相隔一个周期的两个值在季节性模式下有强相关。ρ(2m)ρ(3m) 也会出现峰,因为相隔两个周期、三个周期的值也强相关。

二、用 statsmodels 算 ACF

import numpy as np import pandas as pd from statsmodels.tsa.stattools import acf from statsmodels.graphics.tsaplots import plot_acf # 构造 200 天数据:周期 7 + 趋势 + 噪声 rng = np.random.default_rng(11) n = 200 t = np.arange(n) trend = 0.1 * t weekly = 5 * np.sin(2 * np.pi * t / 7) y = trend + weekly + rng.normal(0, 1, n) s = pd.Series(y, index=pd.date_range("2024-01-01", periods=n)) # 算 ACF(nlags=30 看 lag 1 到 30) acf_vals = acf(s, nlags=30, fft=True) # 显著性的 95% 置信区间近似为 ±1.96/√n threshold = 1.96 / np.sqrt(n) print(f"显著性阈值 ±{threshold:.3f}") # 关键:lag=7、14、21 处的 ACF 值 for lag in [6, 7, 8, 13, 14, 15, 20, 21, 22]: flag = "✓" if abs(acf_vals[lag]) > threshold else "·" print(f"lag={lag:3d} ACF={acf_vals[lag]:+.3f} {flag}") # 预期:lag=7、14、21 处的 ACF 显著大于阈值

经验法则:|ρ(k)| > 2/√n 就算显著(约 95% 置信区间)。如果 |ρ(m)| > 2/√nm 是业务周期长度,则季节性存在。

三、ACF 衰减 vs ACF 周期峰

ACF 的形状透露两类信息:

  • 指数衰减 / 拖尾:ACF 整体随 lag 增大慢慢衰减——这是趋势或 AR 过程的信号。
  • 周期峰:ACF 在固定 lag 处出现局部峰值(且该 lag 是业务周期长度的倍数)——这是季节性的信号。

两种信号可以同时存在。例如,一个有线性趋势 + 周季节性的序列,ACF 会先随 lag 增大快速衰减(趋势效应),然后在 lag=7、14、21 等位置出现周期峰。判读时关注周期峰是否"突出"于整体衰减趋势之上

四、周期图的数学原理

周期图(periodogram)把序列拆成不同频率的复指数波,统计每个频率的能量:

P(f) = (1/n) |Σ y(t) e^(-i 2π f t)|²

直观理解:在频率 f 处,序列的"信号强度"。最强的峰对应"主导周期"。

from scipy.signal import periodogram freqs, power = periodogram(s.values, fs=1.0) # fs=1 每天 1 个采样点 # 周期 = 1 / 频率 periods = 1 / freqs[1:] # 排除 f=0 power_no_dc = power[1:] # 找最强峰 top_idx = np.argsort(power_no_dc)[::-1][:5] for i in top_idx: print(f"周期 {periods[i]:.2f} 天 功率 {power_no_dc[i]:.2f}") # 预期:周期 ≈ 7 天的功率最高

五、ACF 周期峰 vs 周期图:互补

工具 优势 局限
ACF 直观:周期峰在 lag 轴上 周期峰如果太靠后会看不到(要 nlags 够大)
周期图 频率分辨率高,能识别"非整数周期" 频率轴不直观,需要反推周期长度

工程上两个一起画最稳:ACF 确认"lag=7、14 处显著",周期图确认"频率 1/7 处功率最高"。两者一致时,季节性才算"确认"。

六、置信带与显著性

statsmodels 的 plot_acf 会自动画 95% 置信带(蓝色阴影区域)。如果某个 lag 的 ACF 超出置信带 → 显著。

import matplotlib.pyplot as plt from statsmodels.graphics.tsaplots import plot_acf fig, ax = plt.subplots(figsize=(10, 4)) plot_acf(s, lags=30, ax=ax, alpha=0.05) # alpha=0.05 对应 95% 置信带 plt.tight_layout()

如果只有 lag=0 之外、零星几个 lag 超出置信带,且不在业务周期位置 → 多半是噪声。如果 lag=7、14、21 都超出 → 强季节性。

七、一个工程案例:电商周季节性的判读

某电商 90 天日数据,ACF 显示:

  • lag=1: 0.42(短期自相关)
  • lag=2 ~ 6: 衰减
  • lag=7: 0.65(远超置信带)
  • lag=14: 0.41
  • lag=21: 0.28

判读:lag=7、14、21 三个峰依次递减,强周季节性。后续建模应当用 SARIMA(?, ?, ?)(?, ?, ?, 7) 或 Prophet。

本节要点回顾

  • ACF 数学定义:相隔 k 期的相关系数,ρ(m) > 0 是季节性的关键证据。
  • 显著性判据|ρ(k)| > 2/√n(约 95% 置信区间)。
  • 周期图:频率域视角,最强峰对应主导周期。
  • 两者互补:ACF 看 lag 轴,周期图看频率轴;一起画最稳。
  • 工程判读:周期峰应当突出于整体衰减趋势之上,且在业务周期位置。
  • 下一节线索:4.3 进入"季节性调整"——把季节性从数据里"剥掉"用于下游分析与同比对比。

图:周期图原理示意

图:周期图原理示意


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U