GRELEN: グラフ関係学習による多変量時系列異常検知

多変量時系列の異常検知では、個々のセンサーの値だけでなく、センサー間の依存関係の変化を捉えることが重要です。GRELEN(Graph Relational Learning Network)は、IJCAI 2022で発表された手法で、VAEとGNNを組み合わせてセンサー間の確率的グラフ構造を学習し、異常を検知します。

本記事では、GRELENの論文の内容を数式とともに丁寧に解説します。

元論文: IJCAI 2022 — GRELEN: Multivariate Time Series Anomaly Detection from the Perspective of Graph Relational Learning

本記事の内容

  • 多変量時系列異常検知の課題
  • GRELENのアーキテクチャ
  • VAEによるグラフ関係学習の数式
  • 実験結果と考察

前提知識

この記事を読む前に、以下の概念を理解しておくと読みやすくなります。

多変量時系列異常検知の課題

産業システムやインフラでは、多数のセンサーが同時にデータを取得しています。異常検知では、個々のセンサー値の異常だけでなく、センサー間の関係性の変化を捉える必要があります。

例えば、水処理システム(SWaT)では、あるセンサー LIT-101 が異常を示すと、それに連動して FIT-101 やアクチュエータ MV-101 の値も変動します。一方で、P-101 は直接的な変動を示さない場合もありますが、他のセンサーとの関係性を見ることで異常検知に寄与できます。

従来の手法の課題は以下の通りです。

  • 多くの手法はセンサーを独立に扱い、依存関係を考慮しない
  • グラフ構造を学習する手法はあるが、固定的なグラフを仮定するものが多い
  • 時間とともに変化する動的な依存関係を扱えない

問題の定式化

$N$ 個のセンサーがあるシステムを考えます。時系列データ全体を $\bm{X} \in \mathbb{R}^{N \times T}$ と表します。

  • センサー $i$ の時系列: $X_i = \bm{X}_{i,:}$
  • 時刻 $t$ での全センサー値: $X^t = \bm{X}_{:,t}$
  • スライディングウィンドウ $w$ を用いた入力: $S^t = X^{t-w+1:t}$

目標は、時刻 $t$ における異常判定 $y^t = f(S^t) \in \{0, 1\}$ を教師なしで学習することです。

GRELENのアーキテクチャ

GRELENは、VAEの構造をベースに、以下の3つのモジュールから構成されます。

  1. Encoder: 入力 $S^t$ から潜在的なグラフ関係のパラメータを学習
  2. Sampling Layer: 学習した分布からグラフ構造をサンプリング
  3. Decoder: サンプリングしたグラフ構造を用いて再構成

Encoder

Encoderへの入力はスライディングウィンドウ $S^t$ です。Encoderの目的は、条件付き分布 $q_\phi(\bm{Z}^t | S^t)$ を学習することです。

各センサーの時系列をGRU(Gated Recurrent Unit)で埋め込みます。

$$ \begin{equation} \bm{h}_i^t = \text{GRU}(S_i^t) \quad (i = 1, \dots, N) \end{equation} $$

センサー $i$ と $j$ の間の関係を表すパラメータ $\theta_{i,j}^t$ は、埋め込みから計算されます。

$$ \begin{equation} \theta_{i,j}^t = \sigma(\bm{h}_i^t \cdot \bm{W} \cdot (\bm{h}_j^t)^T) \end{equation} $$

ここで $\sigma$ はシグモイド関数、$\bm{W}$ は学習可能な重み行列です。$\theta_{i,j}^t$ はセンサー $i$ と $j$ の間にエッジが存在する確率を表します。

Sampling Layer

$\theta_{i,j}^t$ をパラメータとするベルヌーイ分布からグラフのエッジをサンプリングします。

$$ \begin{equation} z_{i,j}^t \sim \text{Bernoulli}(\theta_{i,j}^t) \end{equation} $$

ベルヌーイ分布は離散的なため、直接微分できません。GRELENではGumbel-Softmaxトリックを用いて連続緩和し、勾配を通せるようにしています。

$$ \begin{equation} \tilde{z}_{i,j}^t = \sigma\left(\frac{\log \theta_{i,j}^t – \log(1 – \theta_{i,j}^t) + g_1 – g_2}{\tau}\right) \end{equation} $$

ここで $g_1, g_2$ は Gumbel(0,1) からのサンプル、$\tau$ は温度パラメータです。

Decoder

サンプリングされたグラフ $\bm{Z}^t$ を隣接行列として使い、GNN(Graph Neural Network)でセンサー間の情報を伝搬させます。

$$ \begin{equation} \bm{H}^{(l+1)} = \text{ReLU}(\bm{Z}^t \bm{H}^{(l)} \bm{W}^{(l)}) \end{equation} $$

最終的にGRUデコーダを通して、時系列の再構成 $\hat{S}^t$ を出力します。

損失関数

GRELENの損失関数はVAEと同様に、再構成誤差とKLダイバージェンスの和で定義されます。

$$ \begin{equation} \mathcal{L} = \underbrace{\|S^t – \hat{S}^t\|^2}_{\text{再構成誤差}} + \beta \underbrace{D_{\text{KL}}(q_\phi(\bm{Z}^t|S^t) \| p(\bm{Z}^t))}_{\text{KL正則化}} \end{equation} $$

KLダイバージェンスは、各エッジについてベルヌーイ分布間のKLとして計算されます。

$$ \begin{equation} D_{\text{KL}} = \sum_{i,j} \left[\theta_{i,j} \log \frac{\theta_{i,j}}{p_0} + (1-\theta_{i,j}) \log \frac{1-\theta_{i,j}}{1-p_0}\right] \end{equation} $$

ここで $p_0$ はエッジの事前確率(スパース性を制御するハイパーパラメータ)です。

異常スコアの計算

異常スコアは、再構成誤差とグラフ構造の変化度を組み合わせて定義されます。

$$ \begin{equation} A^t = \alpha \cdot \|S^t – \hat{S}^t\|^2 + (1-\alpha) \cdot \Delta(\bm{Z}^t, \bar{\bm{Z}}) \end{equation} $$

ここで $\bar{\bm{Z}}$ は学習データから得られた平均的なグラフ構造、$\Delta$ はグラフ間の距離関数です。再構成誤差だけでなく、グラフ構造の変化も異常の手がかりとして活用する点がGRELENの特徴です。

実験結果

GRELENは以下の4つの実世界データセットで評価されています。

データセット 説明 センサー数
SWaT 水処理システム 51
WADI 水配分システム 123
SMD サーバマシン 38
PSM eBayサーバ 25

主要な結果として、GRELENはF1スコアにおいて多くのベースライン手法(LSTM-VAE, MTAD-GAT, GDN等)を上回る性能を示しています。特に、グラフ構造の学習により、センサー間の依存関係を解釈可能な形で可視化できる点が実用上の大きな利点です。

Pythonでの簡易実装

GRELENの核となるアイデア(グラフ構造の学習と再構成誤差による異常検知)を簡略化して実装します。

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)

# 合成データの生成(3センサーの依存関係あり)
T = 500
N = 3

# 正常時: センサー0 -> センサー1, センサー0 -> センサー2 の依存関係
t = np.arange(T)
x0 = np.sin(0.05 * t) + np.random.normal(0, 0.1, T)
x1 = 0.8 * x0 + np.random.normal(0, 0.1, T)  # x0に依存
x2 = 0.6 * x0 + 0.3 * x1 + np.random.normal(0, 0.1, T)  # x0, x1に依存

# 異常期間: 依存関係が崩れる
anomaly_start = 350
anomaly_end = 400
x1[anomaly_start:anomaly_end] = np.random.normal(0, 0.5, anomaly_end - anomaly_start)
x2[anomaly_start:anomaly_end] += 2.0

X = np.stack([x0, x1, x2], axis=0)  # (N, T)

# スライディングウィンドウで相関行列を計算(グラフ構造の近似)
w = 30  # ウィンドウサイズ
anomaly_scores = np.zeros(T)
graph_distances = np.zeros(T)

# 正常期間の参照相関行列
X_normal = X[:, :anomaly_start]
ref_corr = np.corrcoef(X_normal)

for t_idx in range(w, T):
    window = X[:, t_idx-w:t_idx]
    # 現在のウィンドウの相関行列
    curr_corr = np.corrcoef(window)
    # グラフ構造の変化度
    graph_dist = np.linalg.norm(curr_corr - ref_corr, 'fro')
    graph_distances[t_idx] = graph_dist

    # 再構成誤差(線形回帰による予測からの逸脱)
    pred_1 = 0.8 * window[0]
    pred_2 = 0.6 * window[0] + 0.3 * window[1]
    recon_error = np.mean((window[1] - pred_1)**2 + (window[2] - pred_2)**2)

    # 総合異常スコア
    anomaly_scores[t_idx] = 0.5 * recon_error + 0.5 * graph_dist

# 可視化
fig, axes = plt.subplots(3, 1, figsize=(14, 10))

# 上: 時系列データ
for i in range(N):
    axes[0].plot(X[i], label=f'Sensor {i}', alpha=0.8)
axes[0].axvspan(anomaly_start, anomaly_end, alpha=0.2, color='red', label='Anomaly')
axes[0].set_xlabel('Time')
axes[0].set_ylabel('Value')
axes[0].set_title('Multivariate Time Series')
axes[0].legend()

# 中: グラフ構造の変化度
axes[1].plot(graph_distances, color='green', label='Graph distance')
axes[1].axvspan(anomaly_start, anomaly_end, alpha=0.2, color='red')
axes[1].set_xlabel('Time')
axes[1].set_ylabel('Graph Distance')
axes[1].set_title('Graph Structure Change')
axes[1].legend()

# 下: 異常スコア
axes[2].plot(anomaly_scores, color='purple', label='Anomaly score')
threshold = np.percentile(anomaly_scores[:anomaly_start], 95)
axes[2].axhline(y=threshold, color='orange', linestyle='--', label=f'Threshold ({threshold:.3f})')
axes[2].axvspan(anomaly_start, anomaly_end, alpha=0.2, color='red')
axes[2].set_xlabel('Time')
axes[2].set_ylabel('Anomaly Score')
axes[2].set_title('Anomaly Detection Result')
axes[2].legend()

plt.tight_layout()
plt.show()

この簡易実装では、GRELENの核となるアイデアを相関行列の変化として表現しています。正常時の相関構造からの逸脱と再構成誤差を組み合わせた異常スコアにより、依存関係が崩れた異常期間を検出しています。

まとめ

本記事では、GRELEN(Graph Relational Learning Network)による多変量時系列異常検知について解説しました。

  • GRELENはVAEとGNNを組み合わせ、センサー間の確率的グラフ構造を動的に学習する
  • Gumbel-Softmaxトリックにより離散的なグラフ構造のサンプリングを微分可能にしている
  • 異常スコアは再構成誤差とグラフ構造の変化度の両方を考慮する
  • 4つの実世界データセットで既存手法を上回る性能を示している
  • 学習されたグラフ構造はセンサー間の依存関係として解釈可能である

次のステップとして、以下の記事も参考にしてください。