登堂入室LSTM:使用LSTM进行简单的时间序列异常检测

登堂入室LSTM

LSTM进行时间序列异常检测

使用LSTM进行时间序列异常检测(Time Series Anomaly Detection),分为两步。
第一步是使用LSTM进行时间序列预测
第二步是使用预测结果(y_hat)与实际结果(y_test)的差值进行异常区间的判断。

关于如何使用LSTM进行时间序列预测可以看我的前一篇博文
简单粗暴LSTM:LSTM进行时间序列预测


初始入门

首先介绍一下我们的数据
登堂入室LSTM:使用LSTM进行简单的时间序列异常检测_第1张图片
图中蓝色数据为测试数据y_test,黄色数据为LSTM进行预测的预测结果y_hat
获取差值
首先我们获取测试结果和预测结果的差值e

e = [abs(y_h-y_t[0]) for y_h,y_t in zip(y_hat, y_test)]

结果为:
登堂入室LSTM:使用LSTM进行简单的时间序列异常检测_第2张图片
其次对e进行加权平滑

smoothing_window = 105
e_s = list(pd.DataFrame(e).ewm(span=smoothing_window).mean().values.flatten())

平滑之后的结果为
登堂入室LSTM:使用LSTM进行简单的时间序列异常检测_第3张图片
然后我们对平滑后的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]

我们这时的窗口如图
登堂入室LSTM:使用LSTM进行简单的时间序列异常检测_第4张图片

对于每个窗口进行异常检测

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

这时我们进行异常检测的结果如图
登堂入室LSTM:使用LSTM进行简单的时间序列异常检测_第5张图片

对每个窗口汇总可得到最终结果

注:代码之后会上传到我的github
参考&来源
A framework for using LSTMs to detect anomalies in multivariate time series data
Keras中文文档-Sequential model

你可能感兴趣的:(DeepLearning)