時系列データの異常検知に利用できるデータセットまとめ

ICML、ICLR、KDD等のトップカンファレンスで登場する論文を概観し、これらの中で、センサーやアクチュエータの駆動データなど、時系列データセットで、近年利用されているデータセットを解説します。

本記事の内容

  • 時系列異常検知ベンチマークの全体像
  • 各データセットの特徴と規模
  • Pythonでのデータ読み込みと可視化の例

データセット一覧

本記事で扱うデータセットをまとめます。

データセット ドメイン 次元数 訓練サンプル 異常率 公開年
telemanom 人工衛星テレメトリ 25チャネル 各数千点 ~1-3% 2018
WADI 水処理プラント 127 1,048,571 ~6% 2017
SWaT 水処理テストベッド 51 495,000 ~12% 2016
SMD サーバーマシン 38 各708,405 ~4% 2019
PSM サーバーメトリクス 25 132,481 ~28% 2021

telemanom(NASA人工衛星テレメトリ)

telemanom(Telemetry Anomaly Detection)は、NASA JPLのHundman et al.が2018年に発表したデータセットです。火星探査ローバーCuriosityや国際宇宙ステーション(ISS)などの人工衛星のテレメトリ(センサーデータ)から構成されています。

データの特徴

  • チャネル数: 25(E, P, M等のプレフィックスで命名)
  • 各チャネル: 1次元の時系列
  • 訓練データ: 正常なデータのみ
  • テストデータ: 正常データ + 異常データ(ラベル付き)
  • データ形式: NumPy .npy ファイル

データの読み込みと可視化

import numpy as np
import matplotlib.pyplot as plt

# telemanomデータの想定されるディレクトリ構造:
# telemanom/
#   data/
#     train/
#       E-1.npy, E-2.npy, ...
#     test/
#       E-1.npy, E-2.npy, ...
#   labeled_anomalies.csv

# データ読み込みの例(ファイルパスは環境に合わせて変更)
# train_data = np.load("telemanom/data/train/E-1.npy")
# test_data = np.load("telemanom/data/test/E-1.npy")

# ダミーデータでの可視化例
np.random.seed(42)
n_train = 3000
n_test = 1000

# 正常データ(訓練)
train_data = np.sin(np.linspace(0, 20 * np.pi, n_train)) + np.random.normal(0, 0.1, n_train)

# テストデータ(異常あり)
test_data = np.sin(np.linspace(20 * np.pi, 27 * np.pi, n_test)) + np.random.normal(0, 0.1, n_test)
test_data[500:530] += 3  # 異常区間

fig, axes = plt.subplots(2, 1, figsize=(14, 6))

axes[0].plot(train_data, 'b-', linewidth=0.5)
axes[0].set_title("telemanom: Train Data (normal)")
axes[0].set_xlabel("Time step")
axes[0].set_ylabel("Value")
axes[0].grid(True, alpha=0.3)

axes[1].plot(test_data, 'b-', linewidth=0.5)
axes[1].axvspan(500, 530, alpha=0.3, color='red', label='Anomaly region')
axes[1].set_title("telemanom: Test Data (with anomaly)")
axes[1].set_xlabel("Time step")
axes[1].set_ylabel("Value")
axes[1].legend()
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

WADI(Water Distribution Testbed)

WADIは、シンガポール工科デザイン大学(SUTD)のiTrustラボが構築した水処理・配水プラントのテストベッドから収集されたデータセットです。

データの特徴

  • センサー数: 127(流量計、圧力計、バルブ状態等)
  • 攻撃の種類: 15種類のサイバーフィジカル攻撃
  • 正常データ: 14日間の連続運転データ
  • 攻撃データ: 2日間(攻撃を含む)
  • サンプリング間隔: 1秒

WADIは多変量時系列異常検知の標準的なベンチマークとして広く利用されています。

SWaT(Secure Water Treatment Testbed)

SWaTは、WADIと同じくSUTDのiTrustラボが提供するデータセットで、水処理プラントのテストベッドから収集されています。

データの特徴

  • センサー数: 51(水位、流量、圧力、化学物質濃度等)
  • 攻撃の種類: 36種類のサイバーフィジカル攻撃
  • 正常データ: 7日間
  • 攻撃データ: 4日間
  • サンプリング間隔: 1秒
  • 異常率: 約12%

データの規模比較

import numpy as np
import matplotlib.pyplot as plt

# 各データセットの規模を比較
datasets = ['telemanom', 'SWaT', 'WADI', 'SMD', 'PSM']
dimensions = [25, 51, 127, 38, 25]
train_samples = [3000, 495000, 1048571, 708405, 132481]
anomaly_rates = [2, 12, 6, 4, 28]

fig, axes = plt.subplots(1, 3, figsize=(16, 4))

# 次元数の比較
axes[0].barh(datasets, dimensions, color='steelblue', alpha=0.8)
axes[0].set_title("Number of Dimensions")
axes[0].set_xlabel("Dimensions")
axes[0].grid(True, alpha=0.3, axis='x')

# 訓練データ数の比較
axes[1].barh(datasets, [s/1000 for s in train_samples], color='coral', alpha=0.8)
axes[1].set_title("Training Samples (x1000)")
axes[1].set_xlabel("Samples (K)")
axes[1].grid(True, alpha=0.3, axis='x')

# 異常率の比較
axes[2].barh(datasets, anomaly_rates, color='mediumseagreen', alpha=0.8)
axes[2].set_title("Anomaly Rate (%)")
axes[2].set_xlabel("Rate (%)")
axes[2].grid(True, alpha=0.3, axis='x')

plt.tight_layout()
plt.show()

SMD(Server Machine Dataset)

SMDは、OmniAnomaly(Su et al., 2019, KDD)の論文で公開されたサーバーマシンのデータセットです。

データの特徴

  • サーバー数: 28台
  • 各サーバーの次元数: 38(CPU使用率、メモリ、ネットワーク等)
  • データ長: 各サーバー約708,405点
  • 異常ラベル: テストデータに付与
  • 特徴: 各サーバーが異なるパターンを持つ

SMDは、サーバーごとに個別のモデルを訓練して評価することが多く、モデルの汎化性能を評価するのに適しています。

PSM(Pooled Server Metrics)

PSMは、eBay社が公開したサーバーメトリクスデータセットです(Abdulaal et al., 2021, KDD)。

データの特徴

  • 次元数: 25
  • 訓練データ: 132,481点
  • テストデータ: 87,841点
  • 異常率: 約28%(比較的高い)
  • 特徴: 欠損値を含む

データセット選択のガイドライン

手法を評価する際のデータセット選択の指針をまとめます。

import matplotlib.pyplot as plt
import numpy as np

# レーダーチャートでデータセットの特性を比較
categories = ['Dimensions', 'Data Size', 'Anomaly Rate', 'Complexity', 'Popularity']
n_cats = len(categories)

# 各データセットのスコア(1-5の5段階評価)
scores = {
    'telemanom': [2, 1, 1, 2, 4],
    'SWaT': [3, 3, 3, 4, 5],
    'WADI': [5, 5, 2, 5, 4],
    'SMD': [3, 5, 2, 3, 5],
    'PSM': [2, 2, 5, 3, 3],
}

angles = np.linspace(0, 2 * np.pi, n_cats, endpoint=False).tolist()
angles += angles[:1]

fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))

colors = ['steelblue', 'coral', 'mediumseagreen', 'orange', 'mediumpurple']
for (name, vals), color in zip(scores.items(), colors):
    vals_closed = vals + vals[:1]
    ax.plot(angles, vals_closed, 'o-', linewidth=2, color=color, label=name)
    ax.fill(angles, vals_closed, alpha=0.1, color=color)

ax.set_xticks(angles[:-1])
ax.set_xticklabels(categories, fontsize=11)
ax.set_ylim(0, 5)
ax.set_title("Dataset Characteristics Comparison", fontsize=14, pad=20)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))
plt.tight_layout()
plt.show()

まとめ

本記事では、時系列異常検知で利用される代表的なデータセットを解説しました。

  • telemanom: NASA人工衛星のテレメトリデータ。1次元チャネルの集合
  • SWaT / WADI: 水処理プラントのサイバーフィジカル攻撃データ。高次元で実プラント環境
  • SMD: サーバーマシンのメトリクス。複数サーバーで汎化性能を評価可能
  • PSM: eBay公開のサーバーメトリクス。異常率が高く欠損値を含む
  • データセット選択は、次元数・データ規模・異常率・ドメインの適合性を考慮して行う