登堂入室LSTM
LSTM进行时间序列异常检测
使用LSTM进行时间序列异常检测(Time Series Anomaly Detection),分为两步。
第一步是使用LSTM进行时间序列预测
第二步是使用预测结果(y_hat)与实际结果(y_test)的差值进行异常区间的判断。
关于如何使用LSTM进行时间序列预测可以看我的前一篇博文
简单粗暴LSTM:LSTM进行时间序列预测
初始入门
首先介绍一下我们的数据
图中蓝色数据为测试数据y_test,黄色数据为LSTM进行预测的预测结果y_hat
获取差值
首先我们获取测试结果和预测结果的差值e
e = [abs(y_h-y_t[0]) for y_h,y_t in zip(y_hat, y_test)]
结果为:
其次对e进行加权平滑
smoothing_window = 105
e_s = list(pd.DataFrame(e).ewm(span=smoothing_window).mean().values.flatten())
平滑之后的结果为
然后我们对平滑后的e_s进行异常检测
简单的异常检测
简单的异常检测就是均值+2.5倍标准差,大于均值+2.5倍标准差的数据会被记录为异常点
设置窗口
batch_size = 2000
window_size = 20
#找到窗口数目
num_windows = int((y_test.shape[0] - (batch_size * window_size)) / batch_size)
# decrease the historical error window size (h) if number of test values is limited
while num_windows < 0:
# 如果 windowsize过大 不断减少 找到刚好的windowsize
window_size -= 1
if window_size <= 0:
window_size = 1
num_windows = int((y_test.shape[0] - (batch_size * window_size)) / batch_size)
# y_test长度小于batchsize
if window_size == 1 and num_windows < 0:
raise ValueError("Batch_size (%s) larger than y_test (len=%s). Adjust it." % (
batch_size, y_test.shape[0]))
#得到窗口e_s
for i in range(1, num_windows + 2):
prior_idx = (i - 1) * (batch_size)
# 前面有i-1个batch size
idx = (window_size * batch_size) + ((i - 1) * batch_size)
if i == num_windows + 1:
# 因为最后一个加的幅度不满于config.batchsize
idx = y_test.shape[0]
window_e_s = e_s[prior_idx:idx]
我们这时的窗口如图
对于每个窗口进行异常检测
perc_high, perc_low = np.percentile(y_test, [95, 5])
# ytest整体的高低差 和方差
inter_range = perc_high - perc_low
chan_std = np.std(y_test)
#inter_range和chan_std如上所示
#error_buffer是异常点周围被判定为异常区间的范围
def get_anomalies(window_e_s,error_buffer,inter_range,chan_std):
mean = np.mean(window_e_s)
sd = np.std(window_e_s)
i_anom = []
E_seq = []
epsilon = mean + 2.5*sd
#如果太小则忽略
if not (sd > (.05*chan_std) or max(window_e_s) > (.05 * inter_range)) or not max(window_e_s) > 0.05:
return i_anom
for x in range(0, len(window_e_s)):
anom = True
#进行check 大于整体高低差的0.05
if not window_e_s[x] > epsilon or not window_e_s[x] > 0.05 * inter_range:
anom = False
if anom:
for b in range(0, error_buffer):
if not x + b in i_anom and not x + b >= len(e_s) :
i_anom.append(x + b)
if not x - b in i_anom and not x - b < 0:
i_anom.append(x - b)
#进行序列转换
i_anom = sorted(list(set(i_anom)))
# groups = [list(group) for group in mit.consecutive_groups(i_anom)]
# E_seq = [(g[0], g[-1]) for g in groups if not g[0] == g[-1]]
return i_anom
这时我们进行异常检测的结果如图
对每个窗口汇总可得到最终结果
注:代码之后会上传到我的github
参考&来源
A framework for using LSTMs to detect anomalies in multivariate time series data
Keras中文文档-Sequential model