☰
SMD/SMAP/MSL/SWaT/WADI 5大异常检测数据集:从原始文件到统一CSV格式的3步标准化流程
2026/10/22 9:19:07 网站建设 项目流程

五大工业级时间序列异常检测数据集标准化处理实战指南

1. 工业场景下的时间序列异常检测数据集概述

在智能制造和物联网时代,设备传感器产生的多变量时间序列数据呈指数级增长。SMD、SMAP、MSL、SWaT和WADI这五大数据集已成为学术界和工业界评估异常检测算法的黄金标准。这些数据集具有三个显著特征:

  • 多维度监控:单个实体包含38-127个不等的监测指标,如SMD数据集每台服务器监控CPU负载、内存使用等38个维度
  • 精确标注:测试集包含专家标记的异常片段,SWaT数据集甚至标注了41次攻击的具体时间点
  • 真实场景:全部来自服务器集群、航天器、水处理厂等真实工业环境,WADI数据集采集自真实供水管网16天的运行数据
# 典型数据集维度对比 datasets = { 'SMD': {'entities':28, 'dims':38, 'time_points':1411200}, 'SMAP': {'entities':55, 'dims':25, 'time_points':None}, 'MSL': {'entities':27, 'dims':55, 'time_points':None}, 'SWaT': {'entities':1, 'dims':51, 'time_points':946944}, 'WADI': {'entities':1, 'dims':127, 'time_points':1209600} }

2. 数据集标准化处理的核心挑战

原始数据存在三大典型问题需要解决:

2.1 格式异构性

  • SMD采用TXT文件存储,每行代表一个时间点的所有维度数据
  • SMAP/MSL使用NPY二进制格式,配合CSV标注文件
  • SWaT和WADI提供原始CSV但时间格式不统一

2.2 时间表示差异

  • 匿名时间戳:SMAP/MSL用连续整数代替真实时间
  • 多时区问题:WADI数据集包含新加坡时区的UTC+8时间
  • 格式错误:WADI新版存在时间列解析异常

2.3 标签不一致

  • SWaT用"Normal/Attack"字符串标记
  • WADI采用1/-1表示正常/攻击
  • SMD提供额外的异常维度解释标签

重要提示:处理WADI数据时要特别注意,其第二版本删除了训练集中的不稳定时段,但测试集保持完整,需要特殊处理时间对齐问题

3. 三步标准化处理流程详解

3.1 数据下载与结构重组

SMD数据集处理方案:

# 下载并解压SMD数据集 git clone https://github.com/NetManAIOps/OmniAnomaly.git cd OmniAnomaly/ServerMachineDataset tree -L 2 # 输出结构应包含: # ├── train # ├── test # └── test_label

SMAP/MSL特殊处理:

# 使用wget下载NASA数据集 import subprocess subprocess.run(['wget https://s3-us-west-2.amazonaws.com/telemanom/data.zip'], shell=True) subprocess.run(['unzip data.zip && rm data.zip'], shell=True)

SWaT/WADI申请流程:

  1. 访问iTrust实验室官网填写数据使用申请表
  2. 获取批准后下载压缩包文件
  3. 特别注意WADI有两个版本需要区分

3.2 时间对齐与特征提取

关键操作步骤:

  1. 统一时间列为datetime格式
  2. 处理缺失值(向前填充/线性插值)
  3. 特征重命名规范化为col_0到col_N
  4. 标签列统一转换为0/1二进制格式
# WADI时间修正示例 def recover_wadi_time(df): """修复WADI数据集的时间格式问题""" # 合并Date和Time列 df['datetime'] = pd.to_datetime(df['Date'] + ' ' + df['Time']) # 处理新版数据的时间跳变 if 'Row' in df.columns: ref_time = pd.read_csv('WADI.A1_9 Oct 2017/WADI_14days.csv') ref_time['datetime'] = pd.to_datetime(ref_time['Date'] + ' ' + ref_time['Time']) df = df.merge(ref_time[['Row','datetime']], on='Row') return df.drop(['Date','Time'], axis=1)

3.3 标准化输出结构

最终统一的目录结构规范:

processed_datasets/ ├── SMD │ ├── machine-1-1 │ │ ├── train.csv │ │ └── test.csv │ └── machine-1-2 │ ├── train.csv │ └── test.csv ├── SMAP │ ├── train.csv │ └── test.csv └── WADI ├── train.csv └── test.csv

CSV文件标准字段:

  1. timestamp: 统一的时间戳(或连续ID)
  2. col_[0-N]: 所有特征列
  3. label: 仅测试集包含,0表示正常,1表示异常

4. 各数据集处理代码精要

4.1 SMD处理核心逻辑

def process_smd(input_dir, output_dir): for machine_file in os.listdir(f'{input_dir}/train'): if not machine_file.endswith('.txt'): continue # 处理训练集 train_data = pd.read_csv(f'{input_dir}/train/{machine_file}', delimiter=',', header=None) train_data.columns = [f'col_{i}' for i in range(train_data.shape[1])] train_data['timestamp'] = train_data.index # 处理测试集及标签 test_data = pd.read_csv(f'{input_dir}/test/{machine_file}', delimiter=',', header=None) test_labels = pd.read_csv(f'{input_dir}/test_label/{machine_file}', delimiter=',', header=None) # 合并测试数据和标签 test_data['label'] = test_labels.values test_data['timestamp'] = test_data.index # 保存结果 machine_name = machine_file.replace('.txt','') os.makedirs(f'{output_dir}/{machine_name}', exist_ok=True) train_data.to_csv(f'{output_dir}/{machine_name}/train.csv', index=False) test_data.to_csv(f'{output_dir}/{machine_name}/test.csv', index=False)

4.2 SMAP/MSL特殊处理

def process_nasa_data(dataset_name): # 加载异常标注CSV anomalies = pd.read_csv('data/labeled_anomalies.csv') anomalies = anomalies[anomalies['spacecraft'] == dataset_name] # 构建测试集标签 test_labels = [] for _, row in anomalies.iterrows(): chan_data = np.load(f"data/test/{row['chan_id']}.npy") labels = np.zeros(len(chan_data)) for start, end in ast.literal_eval(row['anomaly_sequence']): labels[start:end+1] = 1 test_labels.extend(labels) # 合并所有通道数据 train_data = np.concatenate([ np.load(f"data/train/{row['chan_id']}.npy") for _, row in anomalies.iterrows() ]) # 保存标准化CSV pd.DataFrame(train_data).to_csv(f'{dataset_name}_train.csv', index_label='timestamp') pd.DataFrame(test_labels).to_csv(f'{dataset_name}_test.csv', index_label='timestamp')

5. 实战问题排查指南

常见问题1:WADI时间对齐失败

  • 症状:测试集出现NaN时间戳
  • 解决方案:使用Row列与旧版数据做精确匹配
# WADI时间修复代码 train_new = pd.read_csv('WADI.A2_19 Nov 2019/WADI_14days_new.csv') train_old = pd.read_csv('WADI.A1_9 Oct 2017/WADI_14days.csv', skiprows=4) train_old['datetime'] = pd.to_datetime(train_old['Date'] + ' ' + train_old['Time']) train_new = train_new.merge(train_old[['Row','datetime']], on='Row')

常见问题2:SMAP数据维度不匹配

  • 症状:label长度与测试数据不一致
  • 检查点:确认labeled_anomalies.csv中num_values与npy文件行数一致

性能优化技巧:

  • 对于大型数据集(如SMD),使用dask替代pandas
  • 处理WADI时限制内存使用:pd.read_csv(..., chunksize=100000)
  • 使用并行处理加速SMD的28台机器处理

6. 标准化数据集的应用验证

完成处理后,可通过以下代码快速验证数据质量:

def validate_dataset(dataset_path): """验证标准化数据集的基本属性""" train = pd.read_csv(f'{dataset_path}/train.csv') test = pd.read_csv(f'{dataset_path}/test.csv') print(f"训练集形状: {train.shape}") print(f"测试集形状: {test.shape}") print("特征维度示例:", [c for c in train.columns if c.startswith('col_')][:5]) if 'label' in test.columns: anomaly_ratio = test['label'].mean() print(f"异常比例: {anomaly_ratio:.2%}") # 检查时间连续性 if 'timestamp' in train.columns: time_diff = pd.to_datetime(train['timestamp']).diff().value_counts() print("时间间隔分布:\n", time_diff.head())

典型输出示例:

训练集形状: (708405, 39) 测试集形状: (708405, 40) 特征维度示例: ['col_0', 'col_1', 'col_2', 'col_3', 'col_4'] 异常比例: 3.17% 时间间隔分布: 00:01:00 708404 Name: timestamp, dtype: int64

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

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

立即咨询