1. 周期、季节、循环:三个词背后的三种数据形态
几年前我拿到一份设备振动数据,对方只问了一句“这玩意儿有没有周期性”。当时我图省事,直接把原始序列丢进快速傅里叶变换,频谱上蹦出一堆峰,我挑了最高的那根当周期,写进报告,后面建模预测全线崩盘。回头复盘才发现,那根最高的峰根本不是设备运转周期,而是一个采集通道的工频干扰,真正的主周期藏在旁边一根不起眼的次高峰上。这件事之后,我对“时间序列之周期性”这个话题的态度就变得非常谨慎——周期性检测从来不是跑一个函数那么简单,它是一连串判断的集合,判断错了前提,后面所有计算都是精致的错误。
周期性在时间序列里指的是序列经过固定长度后重复出现相似形态的性质。它可以是24小时、7天、12个月这种自然节律,也可以是设备转一圈、一次生产批次、一个促销档期这种人为节律。看上去定义很清晰,但实际数据里,“周期性”这个词经常被混着用来指代三种完全不同的东西,而这三者的处理方式截然不同。这一节我想先把这三者掰开,因为我在带新人的时候发现,概念混淆是后面所有踩坑的源头,比工具用错还致命。
1.1 把“周期性”拆成可判断的四条特征
我判断一个序列是否存在严格意义的周期,一般看四条特征,缺一条我都会在心里打个问号。第一条是重复长度固定:相邻两次相同形态之间的间隔基本一致,波动不大。第二条是形态相似:不只是幅度回到同一水平,形状轮廓也要对得上。第三条是跨周期可比:至少能找出五个以上完整的重复单元,样本太少得到的结论基本靠不住。第四条是可外推:下一个周期的位置能够按前面的规律推出来,而不是只能做事后描述。
严格满足这四条,我会叫它确定性周期,比如一个稳定转速下的旋转机械信号,或者一个固定发版节奏的系统指标。只满足前三条、第四条打折扣的,我倾向于叫准周期或者近似周期,实际业务数据绝大多数落在这一档。至于完全不满足第一条、周期长度本身就在变的,那通常属于循环波动,比如经济景气度、行业淡旺季,它的“周期”只是一个统计意义上的平均间隔,你不能拿它去精确外推某一个时间点。
把这几类分开之后,很多争论就自然消失了。有人说“这个数据有周期”,另一个人说“没有”,很可能两个人说的根本不是同一件事。我在做需求沟通时养成了一个习惯:先让对方用一句话描述他期望的重复间隔是多少,再问这个间隔是不是固定。这两个问题的答案,直接决定了后面该用频谱还是该用分解,也决定了结果能不能用于预测。
1.2 概念没分清,后面所有检测都是在猜
判断周期长度这件事上,分解类方法和频谱类方法的适用边界差别很大,选错了会得到一个看起来很像那么回事、实际上毫无意义的数字。分解类方法,比如STL,需要一个预先给定的周期参数才能运行,它做的是“按你给的周期把数据拆成趋势、季节、残差三块”,本质上是在验证你的假设,而不是发现周期。频谱类方法,比如周期图和自相关,是从数据里反推周期长度,属于发现型工具。
很多人会犯的错误是拿STL当发现工具用:随手填一个7,跑出来季节项挺像样,就认定周期是7,然后拿去做特征。这种做法的风险在于,只要参数填得不太离谱,STL总能给你凑出一个“季节项”,残差大小才是真正的判据,但很少有人去看残差。我见过一个案例,数据真实周期是30天,团队按7天做分解,季节项看起来很平滑,残差里却藏着一个明显的30天波动,模型自然学不好,最后归因到“数据质量差”。
反向的错误也存在。有分析直接用FFT处理带强趋势的序列,趋势在频域里表现为低频能量极大的一坨,把真正的周期峰压得几乎看不见,于是得出结论“没有周期”。这是因为趋势和周期在时域里是叠加的,在频域里也是叠加的,不先剥掉趋势,低频会淹没一切。我的常规做法是先去趋势再做频谱,或者干脆走ACF,原因在下一节展开。
2. 三条探测路径:自相关、频谱、分解
发现周期这件事,我手里常用的就三把工具:自相关函数、频谱分析、分解方法。它们不是互相替代的关系,而是三种不同视角看同一份数据,各自有明确的优缺点。我的习惯是至少跑两条路径,结果互相印证之后才敢下结论。只信一条路径,尤其是只信FFT,是我早年吃亏最多的地方。
2.1 自相关函数:不挑数据形态的笨办法,但最可靠
自相关函数衡量的是序列和它自己平移k步之后的相似程度,取值在-1到1之间。如果序列存在周期s,那么在滞后s、2s、3s处会周期性出现峰值,而且峰值随着滞后增大逐渐衰减。这个方法的好处是不要求数据平稳到理想状态,也不要求采样间隔绝对均匀(虽然不均匀会影响解释),对非专业人员也比较好讲清楚——你就想象把序列往右挪一段,挪到某个距离上重合度最高,那个距离就是周期。
我第一次真正理解ACF的威力,是处理一份带明显上升趋势的销量数据。FFT跑出来一片糊涂,而ACF在滞后7、14、21处有清晰的局部峰,虽然整体被趋势拖着缓慢衰减。用完一阶差分之后,峰变得更明显了。这里的关键技巧是:趋势会让ACF衰减缓慢并且整体偏高,周期性会让ACF出现等间距的局部峰。判断周期时不要看绝对值,要看局部峰之间的间距是否稳定。
需要注意的坑是滞后阶数的选择。滞后太少看不出长周期,滞后太多计算量上来而且噪声放大。经验上滞后至少取到预期最大周期的3到4倍,如果连这个量级都没有,就老老实实说样本不足以判断。另一个坑是高阶滞后处的峰可能是低阶峰的整数倍,比如真实周期10天,滞后20、30处也会出峰,这是同一种周期性的多次重复,不是多个周期。判断时取最小的那个显著间隔作为基周期,除非有业务证据说明存在更长的真实周期。
我一般会配合偏自相关一起看。PACF剔除了中间滞后的间接影响,如果PACF在某个滞后处有显著尖峰,往往指向AR结构而不是周期;而纯周期的表现是ACF有峰、PACF却没有对应的尖峰。这套组合判断在实操中相当稳,比单看一个图可靠得多。
2.2 周期图与FFT:分辨率、泄漏和补零的骗局
频谱方法的核心思想是把时域信号拆成一堆不同频率的正弦波叠加,哪个频率能量大,哪个就是主要成分。数学上很漂亮,工程上处处是陷阱。第一个陷阱是频率分辨率。对N个采样点、采样间隔Δt的序列,频率分辨率是1/(NΔt),能分辨的最小频率间隔就是这个量。换句话说,如果你的数据只覆盖了三个周期,那你算出来的周期长度只能精确到大概三分之一周期,再好听的小数位都是假的。
第二个陷阱是频谱泄漏。FFT默认序列首尾相连是连续的,如果首尾接不上,能量会从真实频率往两边漏,形成一堆小峰。解决办法是加窗,汉宁窗、汉明窗都行,代价是主瓣变宽、分辨率下降。我在做设备信号分析时基本默认加汉宁窗,宁可牺牲一点分辨率也不想被泄漏造成的假峰骗。加窗之后记得做幅度修正,否则能量估计会偏。
第三个陷阱最阴险:补零不等于提高分辨率。很多人为了让频谱看起来更精细,在序列末尾补一堆零再FFT,出来的峰又尖又密,误以为精度提升了。实际发生的是频域插值,你能更清楚地看到峰值落在哪,但两个靠得很近的真实频率依然分不开。判断办法很简单:补零后的峰宽度不会变窄,只是采样点变密了。真正提升分辨率只能靠更长的观测时间,没有捷径。
还有一个概念必须提:奈奎斯特频率。采样频率的一半是可检测的最高频率,超过这个频率的信号会被折叠到低频区,这就是混叠。混叠是那种“错了你还看不出来”的错误,因为折叠后的信号看起来完全正常,只是周期长度是假的。判断混叠只能靠提高采样率做验证,或者从业务上确认真实信号不会超过某个频率。我在设备场景里有条硬规矩:采样率至少是被关心最高频率的2.5倍以上,留出滤波余量,然后加一个抗混叠低通。
2.3 STL分解:先看见,再量化
STL是我最常用的可视化工具,它的价值不在于告诉你周期多少,而在于把周期项画出来让你确认“长得像不像”。人眼对形状的识别能力远超任何统计量,一个周期项如果看起来不像季度性波动,那它大概率就不是。STL的三个参数值得细说:周期参数必须给定,而且必须是整数;趋势窗口和季节窗口控制平滑程度,窗口越大越平滑、越能抗异常值,但也越容易把真实变化抹掉。
我的经验配置是季节窗口取周期的奇数倍,比如周期7就取7或11,趋势窗口取周期的1到3倍,同时打开稳健模式,让它对异常值的敏感度降低。稳健模式内部做多轮迭代,会给残差异常的点降权,跑起来慢一些但结果稳很多。对于一年365天的日数据,周期填365,STL跑起来会比较吃力,这时候我会先聚合到周,或者改用分段处理。
多周期叠加的时候,单层STL就不够用了。我遇到过一个典型场景:数据同时有日周期和周周期,日周期幅度大,STL填24小时周期分解完之后,季节项里还残留一个明显的周波动。解决办法是做多层分解,先用大周期拆一次,再对残差用小周期拆一次。这个思路在实现上就是把STL套两层,顺序一般从长周期到短周期,因为长周期幅度通常更大,先拆掉能让短周期更清晰。
分解法的局限也要说清楚:它不给出显著性判断,只是把东西摊开给你看。你觉得像周期,它就可能是,你不确定,它也没法帮你确定。所以我的流程固定是:STL帮我看形状,ACF帮我定长度,频谱帮我做交叉验证,三者对上了才写进结论。
3. 工程现场最容易翻车的四个地方
理论层面的方法看几篇文章就能懂,真正让人翻车的是数据本身那些不规整的地方。我在实际项目里踩过的坑,绝大多数不是算法选错,而是数据预处理阶段埋下的雷,当时看不出来,等到模型效果差才回头找,排查成本高出好几倍。这一节把四个高频问题摊开讲。
3.1 采样间隔不均匀,等于给频谱埋雷
FFT有一个硬性前提:采样间隔必须均匀。现实里这个前提经常被破坏,传感器偶尔丢一个点、上报延迟导致时间戳乱序、业务系统节假日不产生数据,都会让序列变成不等间隔的。直接对不等间隔序列做FFT,数学上就是错的,输出结果没有物理意义,但代码不会报错,你只会得到一堆看起来正常的数字。这是最危险的一类错误。
处理办法有两种。一种是重采样到均匀网格,按固定步长把时间戳对齐,缺失的位置插值或标记为空。另一种是改用支持不等间隔的方法,比如朗伯-斯科特周期图,它能处理非均匀采样,代价是实现复杂、可解释性差。我在业务场景里基本都选前一种,因为后续特征工程、模型训练都要求规整时间轴,早对齐早省事。
重采样还有一个副作用要说清楚:降采样会降低可检测最高频率,升采样不会增加信息。把日数据插值成小时数据,看起来很精细,实际新增的点全是猜出来的,频谱上会出现插值函数自带的虚假高频成分。所以除非有明确理由,我尽量不做升采样,需要细粒度就在特征侧处理。
3.2 缺失值插值会凭空造出一个周期
这个坑我印象极深。一份数据每小时采集一次,每天固定时段设备维护、没有数据,处理时用了线性插值把空缺补上。结果FFT跑出来一个非常干净的24小时周期峰。团队一开始还挺高兴,觉得发现了日周期。后来一核对,这个所谓的周期完全来自我们自己的插值操作——每天同一时段被拉成一条直线,这一段的方差接近零,而其他时段有正常波动,这种规律性的方差结构在频域里就是一个标准的周期信号。
判断这类虚假周期有个简单办法:把插值补的点全部标记出来,单独看这些位置上的值分布。如果某个周期位置上的值系统性偏平、偏小或者偏大,那这个周期很可能是人造的。另一个办法是做敏感性分析,换一种插值方式(前向填充、均值填充、不填充直接跳过)再跑一遍,真实周期在不同处理方式下位置应该稳定,人造周期则会跟着处理方式变。
我的实践原则是:缺失比例低于5%可以插值,但要在特征里加一列缺失标记;5%到20%之间慎用插值,优先考虑用模型能直接处理缺失的方法;超过20%就老老实实缩短分析窗口,不要硬补。设备类数据尤其要注意,停机时段的缺失本身携带信息,补平了等于把最重要的信号抹掉。
3.3 多周期叠加时,最强的不一定是你要的
真实数据几乎不会只有一个周期。业务指标常常同时有日周期、周周期、月度周期,设备信号有转频、齿频、轴承特征频率。频谱上会出现多个峰,问题在于幅度最大的那个未必是你关心的那个。前面提到的工频干扰就是典型:干扰信号能量极强,把真正有用的周期峰压成一个小鼓包。
处理思路是先在业务上列清单:这个数据理论上可能存在哪些周期,各自的量级大概是多少。有了先验再去读频谱,就能有针对性地找峰,而不是被最高峰牵着走。如果目标周期被强干扰掩盖,可以尝试带阻滤波先把已知干扰频段滤掉再看,但滤波要谨慎,阻带太宽会连带削弱邻近的真实周期。
多周期还有一个容易忽略的点:周期之间会互相拍频。两个接近但不相同的周期叠加,会产生一个长周期的包络,看起来像出现了一个超长周期。我见过有人把这种拍频包络当成真实业务周期写进报告,实际上它只是两个短周期交互的产物。验证办法是分别用两个短周期做分解,看残差还剩下什么,如果包络消失,那它就是拍频。
3.4 周期漂移:今年是7天,明年可能是6.8天
严格固定的周期在自然界和业务里都是少数,多数周期会缓慢漂移。比如受季节影响,某类业务的周内节律在旺季和淡季长度虽然都是7天,但形态分布完全不同;又比如设备磨损之后,振动特征频率会缓慢下移。用固定周期去套这种数据,短期还凑合,时间一长误差累积得很快。
检测漂移的办法是滑窗分析:按固定长度切窗,每个窗内单独估一次周期,把周期估计值按时间画出来,看它是否稳定。如果这条曲线有缓慢趋势,说明周期在漂移;如果只是随机抖动,那更可能是估计噪声。窗口长度要覆盖至少三到五个完整周期,太短估计噪声大,太长又看不出变化。
应对漂移,我一般走两条路。一条是动态周期特征,把周期估计值本身作为特征送进模型,让模型知道当前周期长度大概是多少。另一条是放弃精确周期,改用频带特征,不追求“周期等于多少天”,而是提取某个频段的能量占比,这样对轻微漂移不敏感。两条路各有适用场景,前者适合周期漂移有明确物理原因的情况,后者适合只需要知道“哪类节律占主导”的情况。
4. 把周期塞进模型:几种编码方式的取舍
检测出周期只是第一步,真正产生价值的是把它变成模型能用的东西。这一步的选择比检测本身更影响最终效果,而且不同模型类型的适配方式差别很大。我见过不少项目在检测环节做得挺漂亮,到了特征工程环节随手一编码,效果反而被拖累。
4.1 正余弦编码与傅里叶项
最通用的做法是正余弦编码。对周期s,把时间索引t映射成sin(2πt/s)和cos(2πt/s)两个特征。这样做的核心好处是保持了周期的循环连续性:时间点s-1和时间点0在编码空间里是相邻的,而如果直接用t除以s取余,这两点会一个在最大值一个在最小值,模型会误以为它们相距很远。
一阶正余弦只能表达一个平滑的单峰形态,真实周期往往更复杂,周内可能有周末低谷、周一高峰这种多起伏结构。这时候要用傅里叶项:取k=1到K,构造sin(2πkt/s)和cos(2πkt/s)共2K个特征。K的取值上限是s/2,因为再高的频率就超过奈奎斯特了,再多加只会引入共线性。实际用的时候K不需要取满,K=2或3通常就能抓住主要形态,K太大容易过拟合,尤其是样本量不大的时候。
选K的方法我一般用逐步增加加验证集评估:从K=1开始,每次加一,看验证集误差什么时候不再下降。这个流程比较笨但很可靠。需要注意K增加会带来特征数量线性增长,如果原始特征已经很多,要考虑降维或者只保留前几阶。
4.2 差分、SARIMA的s参数与计算成本
传统时间序列模型对周期的处理方式不一样。SARIMA通过季节差分和季节自回归项来建模周期,s参数就是周期长度。这里有个很现实的约束:s越大,计算成本涨得越快。月度数据的s=12还算轻松,小时数据的日周期s=24也还行,但如果是小时数据还要建模年周期,s=8760,参数量和计算量会直接劝退,实际跑起来内存都未必够。
我的处理策略是分层建模:短周期用SARIMA直接处理,长周期用外部特征或者单独建模再叠加。比如小时数据先按24小时做SARIMA,把年周期通过傅里叶项作为外生变量塞进去。这样既保留了短周期的精细结构,又不会让参数爆炸。
季节差分还有个副作用:会损失s个观测。序列开头s个点没有差分值,如果样本本来就不长,这一刀砍下去影响不小。另外差分过度会让序列变得过于平滑,周期特征反而被削弱。我一般先用统计检验判断是否需要季节差分,而不是无脑加。
4.3 树模型最容易踩的“序号陷阱”
梯度提升树这类模型处理周期特征时有个经典陷阱。很多人图省事,直接把时间序号t作为特征喂进去,模型在训练集上表现很好,一上测试集就崩。原因是树模型只能内插不能外推,测试集的时间序号超出训练集范围,模型只能给出边界值,相当于对未来做了常数预测。
用正余弦编码能缓解这个问题,因为编码值域固定在-1到1之间,未来时间的编码落在训练时见过的范围内,至少不会出现外推失效。但要注意,正余弦编码解决的是“周期位置”的表达,不解决“趋势”的外推。如果数据有明显增长趋势,光靠周期编码还是不够,得配合趋势特征或者对目标做差分。
还有一个细节:不要把周期位置和绝对时间混着用。我见过特征表里同时有原始时间戳、时间序号、周期编码三套东西,模型会优先抓时间戳这种高基数特征,学出一堆伪规律。时间戳这类特征我一般在树模型里直接删掉,只保留周期编码和必要的业务特征。
5. 一套可复现的检测流程
讲了这么多判断和方法,落到操作上我有一套固定流程,基本上是照着走就能出结论的程度。这套流程不是最优解,但胜在稳定、可复现,换个人照着做也能得到差不多的结果,这在团队协作里比单次分析的精度更重要。
5.1 数据体检:先做五件事再动手
拿到数据别急着跑算法,先做五件事。第一件是确认时间戳的语义,是采集时刻还是入库时刻,两者可能差好几个小时,直接决定周期相位对不对。第二件是检查采样间隔分布,画个间隔直方图,看看有没有大量异常间隔,这决定了要不要重采样。第三件是统计缺失比例和缺失位置分布,尤其要看缺失是否集中在某些时段,这关系到虚假周期的风险。
第四件是看整体趋势和量级变化,画一条原始曲线,肉眼先有个大概印象,后面所有统计结果都要和这个印象对照。第五件是确认业务上已知的周期,比如系统每天几点跑批、每周几休息,这些先验信息能帮你快速识别哪些峰是真实的、哪些是干扰。这五件事做完,通常只要十几分钟,但能省掉后面几个小时的返工。
我特别想强调第一件事。有一次数据的时间戳是入库时间,而入库是批量延迟的,导致所有时间点整体后移,算出来的日周期相位差了六个小时。周期长度是对的,相位错了,做出来的特征在预测时全错位。这种错误光看统计量发现不了,只能靠确认字段语义。
5.2 代码骨架:ACF、周期图、STL三连
下面这段是我常用的检测骨架,参数按照日频数据设置,换数据时主要调整周期上限和采样间隔。
import numpy as np import pandas as pd from scipy import signal from statsmodels.tsa.seasonal import STL from statsmodels.graphics.tsaplots import plot_acf def detect_period(series, max_lag=120, top_k=5): s = series.dropna().astype(float) # 去趋势:一阶差分,避免趋势污染频域 s_diff = s.diff().dropna() # 路径一:自相关,取局部峰 acf = signal.correlate(s_diff, s_diff, mode='full') acf = acf[len(acf)//2:] acf = acf / acf[0] peaks, _ = signal.find_peaks(acf[:max_lag], height=0.1) acf_candidates = peaks[np.argsort(acf[peaks])[::-1][:top_k]] # 路径二:周期图,加汉宁窗抑制泄漏 n = len(s_diff) win = np.hanning(n) freq, power = signal.periodogram(s_diff * win, fs=1.0) idx = np.argsort(power)[::-1][:top_k] freq_candidates = freq[idx] period_candidates = np.where(freq_candidates > 0, 1.0 / freq_candidates, np.inf) # 路径三:STL,用ACF的首选周期做验证 stl_period = int(acf_candidates[0]) if len(acf_candidates) else 7 if stl_period >= 2: res = STL(s, period=stl_period, robust=True).fit() seasonal_strength = max(0, 1 - res.resid.var() / (res.seasonal + res.resid).var()) else: seasonal_strength = np.nan return { 'acf_candidates': acf_candidates.tolist(), 'fft_candidates': [round(float(p), 2) for p in period_candidates if np.isfinite(p)], 'stl_period': stl_period, 'seasonal_strength': round(float(seasonal_strength), 3) }这段代码里有两个细节值得说。一是先差分再去频谱,代码里对原始序列做了一阶差分,代价是会削弱长周期信号,如果数据本身很平稳可以去掉这一步。二是季节强度指标,它用残差方差和季节项加残差方差的比值来量化周期成分有多强,取值在0到1之间,越接近1说明周期越明显。这个指标比单看频谱峰高可靠得多,因为它同时考虑了趋势和残差。
5.3 结果可信度的三道校验
跑出候选周期之后,我会做三道校验。第一道是跨方法一致性:ACF的首选周期和频谱的首选周期如果差太远,说明数据里有复杂结构,不能简单下结论,要回到原始曲线去找原因。第二道是分段稳定性:把序列切成前后两半,分别估一次周期,如果差异超过20%,这个周期就有漂移风险,不能当固定周期用。
第三道是业务合理性:算出来的周期能不能对应到一个可解释的机制。设备数据对应转速、业务数据对应作息规律、环境数据对应日照变化,能对上就基本可信;完全对不上的时候,我更倾向于相信是数据问题而不是发现了一个新规律。这条听起来很主观,但实际用起来拦住了我不少冲动结论。
三道校验都过,再进入特征工程。有任何一道没过,我的做法是先记录在案,把不确定性写进说明,而不是硬着头皮往下走。分析报告里保留不确定性,比给一个看似确定的错误答案要负责任得多。
6. 三个场景的拆解:同样的方法,不同的坑
方法讲完了,最后落到几个具体场景上。这几个场景都是我实际处理过的类型,坑的位置各不相同,放在一起对比能看清楚方法的适用边界。
6.1 设备振动信号:高频周期与采样率的博弈
设备振动的周期通常很短,转频可能是每秒几十次,对应的采样率要求很高。这类数据最大的问题不是算法,而是采样率是否够用。如果采样率刚好卡在两倍转频附近,混叠几乎必然发生。我的处理是先确定关心的最高频率,按2.5到3倍配置采样率,再做一次低通滤波把高频噪声挡掉。
振动信号还有个特点:周期成分不是单一频率,而是基频加一系列谐波。频谱上会看到基频峰和它的整数倍峰排成一列,判断基周期时要取最低的那个显著峰,而不是最高的那个。有时候基频能量反而不如二次谐波大,这是正常的物理现象,不能按峰值高低来定周期。
6.2 业务指标的周周期:节假日把周期“掰弯”
业务数据的周周期看着简单,处理起来麻烦在节假日和促销。一个法定长假会把整个周内节律打乱,用固定7天周期去套,长假那一周的特征会严重失真。我的做法是把异常周单独标记,不参与周期估计,估计完再用正常的周去做特征,异常周用单独的标识特征让模型自己学。
另一个细节是相位对齐。周周期的起点应该定在业务上真正意义上的周初,而不是自然周的周一。有些业务的结算周期是从周日开始的,按周一切分会把同一个结算周期劈成两半,周期特征就废了。这个对齐问题必须在特征工程之前确认清楚。
6.3 传感器长序列:内存、分块与在线检测
长时间高频采集的数据动辄上千万行,一次性做FFT内存直接爆掉。我的做法是分块处理加结果汇总:按固定长度切块,每块单独估周期,再把各块的估计值做稳健平均。块长至少覆盖五个完整周期,块之间可以有一定重叠以减少边界效应。
如果是需要实时检测的场景,就得改成滑动窗口加增量计算。窗口内维护一个固定长度的缓冲区,每次新数据进来就丢掉最旧的,重新算一次ACF峰值位置。这种方式计算量可控,但要注意窗口长度和响应速度的权衡:窗口太长反应迟钝,太短估计噪声大。我一般取预期周期的五到十倍作为窗口长度,这个比例在实测中比较平衡。
最后分享一个我在实际操作中的体会:周期检测这件事,结论的不确定性要如实传递出去。我在报告里从来不只写“周期为7天”,而是写“周期估计为7天,跨方法一致,分段稳定,业务上对应周内作息”。这样后面的人接手时就知道这个结论有多硬,万一模型出问题,也能快速判断是不是周期假设失效了。看起来啰嗦,但能省掉很多来回。