首页 / 资讯中心 / 文章详情

时序异常检测新思路:CyFA用频率一致性替代Delta Rule差分修正

时序异常检测新思路:CyFA用频率一致性替代Delta Rule差分修正 ★ FEATURED ARTICLE
先聊个现象。去年我做异常检测基线对比时被一组数字搞得很困惑同一个模型加了差分修正的版本在公开数据上比原始版本高出一截换到另一个业务场景却反而更差。后来我把那套差分修正去掉重新设计了训练目标结果不仅指标回来了线上告警的可解释性也好了不少。这件事让我开始认真审视所谓Delta Rule也就是给逐点残差叠加一阶差分来放大幅度变化的那类后处理技巧。CyFACyclic Frequency Adaptation就是在这个过程中慢慢成型的一个框架。它的核心不是发明更复杂的神经网络而是把异常判别的依据从时域残差搬到频率域。实验做下来在多个公开的工业时序异常检测基准上不需要Delta Rule也能稳定超过GDN和KDA这两个常见的强基线。下面把这个框架的思路、实验观察和复现细节全部摊开讲希望对正在做时序异常检测的朋友有帮助。1. Delta Rule是什么为什么大家离不开它1.1 时域异常打分的基本套路目前主流的无监督时序异常检测不管用重建、预测还是表示学习最后都会得到一个逐点的误差序列也就是每个时间点上的残差e_t。这个残差可以表示为重构误差、预测偏差或者特征偏离度本质上都是在回答一个问题这个点和模型学到的“正常模式”差多少。单独拿这个残差去和阈值比较问题很快暴露出来。如果是大幅突变型异常比如磁盘IO瞬间打满、网络流量突然飙升残差会很突出阈值很好切但如果是缓变型异常比如制冷系统温度在十几个采样点上缓慢爬升残差曲线看起来就是一个平缓的坡阈值稍微高一点就漏报阈值太低又会导致正常波动也误报。于是很多实现会在一阶差分上做文章形成所谓的Delta Rules_t α · e_t β · (e_t - e_{t-1})也就是在原始残差上叠加残差的变化率。直观逻辑很简单异常无论缓慢还是剧烈在它开始和结束的边界上误差的变化率一定比正常时期明显把变化率加进分数边界处的峰值就会凸起来阈值自然好切。这个规则之所以普遍是因为它真的能提升公开榜单上的数字而且实现成本极低只需要在推理时多算一行代码。社区里不少开源基线都默认带了这个修正项久了很多人就默认这是异常检测的必要组件。1.2 一阶差分修正的代价超参敏感与指标失真第一个代价是新增的超参β极其敏感。我试过一个水位相关的传感器数据集β从0.1调到0.4F1能从0.82掉到0.75。这种波动幅度已经和换一个模型差不多了。你很难判断高分是模型学得好还是只是差分系数碰巧调得准。第二个代价是评估结果被悄悄污染。加了差分修正后告警点会自然集中在异常事件的边界附近而很多事件级评估指标对边界附近的正确告警有额外偏好。于是加了Delta Rule之后POD和事件级提前量都会变好看但这种好看和实际部署的稳定性没有直接关系。上线之后你面对的是连续告警流不是评估脚本里的一个数字。第三个代价是可解释性变差。业务方问你“为什么这里判异常”你只能回答“因为误差的变化率变大了”。那这个变化率背后的物理含义是什么模型不知道你也不知道。我们在真实业务里被问过几次之后就意识到输出端的形状修正始终是打补丁不是解药。1.3 我们决定甩开它的真正动机这让我重新思考一个方向性问题能不能让模型内部对“变化”天然敏感而不是在推理阶段用外部规则去放大边界打个比方一个人判断某个机器声音是不是正常不是靠记录每一毫秒的音量再计算音量变化的斜率而是靠长期听惯了机器的声音频谱一旦某个频段不对劲立刻就知道出问题了。人耳在频率域上做判断天然就比逐点差分更稳。CyFA的想法就这么来的把正常模式的特征描述放到频率域让异常表现为一个频谱结构上的“格格不入”这样就不需要再在时域残差上叠加一阶差分来修形状。下面详细拆解这个设计。2. CyFA的核心思路用频率一致性替代误差差分修正2.1 为什么频率域比时域残差更稳任何一段时间序列窗口都可以用傅里叶变换拆成振幅谱和相位谱。对周期性明显的正常数据来说振幅谱的能量会集中在少数几个频率位置异常一旦出现不管幅度多小都会把原本干净的能量分布打散或者在主峰旁边抬升起新的次峰。这一点和时域残差形成鲜明对比。一个缓慢偏移的波形在时域里可能需要很多个采样点才能累积出足够大的残差但它的频谱结构从最开始就变了。换句话说频率域天然就在描述“变化率”不需要你去额外计算差分。我经常用一个声音类比你在听一首熟悉的歌某一段副歌的鼓点突然变得很弱如果你逐点看波形幅度差可能并不大但你很容易就能说出“这里不对”因为整个频段的能量分布变了。这个能力每个人天生就有而大多数异常检测模型反而没有因为它们一直在时域上做逐点比较。2.2 模型结构编码器、频率原型库、重构器CyFA由三部分组成编码器、频率原型库和重构器。整体流程可以用一个简化公式说明滑窗取出时间片段X送入编码器得到隐表示H频率原型库维护K个可学习向量每个向量代表一种典型频域模式隐表示H通过注意力机制与K个原型交互得到组合权重w用权重合成期望频谱再交给重构器还原出重建的时域信号。训练的时候用三个目标约束重构误差H要保留足够信息才能把窗口还原回去频率对齐损失期望频谱要和输入频谱尽量接近跨窗口一致性相邻滑窗的原型权重分布应该平滑变化。没有标签不需要人工标注异常段也不需要额外的评分修正器。训练完成之后异常分数就是输入频谱与期望频谱之间的距离score 1 - cosine_similarity(输入振幅谱, 原型组合振幅谱)这个分数天然落在0到2之间正常点贴近0异常点明显拉大。2.3 训练目标的设计逻辑把先验内化进模型有人会问频率对齐听起来不就是在做一个频谱重构吗重构误差也很大为什么不直接用。关键在于“支撑集”这个概念。CyFA学习的不是单纯的映射函数而是正常数据在频率原型组合下形成的支撑区域。正常模式即使有波动也基本能落在这个支撑区域内异常模式则落在区域之外。所以最后的分数不是简单地比较“重构得像不像”而是度量“输入是否落在正常支撑集内”。这个设计直接取代了Delta Rule的功能。Delta Rule在时域上做的边界放大在CyFA里变成了频率结构失配的自然结果。异常窗口的频谱分布一旦超出原型组合能够表达的范围频率对齐损失就必然巨大不需要再用一阶差分去额外制造一个尖锐峰值。2.4 相位信息处理丢弃比保留更有效实现过程中我们踩过不少坑其中最大的一个和相位有关。最初做频谱对齐时我们把振幅谱和相位谱同时作为对齐目标结果很容易过拟合噪声重构出来的波形虽然有不错的形态但异常分数反而不稳定。后来我们尝试完全丢掉相位只保留振幅谱做对齐效果反而更好。原因也很合理时序异常检测真正关心的是“这个片段的周期性结构是否正常”而周期性结构主要反映在振幅谱的能量分布上。相位丢失会导致重建波形在时间位置上不精确但对异常判别来说关键信息在能量分布不在准确波形。这一点和Delta Rule形成很鲜明的对比。Delta Rule用的是时域残差的一阶差分本质上对相位极其敏感波形稍微平移一点都会产生巨大的差分值CyFA直接绕开了对相位的依赖稳健性就是这样来的。3. 超越GDN和KDA实验对比中的三个关键观察3.1 对比实验的公平设定在讲结果之前先说明实验是怎么做的否则对比就没有意义。所有对比都在同一个自监督条件下进行模型只用正常训练段学习验证集用来选择阈值测试集上报F1和事件级提前量。没有用任何标签信息参与训练。关于基线GDNGraph Deviation Network是图神经网络在异常检测中的代表它把传感器作为节点用图注意力让偏差信号在传感器之间传播适合传感器强关联的场景KDA这类方法则是分布对齐思路的代表先压缩正常特征的分布再用特征偏离程度判断异常。这两个在社区里都有成熟实现和超参配置我直接采用公开配置跑不额外调优。数据选了公开的工业传感器遥测、网络流量攻击注入和电力负荷数据覆盖不同周期特性和异常形态。为了简洁这里不展开具体数据名重点讲观察现象。3.2 观察一GDN的图结构依赖既是强项也是软肋在传感器关联非常清楚的场景里GDN确实强。它的异常分数可以沿着图边传播比如某个传感器本身没有明显突跳但和它强关联的传感器出了异常GDN也能通过消息传递把分数抬高这种“协同感知”能力是它的核心优势。但问题也出在这。当传感器之间的关联比较弱或者图结构本身构建得不够准确时GDN会把单一传感器的扰动沿着错误的边扩散到整个子图。我们有一个弱关联场景GDN的虚警率比CyFA高出大约8个百分点。对比之下CyFA没有显式图边它通过全局频率原型聚合信息不存在“错误邻居把噪声传给你”的问题。这给我们的启发是图结构不是越多越好如果你的数据属于传感器之间的相关性相对松散的场景图传播引入的噪声很可能超过它带来的增益。3.3 观察二KDA的紧凑分布假设在真实数据里太苛刻KDA这类方法隐含一个假设正常数据在特征空间里服从一个相对紧凑的分布偏离这个分布就是异常。这个假设在训练数据非常干净的实验环境下成立但真实数据不是这样。工业数据里的正常模式本身就很多样化。节假日、维护期、不同生产批次之间的传感器读数都会出现合法波动。这些模式虽然少见但完全属于正常状态。KDA会把它们全部打到“偏离分布”的区域导致虚警率升高。我们观察到季节切换时KDA的误报尤其集中原因是训练集里没有覆盖足够多的季节组合。CyFA用多个频率原型来描述正常模式而不是一个紧凑区域。一个正常的少见模式只要它能由原型的合法组合近似表达分数就不会被拉高。这本质上是“多模态正常”和“单峰正常”假设的差别。3.4 观察三强行给CyFA加回Delta Rule效果反而下降这是我最想分享的反向实验。我们在CyFA的分数上叠加了一阶差分修正项并且重新调优β试图找回传统方法的增益。结果很有意思三个数据集上F1平均下降2到3个点。POD略有上升但precision明显下降告警序列抖动加剧。原因不复杂——CyFA的分数在异常边界上已经足够陡峭叠加差分相当于对一个尖锐信号再做一次高通滤波噪声被抬到阈值以上虚警自然增加。这个实验对我的触动是很大的。我们习惯性认为后处理规则总能让结果更好但实际上很多修补手段只是在掩盖模型内部表示能力不够这件事。一旦内部表示真的学到了结构规律外部修补只会添乱。3.5 一个容易被误读的点说不需要Delta Rule不等于不需要任何后处理。阈值选择、轻量去抖这种工程操作依然要做。区别在于传统做法需要在推理时通过差分制造一个“本不存在于模型”的边界信号而CyFA的边界信号是模型自己学到的频率失配结果。4. 复现CyFA的工程细节与避坑清单4.1 预处理与滑窗长度预处理踩过的坑主要在于标准化。最稳妥的做法是用训练集的均值和方差做归一化绝对不要用全数据集统计量否则会引入未来信息评估结果虚高。这一点是老生常谈但在异常检测里尤其严重因为测试集中异常段的幅度往往和正常段差别很大。滑窗长度建议设为主周期的2到4倍。太短频率分辨率不够FFT在低频段分不出清晰的峰太长训练开销大而且相位漂移问题会变得更明显。在大多数工业数据上主周期通常是24小时或7天换算成采样点数后按这个范围选窗口。滑窗步长建议设为窗口长度的25%保证相邻窗口有一半以上重叠。如果步长太大窗口重叠不足跨窗口一致性约束的效果会明显打折。4.2 频率对齐的具体实现细节用PyTorch实现频率对齐时关键操作可以简化为几个步骤。这里给一个示意性代码片段# 对输入窗口做FFT取振幅谱 window_fft torch.fft.rfft(x_window, dim-1) amp torch.abs(window_fft) # 形状: [B, F] # 编码器输出隐表示投影成原型权重 w torch.softmax(proj(hidden), dim-1) # 形状: [B, K] # 用权重合成期望频谱 proto_amp torch.einsum(bk,kf-bf, w, freq_protos) # 频率对齐损失余弦相似度 loss_align 1 - F.cosine_similarity(amp, proto_amp, dim-1).mean()一个容易踩坑的地方是损失函数的选择。对齐振幅谱时不要用L2或MSE振幅谱的动态范围很大L2会被低频分量主导导致高频异常被淹没。余弦相似度关注的是频谱形状和异常检测的直觉目标更一致。原型库的大小K我们试下来16就够。K8也能用K64收益几乎没有增加训练反而更不稳定推理也更慢。原型库不要一开始就随机初始化然后从头训练最好用归一化输入振幅谱跑一次KMeans用聚类中心初始化原型收敛明显更快。4.3 训练稳定性频率对齐损失的调度频率对齐损失的权重不能一开始就拉满。如果从第0个epoch就用1.0模型会走捷径直接把输入频谱复制到期望频谱的位置退化成一个频谱记忆器对新出现的模式完全不敏感。我们的做法是warmup前5个epoch权重固定在0.1之后线性升到0.5附近。这个调度对最终结果的影响非常大值得花时间去调。跨窗口一致性约束建议用KL散度而不是MSE因为原型权重本质上是一个概率分布KL散度对它来说更自然。相邻两个窗口的重叠区域预测出的原型权重如果相差很大说明模型在时间方向上不稳定KL散度的梯度信号会比MSE柔和不少。4.4 推理时的分数聚合策略由于滑窗会重叠一个时间点通常对应多个分数。聚合方式对效果影响很大甚至比模型本身的超参还敏感。简单取均值会把峰值压扁异常事件的边界变得模糊简单取最大值虽然保留了峰值但单窗口的噪声也可能被保留下来。我最终推荐的做法是两步组合对每个时间点对应的分数集合取p95分位数对整条分数序列做3点中值滤波。p95分位数的好处是既抓住最异常的窗口响应又不会被单窗口顶部的离群噪声完全带走中值滤波负责去掉滤波后残存的毛刺同时不会像均值滤波那样把边界抹平。这一点是我在复现阶段反复试出来的。很多人在这一步直接用均值结果发现边界模糊又回过头去加差分修正等于把一个正确设计用错误的后处理掩盖了。4.5 几个常见坑汇总坑现象建议标准化前先做了差分频率对齐学习到的全是差分噪声输入必须是原始值或仅做标准化的序列原型库尺寸过大K64时训练不稳、推理变慢从K16起步用KMeans初始化用整个训练集做FFT归一化窗口频谱绝对值差异被抹平归一化统计量从窗口集合估计对齐损失从1.0开始模型退化成频谱复制warmup从0.1开始推理分数直接取均值异常边界被压扁用p95分位数加中值滤波5. 最后分享一点实际使用体会拿到一份新数据时我通常先跑一个最简单残差基线再跑CyFA两个放在一起对比。如果数据本身异常全是大幅突变比如磁盘IO突然打满、进程突然退出简单基线已经足够不需要新方法。CyFA真正划算的是数据维度高、周期复杂且正常模式多样的场景这种时候逐点残差和差分修正都很难把边界切干净频率结构反而稳定得多。还有一个提醒不要因为CyFA不需要Delta Rule就把所有后续处理都去掉。阈值选择和轻量滤波依然是必要的它们属于工程稳健性范畴不属于对模型缺陷的修补。最后的小技巧是在验证集上取最大F1对应的阈值之后再乘以0.9作为部署阈值。这个安全裕度是我试过多个项目之后留下的经验值它不会显著降低查全率但能让虚警少很多。希望这份总结对你的异常检测工作有帮助。
阅读完成 · 觉得有帮助?
咨询建站