《异常检测——从经典算法到深度学习》10 Bagel: 基于条件 VAE 的鲁棒无监督KPI异常检测

《异常检测——从经典算法到深度学习》

相关:

10 Bagel: 基于条件 VAE 的鲁棒无监督KPI异常检测

2018 Robust and Unsupervised KPI Anomaly Detection Based on Conditional Variational Autoencoder
下载地址

本文结构:

  • 翻译部分:只摘取一部分翻译,如果希望读全文翻译请前往我的个人博客 smileyan.cn。
  • 代码部分:介绍一下源代码地址,代码环境配置,数据集选择等等内容。
  • 总结部分:此部分单纯的是个人收获,仅提供参考价值。

10.1 论文阅读

有粉丝提出建议可以简单翻译一下论文以供大家参考,但是担心篇幅过长,所以把翻译部分挪到了个人博客。 smileyan.cn

这里只摘录一部分内容,具体内容请参考 smileyan.cn

10.1.1 Abstract

为了确保基于网络的服务不间断,运营商需要密切监控各种 KPI ( KPI ,如CPU使用情况、网络吞吐量、页面浏览量、在线用户数量等),检测其中的异常,并及时触发故障排除或缓解。可能有数十万甚至数百万个 KPI 需要监控,因此运营商需要自动异常检测方法。然而,当面对大量的 KPI 时,无论是传统的统计方法还是监督集成方法都不能满足这一要求。一种最先进的无监督方法提供了有希望的结果,但它不是一个顺序模型,因此不能处理与时间信息相关的异常。因此,本文提出了Bagel算法,这是一种鲁棒的、无监督的 KPI 异常检测算法,可以处理与时间信息相关的异常,使用 CVAE 来合并时间信息和丢失层,以避免过拟合。我们使用互联网公司的真实数据进行的实验表明,与 Donut 相比,Bagel 将异常检测最佳 F1-score 提高了0.08到0.43。

10.1.2 Introduction

为了确保不间断的网络服务,运营商需要密切监控各种 KPI ( KPI ,如CPU使用情况、网络吞吐量、页面浏览量、在线用户数量等),检测其中的异常情况,并及时触发故障排除或缓解。图1显示了我们在本文中研究的几个 KPI 。可能有数十万甚至数百万个 KPI 需要监控[1],[2],因此操作员需要自动异常检测方法。

尽管过去提出了许多异常检测方法[3]–[12],但根据[11],大多数方法在实践中效果不佳。表一 显示了一份比较摘要,将在下文第六章详细阐述。对于传统的统计算法[3]–[7],操作员必须手动选择异常检测算法,并为每个 KPI 调整其参数。基于监督学习的方法[8],[9]需要手动标记每个 KPI 的异常。因此,无论是传统的统计方法还是基于监督学习的方法都不是自动的,当面对大量的 KPI 时,它们在实践中不能很好地工作。

在这里插入图片描述

最近,使用深度生成模型的无监督方法显示了一些非常有希望的结果。基于 VAE这种最新技术 Donut [11] ,显著优于最先进的监督集成方法 Opprentice(对周期性KPI是经典算法中最优的, 比如图1中的 A \mathcal{A} A, B \mathcal{B} B, C \mathcal{C} C )。周期性 KPI 在实践中是非常普遍的,并且与业务相关(如在线用户数量、查询数量),因此,对周期性 KPI 的异常检测非常重要。

然后,Donut 在处理关于时间信息相关的异常时的健壮性是不够的。这是因为 VAE 不是序列模型而 Donut 通过使用滑动窗口的方式处理 KPI 数据来训练 VAE 但是却忽略了窗口与窗口之间的相关性等。Donut 忽略了 每个 KPI 窗口的时间信息,而 Donut 使用的 基于 SGD 的优化算法将训练数据进行了打乱。例如,图1 G \mathcal{G} G 中相对较长的缺失数据片段导致缺失数据片段之后的数据点的假阳性(false positives )(在图中最右边的蓝色虚线框中突出显示),而我们可以想象如果我们以某种方式将定时信息结合到模型中(那些蓝色框中的模式在不同的日子非常相似),这些假阴性(false negatives) 是可以避免的。类似地,图1 H \mathcal{H} H 的每日凹处值处周期性(因此是正常的) 尖峰将被 Donut 错误地分类为异常,然而,结合时间信息将会起起作用。

在这里插入图片描述
由于 Donut 是最先进的异常检测算法,更重要的是有坚实的理论基础,在本文中,我们旨在通过提高 Donut 对时间信息相关异常(如图1中的 G ,    H \mathcal{G},\ \ \mathcal{H} G,  H)的鲁棒性,将 Donut 推向实际部署的重要一步。请注意,在本文中,我们也关注周期性 KPI 中的异常检测,就像 Donut [11] 中一样。

我们提出了 Bagel 算法,一种鲁棒的、无监督的 KPI 异常检测算法。为了包含时间信息,Bagel 是基于条件变化自动编码器(CVAE),而不是 Donut 中的 VAE,并使用时间信息作为输入条件。然而,将时间信息结合到 CVAE 中是一项巨大挑战。由于拟合时间和 KPI value 之间的关系比拟合输入滑动窗口和重构的正态模式之间的关系要容易得多(类似于具有周期性的传统统计模型,如历史平均值),CVAE 对周期性 KPI 的时间信息进行拟合时容易出现过拟合的结果。为了避免过拟合,我们添加了额外的 dropout 层,它可以用于为许多更小的神经网络构建一个全局模型。

本文的贡献可归纳如下:

  • 在文献中,我们第一次发现了时间信息在 KPI 异常检测问题中对于非顺序深度生成模型的重要性。
  • 据我们所知,Bagel是第一个将条件变分自动编码器(CVAE)应用于KPI异常检测,并使用丢失技术成功避免过拟合的人。
  • 我们使用互联网公司的真实数据进行的实验表明,与 Donut 相比, Bagel 将 KPI G \mathcal{G} G H \mathcal{H} H 的异常检测最佳 F1-score 提高了0.08至0.43,大大提高了 Donut 对时间信息相关异常的鲁棒性。

论文的其余部分组织如下。第4章 A 部分综述KPI 异常检测、VAE、CVAE 的背景(错误!这里应该是指第2章)。第3章展现了 Bagel 的神经网络结构以及它的训练与异常检测的设计。第4章是对Bagel 性能评估。第5章是对 Bagel 的原理分析。第6章介绍了相关工作。最后,第7章总结全文。
在这里插入图片描述

注: 为了避免篇幅过长,将翻译部分挪到了 smileyan.cn

10.2 论文代码

以上内容可以对整篇论文有个简单的了解,论文也提供了相应的源码,地址为:https://github.com/NetManAIOps/Bagel

10.2.1 安装 Bagel

先查看一下 Bagel 的依赖环境,即查看 https://github.com/NetManAIOps/Bagel/blob/master/requirements.txt

mltoolkit
torch==0.4
torchvision
visdom
numba
jupyterlab
numpy
scipy
matplotlib
seaborn
numba
pandas
tables
sklearn
mltoolkit
statsmodels
dill
pymongo
click

建议先安装好 pytorch 再根据这个文件安装依赖。

pip install torch==0.4.1.post2 -i https://mirrors.aliyun.com/pypi/simple/

同时需要降低一下 numpy 的版本。

pip install numpy==1.15.0 -i https://mirrors.aliyun.com/pypi/simple/

然后再 git clone 源码,并进行安装依赖。

注意1 安装依赖之前需要修改 requirements.txt 文件,因为很明显这个文件是存在问题的。两个 mltoolkit 需要删除。

注意2 安装依赖之前需要修改 requirements.txt 文件,因为已经安装了 torch 0.4.1.post2 所以把 requirements.txt 中的 torch 那行也删除。或者改成 torch==0.4.1

在源码的目录下输入以下命令:

pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

如果提示错误:

ERROR: Could not find a version that satisfies the requirement mltoolkit (from -r requirements.txt (line 1)) (from versions: none)
ERROR: No matching distribution found for mltoolkit (from -r requirements.txt (line 1))

解决方法就是把 requirements.txt 中的两行 mltoolkit 删除。

如果错误提示:

  ERROR: Could not find a version that satisfies the requirement torch==0.4 (from -r requirements.txt (line 1)) (from versions: 0.1.2, 0.1.2.post1, 0.1.2.post2, 0.4.1, 0.4.1.post2, 1.0.0, 1.0.1, 1.0.1.post2, 1.1.0, 1.2.0, 1.3.0, 1.3.1, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.7.1, 1.8.0, 1.8.1, 1.9.0)
ERROR: No matching distribution found for torch==0.4 (from -r requirements.txt (line 1))

需要修改requirements.txt 中 torch的版本,改为 0.4.1

如果提示错误:

RuntimeError: PyTorch was compiled without NumPy support

那么极有可能就是 numpy 版本太高的问题,需要像上面提到的一样,降低 numpy 版本。然后再次安装torch. 参考

解决问题后再次执行,确保安装正确。

pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

10.2.2 运行demo

源代码中提供了一个测试用的数据集,sample_data.csv ,而且路径什么的都是对的,所以跑测试代码非常简单:

在源码目录下执行以下命令:

python main.py

输出内容如下:
在这里插入图片描述

10.2.3 测试其他数据集

测试其他数据集的时候,数据集需要具有以下三个属性:

  • timestamp
  • value
  • label

为了方便测试其他数据集,我们对 main.py 代码进行更改,并且直接运行这些代码。(在 notebook 环境下)

from model import DonutX
import pandas as pd
import numpy as np
from kpi_series import KPISeries
from sklearn.metrics import precision_recall_curve
from evaluation_metric import range_lift_with_delay

# 需要更改这个文件的路径
df = pd.read_csv('sample_data.csv', header=0, index_col=None)
kpi = KPISeries(
    value = df.value,
    timestamp = df.timestamp,
    label = df.label,
    name = 'sample_data',
)

train_kpi, valid_kpi, test_kpi = kpi.split((0.49, 0.21, 0.3))
train_kpi, train_kpi_mean, train_kpi_std = train_kpi.normalize(return_statistic=True)
valid_kpi = valid_kpi.normalize(mean=train_kpi_mean, std=train_kpi_std)
test_kpi = test_kpi.normalize(mean=train_kpi_mean, std=train_kpi_std)

model = DonutX(cuda=False, max_epoch=50, latent_dims=8, network_size=[100, 100])
model.fit(train_kpi.label_sampling(0.), valid_kpi)
y_prob = model.predict(test_kpi.label_sampling(0.))

y_prob = range_lift_with_delay(y_prob, test_kpi.label)
precisions, recalls, thresholds = precision_recall_curve(test_kpi.label, y_prob)
f1_scores = (2 * precisions * recalls) / (precisions + recalls)
print(f'best F1-score: {np.max(f1_scores[np.isfinite(f1_scores)])}')

10.2.4 关于 delay 参数

有小伙伴提问,论文源码中怎么没有 delay 参数调节。

如果需要测试一下对于不同的 delay 运行效果如何,只需要更改其中一行代码:

y_prob = range_lift_with_delay(y_prob, test_kpi.label)

更改为:

y_prob = range_lift_with_delay(y_prob, test_kpi.label, delay=1)

再次运行就可以发现 f1-score 不是 可怕的 1.0 了。

10.2.5 安装成功后运行范围限制

如果已经成功安装并且能够正常运行,但是新建一个notebook,运行 main.py 中的代码,发现报错 ModuleNotFoundError: No module named 'model'

这个与安装范围有关,与 Donut 不同,Donut 带有 setup 来设置全局安装,而 Bagel 安装后只能在当前目录下使用。

也就是说如果新建 notebook 的话,需要在 Bagel 安装目录下新建。才能正常运行。

如果先打开了 notebook 再去安装 Bagel 环境的话,需要重启一下 notebook 才能正常使用。

10.2.6 更多问题

上面的几个问题是小伙伴私信提到的,觉得可能其他人也会遇到这种问题,因此特意摘录一下。

更多问题欢迎评论,一起解决问题。

10.3 论文总结

推荐去读一下原论文,或者可以参考这个全文翻译smileyan.cn

论文中反复说明:这个不是 Bagel 的成就,那个不是 Bagel 的成就。

但是这个不影响这个论文的成就,是值得一读的,但是如果读过 Donut 相关论文的话,那么理解这篇论文就简单得多了。因为很多部分只需要关注两篇论文的不同之处就可以了。

但不得不说的是,事实上,Donut 的效果并没有那么好,依然会被异常影响严重,而 Bagel 只是取得了一定的优化效果,并且它的鲁棒性是有限的。简单总结,论文在 Donut 基础上做了两件事情:1. Donut 忽略了时间戳这个重要数据中蕴含着的月,星期等信息,这里添加上了。2. 添加上以后容易出现过拟合,所以引入了 dropout 层。

如果如果需要做对比实验的话,一定要把重点放在鲁棒性方面进行对比。


事实上,关于这一系列博客的编写一直在不断地纠结中,是否应该以 翻译 为主还是以 代码 相关为主,或者以自己的 理解 为主?都加起来的话,是否会导致篇幅过大根本就没有人愿意读?

如果有好的建议或者意见,请一定留言提出,感谢!


编写不易,拒绝白piao。。。

感谢 您的 阅读点赞收藏评论 ,别忘了 还可以 关注 一下哈,感谢 您的支持!

Smileyan
2021.3.9 20:02
2021.6.26 22:21 添加安装补充与运行参数delay添加

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

smile-yan

感谢您的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值