佳木斯市网站建设_网站建设公司_轮播图_seo优化
2025/12/18 10:42:36 网站建设 项目流程

原文:towardsdatascience.com/hands-on-time-series-anomaly-detection-using-autoencoders-with-python-7cd893bbc122

异常时间序列是一个非常严肃的问题。

如果你考虑地震异常是指数据中突然的峰值或下降的地震信号,这暗示着可能正在发生不好的事情。

金融数据中,每个人都会记得 1929 年的华尔街崩溃,那是一个在金融领域具有异常的信号的明显例子。在工程中,峰值信号可以代表超声波反射到墙壁或人身上的情况。

所有这些故事都源于一个非常明确的问题:

如果我有一系列正常的信号,并且一个新的信号进来了,我如何检测这个信号是否异常?

注意,这个问题与检测给定信号中的异常的问题略有不同(这也是一个众所周知的问题)。在这种情况下,我们假设我们得到了一个全新的信号,我们想知道这个信号是否与我们的数据集中被认为是“正常”的信号有足够的差异。

那么你将如何处理这样的问题呢?

强大的**神经网络**为我们提供了这个问题的解决方案,这个解决方案自 2016 年以来一直存在。实现神经网络本身现在是一个相当简单的事情,但理解如何使用神经网络进行异常检测可能会有些棘手。

这篇博客文章的目的是引导读者了解使用神经网络进行异常检测的概念,将这两个主题结合在一个独特的代码片段中,从 A 到 Z。我们还将对合成数据集上的时序进行自己的异常检测案例研究。

希望介绍部分足够有趣 🤞。现在让我们开始吧!

0. 想法

一般而言,一个好的方法是“假装自己是计算机”。问题是“如果你(一个人类)来做这个任务,你会怎么做?”。嗯,我们确实有一系列的信号,对吧?所以可以说,我们需要处理信号以找到某种相关的特征并将它们用作参考。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/de7db3077a0d1334cae322b304203b06.png

作者制作的照片

这是第一步。我们现在有一组参考值。这些参考值将通过简单的比较来确定新的信号是否异常。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/70e23a8799156b8f53a0902493af93de.png

作者制作的照片

所以它的工作原理是这样的:

  • 一个新的信号进来了,

  • 我们提取这个新信号的特征

  • 我们比较特征与我们之前从数据库中提取的特征,并检查它是否是一个异常。就这么简单。

现在,真正的正题如下:

“我们如何处理数据库(以及新的信号)以提取特征?”

这确实是使异常检测算法与其他算法不同的地方。不用太多想象力,在机器学习中,提取特征的模型通常被称为特征提取器

1. 特征提取器

现在有许多特征提取器,数量众多。我今天想谈论的一个涉及深度学习

深度学习(并且一直是)科技界的热门话题:每个人都谈论它。而且有原因,我会这么说。我们在日常新闻中看到的所有令人惊叹的事物:由 Meta AI LLAma 驱动的聊天机器人,由 Google 驱动的圆形搜索功能,Midjourney卓越的“想象”功能,都是(非常成功)深度学习架构的例子。

但深度学习可以比这些例子简单得多。甚至一个非常简单的猫/狗图像分类器也可以是一个深度学习算法。一般来说,当我们谈论一个以“分层”方式学习的算法时,我们指的是深度学习算法(这就是为什么它被称为深度),它允许你自行提取特征,绕过手动特征工程步骤。例如,如果我们区分猫和狗的图像,也许第一层会得到非常简单的特征(如图像的主要颜色),随着我们深入到这个兔子洞,最后一层会得到非常精细的细节(如图像中的爪子)。

我不想过多地谈论哲学,所以我们来谈谈我们的特定深度学习算法,它被称为编码器-解码器,更具体地说,自动编码器

1.1 自动编码器

我们的深度学习算法非常特别,因为它旨在重建你作为输入的相同对象。就像这样:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1653e830bada661d89734d9ad289d5f8.png

作者制作的照片,狗的照片由Caleb Fisher在Unsplash上拍摄

现在,这看起来有点荒谬,对吧?为什么需要一个仅训练来复制你所看到内容的机器学习算法呢?想象一下 ChatGPT,想象一下如果模型只是精确地复制你所写的内容,那这有什么帮助呢?

好吧,自编码器的技巧在于它们的架构。自编码器的输入单元数量(这些单元不过是值,实数)与输入大小相同。例如,如果狗狗图像是 10×10=100 像素,输入将是 100 个单元长。输出与输入具有相同数量的单元。然而,在中间,单元的数量会减少。较少的单元数量被称为“潜在空间”,这是有意义特征的空间。您只需要 k<100 个单元(潜在空间中的一个)来重建整个图像,因此它们必须是关键的

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/70626ed39341834260292ab6c4f63e6a.png

作者使用惊人的NN-SVG工具制作的图像

换句话说,“隐藏层”或“潜在空间”包含了我们可以用来复制作为输入获得的信号(或图像或文本)的关键信息。

我能从电脑那头听到你在问我“我们为什么需要这个来进行异常检测?”好吧,这是逻辑:

如果我训练一个机器学习模型来复制猫的图像,这意味着它将能够成功复制猫的图像。

但相反的情况也是真实的:如果给你另一张图片,并且它无法成功复制,那么这张图片可能不是猫的图片-> 它是一个异常!

更技术地说,如果非异常重建信号的误差平均来说,比如说当我们找到异常信号时,我们希望得到 0.10 的误差,并且由于它是正常误差的 10 倍,我们可以自信地称它为异常。

我知道这可能会让人困惑,但希望当我们用 Python 进行实际操作示例时,它将变得更加清晰。让我们开始吧!

2. 我们的实际操作示例

在本节中,我们将:

  • 定义我们需要的Python

  • 构建我们的“正常信号

  • 构建我们的“异常信号

  • 训练我们的自编码器

  • 分类异常信号与非异常信号。

好的,让我们开始吧。

2.1 Python 环境

我们使用了numpy进行数据处理(您也可以使用pandas),matplotlibseaborn来绘制图像,tensorflow用于深度学习,sklearn用于错误分析。

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D1&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D1&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1723941149428&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

*对于这个非常简单的练习,我们不需要对神经网络有太多的控制,因为我们将会使用一个非常简单的 1D CNN(剧透啦)。因此,我们可以直接使用tensorflow。如果你是torch的用户,也没有问题!这种方法同样适用。

2.2 数据生成器

让我们先描述一下我们将如何设置我们的实验。我们将有一个x的范围,它将从-8π到 8π。一个“非异常”信号的构建方式如下:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1575f1b610ad72f742b8147946642f88.png

由作者制作的照片

其中:

  • A_1、A_2 和 A_3 是三个随信号变化的随机振幅,其值可以从-2 到 2 之间取

  • f_1、f_2 和 f_3 是三个随信号变化的随机频率,其值可以从-2 到 2 之间取

异常信号的构建方式如下:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/21e96cd06ff228a6c23dfbd1a0c06b84.png

由作者制作的照片

其中,一切与正常信号相同,但:

  • A_anomaly 可以在-5 到-2 之间以及从 2 到 5 之间取值

  • f_anomaly 可以在-10 到-5 之间以及从 5 到 10 之间取值

换句话说:

  • 正常信号是由三个具有随机振幅和随机频率的正弦分量组成的

  • 异常信号是由三个具有随机振幅和随机频率的正弦分量组成的,并且包含一个具有较大绝对振幅和较大绝对频率的正弦分量

这是我们如何在 Python 中实现这个想法:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D2&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D2&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1723941149428&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

上述代码生成了num个正常信号和num个异常信号。我们设置 num=1000,但您可以根据需要增加或减少它。您还可以将正弦分量的数量从默认的 3 个增加到您想要的任何数量。

因此,如果我们绘制它们,我们可以清楚地看到在幅度和(主要是)频率方面的差异*:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D3&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D3&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1723941149428&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

2.3 自动编码器

在这个项目中我们使用的自动编码器是一个 1D CNN。1D CNN 在信号处理中应用广泛,其原理相当简单。有一个小的(向量)通过卷积操作在信号上运行。就像在 2D CNN 中一样,可以使用多个过滤器来提取信号的有意义特征。例如,一个过滤器可以查看最大值,一个查看它们的宽度,一个查看最小值,等等。

这就是我们构建自动编码器的方式:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D4&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D4&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1723941149428&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

为了训练我们的模型,我们需要重塑我们的向量。我们可以使用以下方法来完成:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D5&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D5&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1723941149428&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

因此现在我们可以用这个来训练我们的模型:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D6&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F14%26cellId%3D6&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1723941149428&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

2.4 异常检测器

现在我们有了我们的模型,我们可以尝试重建信号。

我们将正常信号作为输入,并提取我们 MSE 的一些统计数据。例如,我们可以考虑 p = 0.99 的百分位数值。然后我们将重建我们的异常信号,并查看 MSE。如果 MSE 大于 0.99 百分位数值,那么我们称之为异常,否则,我们称之为正常信号。

就像这样:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D7&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D7&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1724018516508&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

正如我们所见,所有异常都被正确分类为异常,并且“代价”仅为 3 个被分类为异常的正常信号(在 1000 个信号中)。

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D8&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D8&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1724018516508&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

2.5 同时全部完成!

现在你可能会想,正常信号和异常信号确实差异很大,因此我们可以,例如,使它们变得更加相似。我创建了一个函数,允许你调节真实信号和异常信号的频率和幅度范围。你只需将它们放入一个像这样的字典中:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D9&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D9&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1724018516508&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

并且,执行相同分析的自定义setup_dict边界的整个函数如下:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D10&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D10&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1724018516508&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

您可以像这样运行它:

cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D11%26hideOutput%3Dtrue&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fencoder-decoder-ad%2Fv%2F15%26cellId%3D11%26hideOutput%3Dtrue&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F1ad0531fe41145eeb2ebb4ecc5a577df%2Fpreview%2F18f2f805d617496495e0b6900f5339f0%3Fts%3D1724018516508&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian

在上面的默认 setup_dict 中,异常频率和振幅与正常频率非常相似。

尽管如此,性能非常好:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/33c2742d3f30507ef622b65daa42befa.png

由作者使用上述代码制作的照片

只有44 个异常没有被检测到,只有13 个正常信号被错误地检测为异常。

最终,当正常频率和异常频率相同或非常相似时,当然,区分正常和异常信号是不可能的,但看到我们如何将我们的自编码器推向区分正常和异常信号的程度是非常有趣的。

3. 结论

非常感谢您花时间与我交流。在这篇文章中,我们做了以下几件事情:

  • 讨论了异常检测:我们描述了异常检测的问题,特别是在时间序列的多个场景中,如工程、金融和地质学。

  • 引入自动编码器:我们解释了自动编码器用于异常检测的想法。我们从描述深度学习算法开始,讨论了自动编码器,并介绍了基于重建误差使用自动编码器进行异常检测的概念。

  • 生成合成数据:我们构建了正弦波的合成数据集,包括有异常和无异常的情况。

  • 实现了模型:使用一维卷积神经网络(CNN)构建了自动编码器,该编码器被训练以复制正常信号。

  • 使其可定制:我们证明了我们的方法适用于我们的数据集,并创建了一个非常简单的函数,允许用户修改正常和合成数据集,并与之互动。

4. 关于我!

再次感谢您抽出宝贵时间。这对我们意义重大 ❤

我的名字是 Piero Paialunga,我就是这里的人:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0b3f51bd650634b8fe39a633fe6855c9.png

由作者制作的照片

我是辛辛那提大学航空航天工程系的博士研究生,同时也是 Gen Nine 的机器学习工程师。我在博客文章和领英上谈论人工智能和机器学习。如果你喜欢这篇文章,并想了解更多关于机器学习的内容,以及跟随我的研究,你可以:

A. 在**领英上关注我,我在那里发布所有故事。B. 订阅我的通讯。这将让您了解新故事,并有机会给我发信息,以接收您可能有的所有更正或疑问。C. 成为推荐会员,这样您就不会有“每月故事最大数量”的限制,您可以阅读我(以及成千上万的机器学习和数据科学顶级作家)关于最新技术的所有文章。D. 想和我一起工作?请查看我的收费和项目在Upwork**!

如果你想问我问题或开始合作,请在这里或**领英**上留言:

[email protected]

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询