You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动检测时间序列的信号周期性,尤其是日度周期性?

时间序列日度周期性自动检测问题

问题背景

我手头有一个包含约1000条不同时间序列的数据集,其中部分序列存在明显周期性,其余序列则没有。我需要自动判断给定时间序列是否存在明确的周期性,从而确定在应用异常检测方法之前,是否需要先对其做季节性分解。
现有一条具备日度周期性的信号,采样间隔为15分钟,信号示例如下:
信号示例图

已尝试方案

方案1:kats库自带检测函数

代码实现如下:

from kats.consts import TimeSeriesData
from kats.detectors.seasonality import FFTDetector, ACFDetector
def detect_seasonality(df,feature,time_col,detector_type):

    df_kpi = df[[feature]].reset_index().rename(columns={feature:'value'})
    ts = TimeSeriesData(df_kpi,time_col_name=time_col)

    if detector_type == 'fft':
        detector = FFTDetector(ts)
    elif detector_type == 'acf':
        detector = ACFDetector(ts)
    else:
        raise Exception("Detector types are fft or acf")

    detection = detector.detector()
    seasonality_presence = detection['seasonality_presence']
    return seasonality_presence

检测结果:fft和acf检测器返回的周期性存在性结果均为False。

方案2:自主实现FFT检测

代码实现如下:

import numpy as np
import scipy.signal

from matplotlib import pyplot as plt

L = np.array(df[kpi_of_interest].values)
L -= np.mean(L)
# Window signal
L *= scipy.signal.windows.hann(len(L))

fft = np.fft.rfft(L, norm="ortho")

plt.figure()
plt.plot(abs(fft))

对应的频谱图如下:
FFT频谱图
检测结果:无法明确识别出预期的日度周期性。

待解答疑问

目前每条时间序列仅约10天的数据,请问还有哪些更合适的方法可用于自动检测日度周期性?检测前需要完成哪些必要的预处理步骤?检测失败是否可能是由数据量不足导致的?


解答内容

检测失败原因判断

10天的15分钟采样数据量本身足以检测日度周期,检测失败的核心原因不是数据量不足,大概率是现有方法没有针对日度周期做参数适配,以及预处理步骤有缺漏。

必要预处理步骤

在做周期性检测前,必须完成以下操作:

  • 缺失值填补:15分钟采样的序列如果存在缺失值,会直接破坏周期特征,优先用同时间段的历史均值填补,不要用线性插值或前向填充,避免掩盖周期特征
  • 趋势剔除:如果序列存在明显的上升/下降趋势,会大幅干扰周期性检测的结果,建议先用STL分解提取残差序列,或者用一阶差分法消除趋势
  • 异常值过滤:单值突增/突降的异常点会拉高频谱噪声,可先用3σ原则过滤掉偏离均值3倍标准差之外的异常点,再做检测

适配短序列的日度周期检测方法

1. 固定滞后项ACF显著性检验

不需要用通用的ACF检测器,直接针对日度周期的滞后项做检验即可:15分钟采样的日度周期对应滞后长度是24*4=96,直接计算序列滞后96位的自相关系数,做显著性检验:

from statsmodels.tsa.stattools import acf

# 序列长度N,滞后96位的自相关系数及置信区间
acf_vals, conf_int = acf(preprocessed_series, nlags=96, alpha=0.05)
# 判断滞后96位的自相关系数是否显著不为0
lag96_acf = acf_vals[96]
is_significant = (conf_int[96][0] > 0) or (conf_int[96][1] < 0)

如果滞后96位的自相关系数显著不为0,直接判定存在日度周期即可,准确率远高于通用周期检测工具。

2. 周期箱线方差检验

把10天的序列按每日的96个时间点分组,同一时间点的10个值归为一组,计算组间方差和组内方差的比值:如果比值明显大于1,说明同时间点的取值相似度远高于不同时间点,存在日度周期。

import pandas as pd
import numpy as np

# 给每个点打时间点标签(0-95,对应一天内的第n个15分钟)
df['time_of_day'] = df['timestamp'].dt.hour * 4 + df['timestamp'].dt.minute // 15
# 计算组间方差和组内方差
between_var = df.groupby('time_of_day')['value'].mean().var()
within_var = df.groupby('time_of_day')['value'].var().mean()
f_score = between_var / within_var
# 阈值可根据业务调整,一般f_score>2即可判定存在日度周期

3. 傅里叶变换功率占比检验

你之前的FFT实现只做了可视化没有做量化判断,可直接计算对应日度周期的频率点功率占总功率的比例:
15分钟采样的采样频率是 1/(15*60) Hz,日度周期的频率是 1/(24*3600) Hz,找到频谱中最接近该频率的点,计算该点的功率占所有频率点总功率的比例,比例超过5%即可判定存在明显日度周期。


内容的提问来源于stack exchange,提问作者kspr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 23:15:03