工业级时序异常检测利器:USAD 算法深度解析与实战

工业级时序异常检测利器:USAD 算法深度解析与实战

在智能运维(AIOps)和工业互联网领域,如何从海量的传感器数据中精准识别出设备故障、网络攻击或业务异常,一直是核心挑战。经典的自编码器(AE)虽然能学习重构,但在面对某些精巧的异常时往往表现得过于“宽容”,导致漏报。

2020年,由 KTH 皇家理工学院提出的 USAD (UnSupervised Anomaly Detection for Multivariate Time Series) 算法横空出世。它巧妙地结合了**自编码器(AutoEncoder)的重构能力和生成对抗网络(GAN)**的对抗特性,成为了目前多维时序异常检测领域的标杆模型。


一、 技术核心:为什么 USAD 如此强大?

USAD 的核心逻辑在于:通过对抗训练来弥补传统自编码器重构能力过强的缺点。

1.1 传统 AE 的痛点

普通的自编码器通过最小化重构误差来学习数据的压缩表示。然而,由于神经网络强大的拟合能力,AE 有时甚至能把异常点也复原得很好,导致异常点和正常点的重构误差差距不明显,产生大量漏报。

1.2 USAD 的创新架构

USAD 采用了三支路结构:一个共享的编码器(Encoder)和两个平行的解码器(Decoder1 和 Decoder2)。

  • 第一阶段:自编码器重构训练两个解码器都尝试学习复原输入数据。这保证了模型具备基础的特征提取和还原能力。
  • 第二阶段:对抗训练这是 USAD 的精髓。我们将两个解码器看作 GAN 中的角色:
    • Decoder1 产生的重构数据被视为“生成的样本”。
    • Decoder2 则试图分辨这个样本是真实的还是由 Decoder1 伪造的。
    • Encoder 的目标是学习更深层次的分布,使得 Decoder1 产生的重构数据能够骗过 Decoder2。

通过这种“内卷”式的对抗,模型被迫学习到数据中极其细微的正常分布约束,从而对不符合分布的异常点产生极大的重构偏差。


二、 核心算法与使用技巧

2.1 异常得分计算 (Anomaly Score)

USAD 在检测阶段并不是简单地计算 MSE,而是结合了两阶段的误差:

Score=α⋅∣X−AE1(X)∣+β⋅∣X−AE2(AE1(X))∣Score = \alpha \cdot |X - AE_1(X)| + \beta \cdot |X - AE_2(AE_1(X))|Score=α⋅∣X−AE1​(X)∣+β⋅∣X−AE2​(AE1​(X))∣

通过调节 α\alphaα 和 β\betaβ,我们可以控制模型对“重构精确度”和“对抗敏感度”的倾向。

2.2 常用技巧

  1. 滑动窗口 (Sliding Window):时序数据必须经过窗口化处理。通常窗口长度 WWW 取决于数据的周期性,例如监控数据可取 5-10 个采样点。
  2. 标准化 (Normalization):USAD 对数值范围非常敏感,推荐在 Windows/CentOS 环境下使用 MinMaxScaler 将数据映射到 [0,1][0, 1][0,1]。
  3. 学习率衰减:对抗训练初期容易震荡,建议使用 StepLR 并在训练 50 轮后降低学习率。

2.3 常见错误与排除

  • 报错:Input contains NaN:时序数据采集常有缺失,必须在喂入模型前使用 df.fillna(method='ffill') 处理。
  • 模型不收敛:如果损失函数一直震荡,通常是因为两阶段训练的比例不协调。建议先单独训练重构阶段(Phase 1)10个 Epoch。

三、 相关背景知识讲解

3.1 多维时间序列 (Multivariate Time Series)

不同于单维数据,多维数据(如一台服务器的 CPU、内存、网卡流量、磁盘IO)之间存在空间相关性。USAD 的编码器通过全连接层捕捉这些维度间的非线性依赖关系。

3.2 对抗损失 (Adversarial Loss)

在 GAN 中,损失函数是零和博弈。但在 USAD 中,对抗损失被转化为重构误差的对比。Decoder2 尝试最小化重构“被 Decoder1 重构后的数据”的误差,而 Encoder 尝试最大化这个误差。


四、 实战演练:构建基于 USAD 的多维指标监测系统

本项目将使用 Python 和 PyTorch 实现一个可直接运行的 USAD 模型,用于检测模拟的工业传感器异常。

4.1 环境准备

建议在 Windows 下使用 Anaconda 环境,或在 CentOS7 下使用 Python3.8。

pip install torch numpy pandas scikit-learn matplotlib 

4.2 核心模型实现 (code.py)

import torch import torch.nn as nn import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler # 1. 定义 USAD 模型结构classEncoder(nn.Module):def__init__(self, in_size, latent_size):super().__init__() self.linear1 = nn.Linear(in_size, in_size //2) self.linear2 = nn.Linear(in_size //2, in_size //4) self.linear3 = nn.Linear(in_size //4, latent_size) self.relu = nn.ReLU()defforward(self, x): x = self.relu(self.linear1(x)) x = self.relu(self.linear2(x)) x = self.relu(self.linear3(x))return x classDecoder(nn.Module):def__init__(self, latent_size, out_size):super().__init__() self.linear1 = nn.Linear(latent_size, out_size //4) self.linear2 = nn.Linear(out_size //4, out_size //2) self.linear3 = nn.Linear(out_size //2, out_size) self.relu = nn.ReLU() self.sigmoid = nn.Sigmoid()defforward(self, x): x = self.relu(self.linear1(x)) x = self.relu(self.linear2(x)) x = self.sigmoid(self.linear3(x))return x classUSAD(nn.Module):def__init__(self, w_size, z_size):super().__init__() self.encoder = Encoder(w_size, z_size) self.decoder1 = Decoder(z_size, w_size) self.decoder2 = Decoder(z_size, w_size)deftraining_step(self, batch, n): z = self.encoder(batch) w1 = self.decoder1(z) w2 = self.decoder2(z) w3 = self.decoder2(self.encoder(w1))# Phase 1: 重构阶段 loss1 =1/n * torch.mean(torch.abs(batch - w1))+(1-1/n)* torch.mean(torch.abs(batch - w3))# Phase 2: 对抗阶段 loss2 =1/n * torch.mean(torch.abs(batch - w2))-(1-1/n)* torch.mean(torch.abs(batch - w3))return loss1, loss2 # 2. 数据处理:滑动窗口化defcreate_windows(data, window_size): windows =[]for i inrange(len(data)- window_size +1): windows.append(data[i:i+window_size].reshape(-1))return np.array(windows)# 3. 模拟实战流程defrun_usad_demo():# 模拟数据生成:5个维度的传感器数据 np.random.seed(42) normal_data = np.random.rand(1000,5) test_data = np.random.rand(200,5) test_data[50:60]+=2.0# 注入异常 scaler = MinMaxScaler() normal_data = scaler.fit_transform(normal_data) test_data = scaler.transform(test_data) w_size =10# 窗口大小 train_windows = create_windows(normal_data, w_size) test_windows = create_windows(test_data, w_size) train_loader = torch.utils.data.DataLoader( torch.from_numpy(train_windows).float(), batch_size=64, shuffle=True)# 实例化模型 model = USAD(w_size *5, z_size=20) opt1 = torch.optim.Adam(list(model.encoder.parameters())+list(model.decoder1.parameters())) opt2 = torch.optim.Adam(list(model.encoder.parameters())+list(model.decoder2.parameters()))# 训练循环 epochs =20for epoch inrange(epochs):for batch in train_loader: loss1, loss2 = model.training_step(batch, epoch +1) loss1.backward(retain_graph=True) opt1.step() opt1.zero_grad() loss2.backward() opt2.step() opt2.zero_grad()if epoch %5==0:print(f"Epoch {epoch} complete")# 检测 model.eval()with torch.no_grad(): test_batch = torch.from_numpy(test_windows).float() z = model.encoder(test_batch) w1 = model.decoder1(z) w2 = model.decoder2(model.encoder(w1))# 计算异常得分 scores =0.5* torch.mean(torch.abs(test_batch - w1), axis=1)+ \ 0.5* torch.mean(torch.abs(test_batch - w2), axis=1)return scores if __name__ =="__main__": scores = run_usad_demo()print("Top 5 anomaly scores:", scores[:5].numpy())

4.3 预期执行结果

执行该代码后,你会看到模型在 Epoch 15-20 左右趋于稳定。由于我们在 test_data[50:60] 处注入了巨大的偏移值,反映在 scores 结果中,索引 50 附近的数值会远高于其他区域(通常高出 10-50 倍),此时通过设置阈值(如均值的 3 倍标准差)即可实现自动报警。


五、 深度进阶:如何在生产环境中落地 USAD?

作为资深架构师,我建议在实际部署(如 CentOS7 生产环境)时考虑以下几点:

5.1 阈值自动选择

不要使用固定阈值。推荐使用 POT (Peak Over Threshold) 算法。它基于极值理论,可以根据数据分布自动计算出一个动态的、科学的异常边界。

5.2 模型剪枝与加速

USAD 的全连接层虽然简单,但在处理 100 维以上的指标时速度会变慢。在 CentOS 环境下,可以考虑使用 TensorRT 进行模型量化,或者将 PyTorch 模型转化为 ONNX 格式,从而在 CPU 上也能达到毫秒级的推理速度。

5.3 增量学习 (Incremental Learning)

工业环境的“正常”定义是会随季节或生产计划改变的。建议每隔一周使用最近的正常数据对 USAD 进行 Fine-tuning,避免模型因环境漂移导致的误报。


六、 总结

USAD 算法通过简洁而巧妙的对抗自编码器架构,解决了多维时序异常检测中“重构过强”的痛点。它既具备深度学习的非线性拟合能力,又通过对抗机制增强了对微小异常的敏感度。

无论你是要监控 Kubernetes 集群的性能指标,还是检测风力发电机的传感器数据,USAD 都是一个非常扎实且易于落地的起点。

Read more

Flutter 三方库 image_compare 鸿蒙图像治理算法域双向适配解析:突破千万级相册视觉感知哈希运算指纹比对墙,大体量空间冗余清扫提供高精雷达矩阵-适配鸿蒙 HarmonyOS ohos

Flutter 三方库 image_compare 鸿蒙图像治理算法域双向适配解析:突破千万级相册视觉感知哈希运算指纹比对墙,大体量空间冗余清扫提供高精雷达矩阵-适配鸿蒙 HarmonyOS ohos

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 image_compare 鸿蒙图像治理算法域双向适配解析:突破千万级相册视觉感知哈希运算指纹比对墙,为大体量空间冗余清扫提供高精雷达矩阵 前言 在 OpenHarmony 应用的内容社交或相册管理开发中,由于重复下载或连拍,用户的磁盘空间极易被重复图像挤占。image_compare 为 Flutter 开发者提供了一套高性能、专注于图像指纹算法的对比方案。本文将介绍如何在鸿蒙端打造极致的视觉资产治理底座。 一、原理解析 / 概念介绍 1.1 基础原理/概念介绍 image_compare 的核心逻辑是基于 感知哈希(Perceptual Hashing, pHash)与颜色直方图空间映射 (Visual-Entropy Map)。它并非简单的逐像素二进制对比,而是通过将图像进行灰度化、离散余弦变换(DCT)降噪,提取反映图像“骨架结构”的

算法奇妙屋(三十四)-贪心算法学习之路 1

算法奇妙屋(三十四)-贪心算法学习之路 1

文章目录 * 一. 力扣 [860. 柠檬水找零](https://leetcode.cn/problems/lemonade-change/description/) * 1. 题目解析 * 2. 算法原理 * 3. 代码 * 二. 力扣 [2208. 将数组和减半的最少操作次数](https://leetcode.cn/problems/minimum-operations-to-halve-array-sum/description/) * 1. 题目解析 * 2. 算法原理 * 3. 代码 * 三. 力扣 [179. 最大数](https://leetcode.cn/problems/largest-number/) * 1. 题目解析 * 2. 算法原理 * 3. 代码 一. 力扣

​ 封装哈希表实现unordered_set/undered_map

​ 封装哈希表实现unordered_set/undered_map

Hello大家好! 很高兴与大家见面! 给生活添点快乐,开始今天的编程之路。 我的博客:<但愿. 我的专栏:C语言、题目精讲、算法与数据结构、C++ 欢迎点赞,关注 目录 一 STL标准库中unordered_set/unordered_map的使用     1.1参考文档 二  哈希表的实现(抓住映射)     2.1哈希表的概念     2.2哈希表的实现方法一直接定址法     2.3哈希表相关概念           2.3.1  哈希冲突           2.3.2负载因⼦(由于扩容,注意不同方法的扩容条件不同)           2.3.3将关键字转为整数    2.4哈希函数(用于解决/降低哈希冲突)           2.4.1除法散列法/

【数据结构与算法】单链表的综合运用:1.合并两个有序链表 2.分割链表 3.环形链表的约瑟夫问题

【数据结构与算法】单链表的综合运用:1.合并两个有序链表 2.分割链表 3.环形链表的约瑟夫问题

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《C语言》《【初阶】数据结构与算法》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、合并两个有序链表 * 1.1题目 * 1.2 算法原理 * 1.3代码 * 二、分割链表 * 2.1题目 * 2.2 算法原理 * 2.3代码 * 三、环形链表的约瑟夫问题 * 3.1题目 * 3.2 算法原理 * 3.3代码 * 总结与每日励志 前言 链表是C语言数据结构的核心内容,也是算法面试的高频考点,其灵活的指针操作与逻辑构建对编程思维要求颇高。本文聚焦链表经典实操题型,从合并有序链表、分割链表到环形链表约瑟夫问题,由浅入深拆解解题思路,

阿里云全品类 8 折券限时领,建站 / AI / 存储通用 立即领取