特異スペクトル変換 (SST) とは
= Singular Spectrum Transformation
行列の特異値分解を利用した、時系列データの異常検知の手法。
手順
時系列データ
x=(x1,x2,⋯,xT)に対して、注目する時刻 t から、ウインドウ幅 w 個の要素を取り出し、yt とする:
(x1,⋯,xt,xt+1,xt+2,⋯,xt+(w−1)⏟yt,xt+(w−1)+1,xt+(w−1)+2,⋯,xT)ウインドウを1ずつずらし、同様の操作をして yt+1,⋯,yt+M−1 を抽出する:
(x1,⋯,xt,xt+1,xt+2,⋯,xt+(w−1),xt+(w−1)+1⏟yt+1,xt+(w−1)+2,⋯,xT)(x1,⋯,xt,xt+1,xt+2,⋯,xt+(w−1),xt+(w−1)+1,xt+(w−1)+2⏟yt+2,⋯,xT)⋮(x1,⋯,xt+(M−1)−2,xt+(M−1)−1,xt+(M−1),⋯,xt+(w−1)+(M−1)⏟yt+(M−1),⋯,xT)これら $\boldsymbol{y}t , \cdots, \boldsymbol{y}{t+(M-1)}$ を転置した列ベクトルを並べた行列
HT≡(yTt,⋯,yTt+(M−1))=(xtxt+1⋯xt+(M−1)xt+1xt+2xt+(M−1)+1⋮⋱⋮xt+(w−1)xt+(w−1)+1⋯xt+(w−1)+(M−1))を定義する。
実装例
結果が期待通りにならないのでバグが有りそう。要確認
import numpy as np
from matplotlib import pyplot as plt
T = 5000
w = 10
M = 500
L = 300
ts = np.arange(T) / 100
y_noise = np.random.normal(loc=0, scale=0.1, size=T)
y1 = y_noise + np.where(np.logical_and(4*np.pi < ts, ts < 9*np.pi), np.sin(ts), np.sin(3*ts))
y2 = y_noise + np.sin(ts) + np.where(np.logical_and(np.pi < ts, ts < np.pi*101/100), 5.0, 0)
#plt.plot(ts, y1)
#plt.show()
#plt.plot(ts, y2)
#plt.show()
def get_matrix(i_start, y):
ret = []
for i in range(i_start, i_start+M):
ret.append(y[i:i+w])
return np.array(ret).T
def calc_svd(matrix):
U, s, V = np.linalg.svd(matrix)
return U, s, V
def step(i_start, y):
H = get_matrix(i_start, y)
H_history = get_matrix(i_start-L, y)
U, _, _ = calc_svd(H)
U_history, _, _ = calc_svd(H_history)
_, s, _ = calc_svd((U.T).dot(U_history))
return 1 - s[0]
a_y1 = []
a_y2 = []
for i_start in range(L, T-w-M):
if i_start % 100 == 0:
print(i_start)
a_y1.append(step(i_start, y1))
a_y2.append(step(i_start, y2))
plt.plot(ts[L:T-w-M], a_y1)
plt.show()
plt.plot(ts[L:T-w-M], a_y2)
plt.show()