多变量时间序列异常检测数据集与可运行Baseline实战指南
2026/9/20 14:07:18 网站建设 项目流程

简介:面向多变量时间序列异常检测研究者的资源包,整合SMD、SMAP/MSL、SWaT与WADI四类公开数据集及配套标准化处理代码,解决从数据下载、时间格式统一到异常标签生成的预处理难题。其中SMD来自服务器机器,SMAP/MSL来自航天器遥测,SWaT与WADI分别覆盖水处理系统和配水网络,为工业故障检测、航天监控、水利安全等场景提供了跨领域基准数据。压缩包共10个文件,约30MB,包含CSV原始/处理后数据、TXT说明文件、Python处理脚本、HTML报告页面及运行配置文件,目录结构清晰,便于按数据集快速定位。已有502人学习/下载,适合数据分析、算法研究人员和具备基础Python能力的开发者使用。资源特别提供Python数据处理脚本与依赖清单,可一键完成MSL、SMAP、SMD、WADI、SWaT数据集的读取、解析与标签处理;并附处理结果摘要和可视化报告页面,帮助使用者核对预处理效果,直接投入模型训练与异常检测实验。 我第一次做多变量时间序列异常检测的时候,光是在“数据集选哪个”这件事上就耗了将近一周。网上能搜到的数据集名字不少,但每个的格式、标签方式、异常类型都不一样,有的要填表申请,有的下载回来是一堆没有任何说明的npy文件。真正跑通一个能用的baseline,比想象中费劲得多。所以这篇就把我实际整理过的多变量时间序列异常检测数据集和可直接运行的源码经验写出来,覆盖选型思路、数据格式、预处理、可运行baseline和几个容易被忽略的坑,给准备入门的同学和需要快速选型的工程师做个参考。

1. 选数据集前先想清楚:你的异常长什么样

很多人选数据集只看“哪个名气大、哪个论文用得多”,但我建议先反过来想一个问题:你要检测的异常,到底是什么形态?

1.1 异常形态决定评测粒度

多变量时间序列里的“异常”其实分好几类,不同数据集的异常形态差异非常大,选错了会导致后续评估方式完全对不上。

第一种是点异常,指某个时间点上的单个样本值明显偏离正常范围。比如MSL、SMAP这类航天器遥测数据里,某个传感器突然跳变然后恢复,训练集里没有这种模式。这类异常适合做逐点评估,模型只需要判断“这个时间点是不是异常”。

第二种是子序列异常,指一段时间内的连续行为异常。SWaT、WADI这类物理系统数据集大多属于这一类,攻击者篡改阀门或传感器后,异常会持续几十秒甚至几分钟,不是单点跳变。对这类异常做逐点评估会非常刻薄,因为窗口边界错一个点就算误判,所以很多论文会引入我们后面会讲的“点调整”策略。

第三种是相关异常,也就是单通道数值看起来都正常,但通道之间的联合分布被破坏了。比如两个传感器在正常工况下有明显的比例关系,突然这个联动关系消失了。这类异常是多变量模型的甜区,也是单变量模型识别不了的场景。我见过不少新手拿着单变量检测器硬跑这类数据,效果奇差,还以为是模型不行,其实是问题本身就超出了模型能力。

1.2 按场景锁定数据集

想清楚异常形态后,选数据集就简单了:

  • 快速验证算法、做学术迭代:首选Tsinghua、SMD、PSM这类公开可下载、切分固定的数据,不用等流程,能立刻跑起来。
  • 验证工业物理系统场景:选SWaT、WADI,它们有真实的物理攻击过程,异常有明确的因果关系,缺点是申请流程需要时间。
  • 研究航天遥测点异常:MSL、SMAP是标准答案,维度低、规模小,很快就能跑完一轮实验。

我个人的建议是不要一上来就追求“最复杂、最工业”的数据集。先把一个公开数据集的预处理和评估流程跑通,再换更复杂的场景,效率会高很多。

2. 主流数据集的“性格差异”:从SWaT到Tsinghua

把数据集列成一张表,很多事情会瞬间清晰。

数据集来源环境维度常见切分异常形态获取门槛
SWaT水处理试验台51训练约49.5万/测试约44.9万传感器/执行器攻击,子序列异常iTrust官网申请
WADI水分配系统123训练约78.4万/测试约17.3万泄漏等物理故障,子序列异常iTrust官网申请
MSL火星科学实验室55训练约5.8万/测试约7.4万遥测点异常为主NASA公开/GitHub
SMAP土壤水分卫星25训练约1.4万/测试约4.3万遥测点异常为主NASA公开/GitHub
SMD服务器集群监控38×28个实体前28天训练/后14天测试真实运维异常,混合形态GitHub公开
PSMeBay线上服务26训练约13.2万/测试约14.2万运维异常,信号较干净GitHub公开
Tsinghua互联网业务KPI单变量KPI×多个序列按时间连续切分真实业务异常,人工标注GitHub公开

2.1 每个数据集值得注意的细节

SWaT的训练集全部是正常数据,测试集里混有攻击数据,标签列常见的命名是“Normal/Attack”,但不同渠道下载的版本列名可能不一样,读取时需要先看一眼列名。它的攻击是分阶段注入的,异常占比约在一成以上,比较适合评估“能否在持续异常中快速报警”。

WADI的维度高达123列,最容易踩坑的是CSV里可能有特殊字符、空格和编码问题,直接pd.read_csv可能会出现一堆列名错乱。另外WADI的异常占比明显低于SWaT,正负样本不平衡更严重,随手用accuracy评估会得到虚高的漂亮数字,基本没有参考价值。

MSL和SMAP下载回来通常是npy或pickle格式,自带多个实体ID。它们经常被当作“多实体多变量”数据使用,但单实体维度不高。因为是以点异常为主,很多深度模型在这里其实发挥不出时序优势,倒是适合做快速基线验证。

SMD是28个服务器实体的监控数据,每个实体38个指标,训练和测试按天切分。它的价值在于多实体结构更接近真实运维场景,但代价是你需要决定是逐实体训练还是做联合建模。

PSM是eBay开源的线上服务监控指标,26维,异常标注做得比较干净,分布相对稳定,是我个人觉得最适合新手练手的数据集之一。

Tsinghua数据集严格说是单变量KPI集合,但因为包含大量实体、有明确时间连续性,经常被用来做多实体时间序列异常检测的baseline。如果你关注KPI异常检测方向,这个数据集基本绕不开。

2.2 数据量级与计算成本的匹配

很多教程不会提醒你数据集规模对算力的影响。SMD要训练28个实体,如果每个实体都上Transformer,单卡可能得跑很久;而ECOD、Isolation Forest这类轻量模型五分钟就能全跑完。SWaT和WADI的数据量中等,GNN或Transformer还能接受,但做消融实验时多跑几组也会很费时间。

我的经验是:初期先用轻量模型把整套流程走通,确认代码、评估、可视化都没问题,再上重模型,省下的都是真金白银的时间。

3. 别让数据格式卡住你:统一加载与预处理方案

数据集下载回来后,第一道坎不是模型,而是格式。SWaT是CSV,MSL/SMAP是npy或pickle,SMD是文本文件,Tsinghua是一个zip包里面放一堆CSV。如果为每个数据集单独写一套加载逻辑,光这一点就很劝退。

3.1 SWaT这类CSV的读取坑

SWaT的CSV通常有表头,第一列是时间戳,后面是传感器和执行器数值,最后一列是标签。但不同渠道的标签列名不一样,可能是“Normal/Attack”,也可能是“Label”或“attack”。我建议写一个统一的加载函数,先打印出列名看一眼再处理。

import pandas as pd def load_swat(train_path, test_path, label_path): train = pd.read_csv(train_path) test = pd.read_csv(test_path) labels = pd.read_csv(label_path) # 这里假设标签列名是 Normal/Attack,实际以你下载到的版本为准 train = train.drop(columns=["Timestamp"]) test = test.drop(columns=["Timestamp"]) label_column = [c for c in labels.columns if "attack" in c.lower() or "normal" in c.lower()] if label_column: y_test = labels[label_column[0]].map({"Normal": 0, "Attack": 1}).values else: y_test = labels.iloc[:, -1].values return train.values, test.values, y_test

CSV里偶尔会有空值,SWaT某些通道在攻击阶段会有NaN。不要直接dropna,因为时间序列的行顺序是有含义的,删除某一行会破坏连续性和标签对齐。更好的做法是先用前向填充再少量插值。

3.2 标准化与数据泄露

这是新手最容易踩死的一个坑。很多人习惯把训练集和测试集拼到一起做标准化,这属于严重的数据泄露,会让测试指标虚高。

from sklearn.preprocessing import StandardScaler # 错误示范:把train和test放一起fit # data = np.concatenate([train, test], axis=0) # scaler = StandardScaler().fit(data) # 正确做法:只用训练数据fit scaler = StandardScaler() train = scaler.fit_transform(train) test = scaler.transform(test)

标准化只允许在训练集上估计均值和方差,测试集用同一套参数做变换。数据泄露在异常检测里尤其隐蔽,因为测试集里本身包含异常点,如果这些异常点参与了均值和方差的估计,会把异常拉回“正常范围”,模型自然看不出来。

3.3 滑动窗口切分的正确姿势

大多数时序模型需要把原始序列切成固定长度的窗口。简单方式是直接循环切片,但数据量大时内存会爆炸。

import numpy as np def sliding_window(X, window_size): n = len(X) Xs = [] for i in range(n - window_size + 1): Xs.append(X[i:i + window_size]) return np.stack(Xs)

如果数据量很大,更推荐用PyTorch的Dataset接口,在__getitem__里按索引实时取窗口,而不是一次性预切分:

import torch from torch.utils.data import Dataset class SeriesWindowDataset(Dataset): def __init__(self, X, window_size): self.X = X self.window_size = window_size def __len__(self): return len(self.X) - self.window_size + 1 def __getitem__(self, idx): return self.X[idx:idx + self.window_size]

切窗口时记住一个关键点:标签不要乱取,一般取窗口最后一个时间点的标签作为整个窗口的标签,因为窗口内的历史信息是在为“当前时刻是否异常”服务的。

3.4 多实体数据要拆分实体ID

SMD、MSL、SMAP这类多实体数据集,训练和测试文件里通常包含多个实体。很多人直接整个文件读进来、全局切窗、全局标准化,这样做会引入实体间的伪相关,属于跨实体的数据混用。

标准做法是先按实体ID分组,每个实体单独标准化、单独切窗。评估时也一样,先算每个实体的指标,再取macro平均,而不是把所有实体混在一起算。

4. 可运行源码盘点:官方开源与统一评测框架

说实话,除了少数分类任务之外,大多数异常检测数据集没有官方训练源码。所谓“可运行源码”实际分三类:优秀开源项目自带的预处理和模型、统一评测框架、以及你按需组合的最小baseline。

4.1 开源项目里已经封装好的数据加载器

很多知名异常检测开源项目已经内置了数据集处理逻辑,拿过来就能复现论文结果。

  • thuml/Anomaly-Transformer:内置了Tsinghua、MSL、SMAP、SMD等数据集的加载与切分逻辑,照着README跑一遍就能出结果。
  • OmniAnomaly:对SMD的处理非常完整,包含数据归一化、窗口化、训练循环和可视化。
  • TranAD:也内置了多个数据集的适配器,适合用来跑对比实验。

我建议你拿到一个新数据集时,先去找一个成熟项目看它怎么组织预处理流程,比自己摸半天要快得多。很多预处理细节(比如标签是0-index还是1-index、测试集有没有重叠窗口、实体ID怎么编码)都藏在代码里,官方文档反而不写。

4.2 最小可运行baseline:ECOD实战

如果你想在自定义数据上快速跑通全链路,ECOD(经验累积分布函数)是目前最省事的无监督方法之一,不需要训练标签,一管到底。

import pandas as pd from pyod.models.ecod import ECOD from pyod.utils.data import evaluate_print # train.csv 全部是正常历史数据 train = pd.read_csv("train.csv").values test = pd.read_csv("test.csv").values labels = pd.read_csv("label.csv").values.ravel() clf = ECOD(contamination=0.05) clf.fit(train) pred = clf.predict(test) evaluate_print("ECOD", labels, pred)

这段代码里contamination表示你预先估计的异常比例,ECOD会用训练数据的分位数自动确定阈值。整个流程跑通不到一分钟,非常适合作为第一个baseline。之后你再换TranAD、Anomaly Transformer这类深度模型,就能对比“轻量方法”和“深度方法”的差距到底有多大,而不是一头扎进复杂代码里调试。

4.3 统一评测框架怎么选

如果你不想自己写评估代码,有几个现成框架可以用:

  • PyOD:最通用的异常检测库,支持ECOD、IForest、KNN等大量方法,接口统一,适合快速对比。
  • Tods:微软开源,偏自动化机器学习的时序异常检测,内置了数据处理、特征工程、检测算法全链路。
  • Merlion:偏轻量部署,自带时序数据集接口和评估工具,适合想快速产品化的场景。
  • TimeEval:学术评测框架,可以把多个算法和多个数据集统一挂进去批量跑实验。

这些框架各有侧重,但基础思路是一样的:数据集通过统一接口加载,模型通过统一接口训练和预测,减少自己写胶水代码的时间。我的建议是不要每个框架都装,先选一个最顺手的用熟,其他按需再上。

4.4 同一数据集不同切分的结果对比陷阱

这是需要特别提醒的一点:同一个数据集,不同开源项目可能采用完全不同的切分方式,结果之间是不能直接对比的。

以SWaT为例,官方按时间连续切分训练和测试,但有些社区复现会随机抽70%数据训练,有些会做在线滚动预测,还有的会截取某一段攻击最多的区间做测试。同一套算法在这几种切分下,F1可能从0.75浮动到0.93,差距大得离谱。

所以看论文时一定要看它实验部分的“dataset setting”,复现时也要确认切分规则和原论文一致。不做这一步,你的模型效果“更好”很可能只是切分规则不同造成的假象。

5. 跑通之后最容易被忽略的四个细节

代码能跑只是第一步,我在实际使用中发现,下面这四件事决定你的结果是不是真正可信。

5.1 点调整(PA)带来的虚高

很多论文在评估时会用点调整策略:只要模型预测的某一段和真实异常段有任意重叠,就把整个预测段标为正确。好处是贴近“事件是否被命中”的直觉,坏处是容易虚高。

你的模型可能把一段100个点的异常只预测中了其中1个点,PA之后这100个点全算正确,F1直接奔着1.0去。这对工业场景是危险的,因为实际运维里漏报警和误报警不会因为你“沾了点边”就被原谅。

我的建议是评估时同时报两组指标:逐点F1和事件级命中率。逐点F1反映模型对异常边界的识别精度,事件级命中率反映“有没有抓到这件事”。两个都亮出来,模型真实水平一目了然。

5.2 窗口尺寸选错,异常直接失效

窗口大小是所有方法里最微妙也最容易被忽视的参数。窗口太短,长漂移异常根本看不出来;窗口太长,短促点异常会被大量正常历史信息“稀释”掉。

我一般这样选:先看异常标注的持续时间分布。SWaT攻击通常持续若干秒到几分钟,如果传感器是10Hz采样,窗口可以取几十到几百个点;KPI业务异常通常在1到5分钟内,按分钟级采样取5到15个点;航天遥测的点异常往往只有一到两个点,窗口太多反而帮倒忙。

你可以把窗口尺寸当作一个先验知识输入,而不是纯超参瞎试。做消融实验时也建议报告不同窗口下的效果,很多论文不写这一点,但实际上它对结果影响非常大。

5.3 阈值只能从训练侧决定

无监督异常检测模型输出的往往是异常分数,不是概率。分数高不代表“异常概率大”,只是“和训练分布偏差大”。这个分数怎么转成0/1标签,取决于阈值怎么定。

最常见的作弊做法:跑完测试集之后,用测试集异常分数的95%分位当阈值。这等于提前知道了测试集的信息,指标会好看但不真实。

正确做法是:从训练数据里再切出一段正常的验证集,模型训练完成后在验证集上打分,取比如95%或99%分位点作为阈值,再拿到测试集上预测。阈值一旦定了就不要因为测试集的分数分布往回调整,这是确保评估可信的底线。

5.4 多实体全局混排会得到伪装的高分

SMD和Tsinghua这类多实体数据,如果所有实体拼在一起做全局标准化,实体之间的水平差异会让模型的异常分数分布严重偏离真实情况。结果往往是分数最高的那批点集中在某些正常实体上,真正的异常反而被淹没了。

标准流程是:每个实体独立标准化、独立切窗、独立预测,最后按实体粒度算macro-F1。如果你的模型要联合多个实体学习,至少也要加上实体ID作为条件信息,让模型知道当前处理的是哪台设备。落地部署时这个细节更重要,因为运维关心的是“哪台设备出了问题”,不是一个模糊的全局分数。

6. 工业界的另一种视角:从WM-811K到安检图像的时间序列思维

最后一个部分想说说热词里反复出现的WM-811K和X光安检物品检测。这些看起来是图像任务,和时序异常检测关系不大,但工业场景里很多问题站在时间序列角度看会完全不一样。

6.1 WM-811K的“空间快照”与时间展开

WM-811K是晶圆制造领域的经典数据集,样本是晶圆图,被用来做缺陷分类和异常检测。它看起来是二值图像分类问题,但晶圆制造过程中,腔室温度、压力、气流速率等状态变量都是连续记录的多变量时间序列。一块晶圆出现缺陷,往往是某些工艺参数在某个阶段发生异常累积的结果。

如果你已经会做多变量时间序列异常检测,完全可以把WM-811K当作下游验证场景:用工艺参数时间序列预测晶圆良率缺陷,而不是只对着缺陷图做空间分类。这也是工业AI落地中很常见的思路,把问题从“事后找图”变成“事前告警”。

6.2 安检图像连续帧背后的序列异常

网上有人搜“X光安检物品检测数据集 voc+yolo”,他们真正想解决的是传送带上的物品识别。但X光安检的视频流天然带时间维度:物品在传送带上运动、遮挡、分离,异常物品往往不是在某一帧突然出现,而是多帧连续观察中才暴露特征的。

这和时序异常检测的“状态转移”理念是相通的。只看单帧图像,重物遮挡、角度变化都可能误判;连续多帧联合判断,能把“这是一个完整物体”和“这里有不该出现的东西”区分得更好。所以我建议做图像异常检测的工程师,也值得学一点多变量时间序列思维,它提供的不是另一种算法,而是另一种看问题的视角。

6.3 工业落地的三件烦心事

最后说点实在的。工业异常检测落地,跟刷benchmark完全是两码事。标签稀缺是最普遍的痛点,时间序列异常的人工标注成本极高,很多工厂连“哪些时间点出了问题”都说不清。类别不平衡也很要命,异常占比经常不到百分之一,模型很容易学成“永远报正常”。概念漂移就更麻烦了,设备老化、工艺调整、季节变化都会让数据分布缓慢移动,今天好用的模型三个月后可能就是废的。

我个人现在的选择是,在算法研究之外,一定要给自己留一条在线监控和定期重训的路径。模型跑在真实系统里,不是训完就完事,而是要能回放历史数据、查看误报漏报、定期加入新样本迭代。

如果让我从零开始做这个方向,流程会短很多:先用Tsinghua或SMD把全链路跑通,再用SWaT/WADI验证物理系统异常场景,最后才碰大规模多实体模型和跨模态工业数据。这个顺序能帮你避开我当年踩过的那些坑。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询