原文:
towardsdatascience.com/hands-on-neural-networks-and-time-series-with-python-a61d7d75f3d9
在我的学士学位期间,我最喜欢的教授告诉我:
一旦某物工作得足够好,就不再有人称之为“AI”
这个概念与Larry Tesler的观点一致,他曾说过“AI 就是尚未完成的事情。”人工智能的第一个例子是计算器,它能够在几秒钟内完成非常复杂的数学运算,而人类可能需要几分钟或几小时。然而,当我们今天谈论人工智能时,我们并不想到计算器。我们之所以不这么想,是因为它简单地工作得非常好,你把它视为理所当然。谷歌搜索算法,在许多方面比计算器复杂得多,是我们日常生活中使用的一种人工智能形式,但我们甚至没有意识到它。
那么,什么是真正的“AI”?我们什么时候停止将某物定义为 AI?这个问题相当复杂,因为如果我们真正思考,AI 有多个层次和领域。
它肯定有多个复杂性层次。例如,ChatGPT 在概念和计算上比 LeCun 提出的"数字识别" 2D CNN 更复杂,而一个简单的回归算法比 LeCun 提出的数字识别 2D CNN 简单得多(关于这一点稍后还会讨论)。
它肯定也有多个领域。每次我们看到 CAPTCHA 时,我们都在积极地为神经网络创建处理图像的输入。每次我们与 GPT 互动时,我们都在构建 NLP 算法的文本输入。每次我们说“Alexa,打开厨房的灯”时,我们都在为神经网络提供音频输入。虽然从理论上讲,最终一切对计算机来说不过是 0/1 信号,但事实上,处理图像的神经网络在哲学、实现和复杂性方面与处理音频或文本的神经网络完全不同。
这就是为什么公司越来越需要寻找专业的机器学习工程师,他们知道如何处理比其他人更擅长处理的一种特殊类型的数据。例如,在我的职业生涯中,我更多地从事时间序列领域的工作,而不是其他任何事情。这篇博客文章旨在让读者了解在时间序列领域如何使用神经网络。我们还将从不同复杂度的级别进行操作。我们将从最简单的神经网络开始,也就是所谓的前馈神经网络,到最复杂、最现代和复杂的Transformer结构。
我不想让任何读者感到无聊,我也知道,如果没有任何编码,很多读者可能觉得这篇文章没有用,所以我们将会把所有内容从英语翻译成 Python。
让我们开始吧!🚀
1. 前馈神经网络
1.1 解释
我想从这个部分开始,对问题进行简短的形式化。时间序列是一系列随时间记录的观察值。序列中的每个观察值对应于特定的时间点。它有点像这样:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/560dcf1a4afafc99df720964c5b5215c.png
作者制作的照片
对于每一个时间步 t_i,都有一个对应的 y_i。现在很明显,y_i 与 y_i+1 是相关的。正如聪明人所说,数据是“序列的”。尽管如此,一个非常简单的方法是完全忽略时间轴,并将序列 y_1,…,y_T 视为我们前馈神经网络的输入层的单元:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1feef07352a5d8c596d7b16b4ef858ac.png
作者制作的照片
一旦我们有了输入层,我们就会在前馈神经网络中从左到右处理它。例如,如果我们想进行二分类或回归任务,我们可以构建以下 FFNN:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/928c2f10ce77717f17e5e465c7ceffbb.png
作者使用NN SVG制作的照片
现在,你在这个网络中看到的每一个箭头(或线条)都是一个权重,这是一个乘以并相加(+偏差)在单元(即白色圆圈)中的实数。
你可能已经看到了这种方法的优势和为什么我们将其定义为简单:所有的单元都混合在一起,所以“序列性”完全丢失了。当然,如果模型训练得很好,它可能能够通过相应地调整权重来部分恢复它,但我们并没有强制执行这一点,这并不是最好的。这个模型的缺点是简单,优点也是简单:对于非常简单的任务,FFNN 工作得很好,计算成本非常有限。
1.2 代码
现在,让我们考虑一个正弦波。一个非常简单的,就像这样:
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D2&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D2&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F3eed5524702c49e787bd8073cefb32a9%2Fpreview%2F11d52b39e121448997c358df2d5e4c13%3Fts%3D1724775888492&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian
现在,我们将这个任务变得非常简单。首先,我们将进行一个简单的回归,实数回归,简单而甜蜜。输入将是一段正弦波,输出是下一个点。例如,你给我从 t= – 2.9s 到 t= – 2.7s 的正弦值,我给你 t= – 2.6s 时发生的情况。这比说起来容易,看起来是这样的:
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D3&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D3&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F3eed5524702c49e787bd8073cefb32a9%2Fpreview%2F11d52b39e121448997c358df2d5e4c13%3Fts%3D1724775888492&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian
然后,我们训练我们的神经网络从 N 个点的一个序列到 1,其中 1 基本上是下一个点。我让它变得极其简单,你可以通过添加密集层、改变单元数、改变激活函数、改变优化器等方式添加层。
Jovian 上的神经网络与时间序列
我们可以用这段代码来测试结果:
Jovian 上的神经网络与时间序列
如我们所预期的那样,相当不错:我们创建了一个非常简单的任务,并要求一个非常简单的神经网络来完成这项工作。
我不想只给你一个虚构的例子,所以我会说:当以下情况时,考虑使用 FFNN:
时间序列的“顺序性”并不那么相关。例如,可能你有一个与另一个也随时间变化的量度相比的信号。在这种情况下,也许你的时间序列并不是真正的“时间”序列,FFNN(前馈神经网络)可能做得很好。
你希望保持事物简单。这更为常见。考虑序列输入的模型通常计算量更大。FFNN 是一个非常好的替代方案,因为它们允许你考虑甚至非常简单的结构。
除非你有大量的实例(即大型数据集),否则开始时使用 FFNN 是一个好的做法,因为这是最简单的方法。
1D 卷积神经网络
2.1 说明
要使这个事物更复杂,首先需要考虑输入的顺序性。实现这一点的办法是使用一个通过“运行”内核(一小组权重)沿着信号“运行”来处理这种顺序性的模型,如下面的图片所示:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/88006fe98586c380dc88e9b3902f6a9c.png
作者制作的照片
这个操作被称为卷积,相应的网络被称为卷积神经网络(CNN)。当有人谈论 CNN 时,他们可能指的是由**Yann Lecun**这位杰出的头脑构建的结构,他开发了这种网络来将手写数字分类为 0-9。
我上面展示的内容稍后出现,并由 Serkan Kiranyaz 等人于 2015 年开发,在名为**卷积神经网络用于特定患者的 ECG 分类的论文中。现在,原始论文正在进行分类任务**,实际上这是使用 1DCNN(以及 CNN 总体上)的一个很好的方法。因此,我们将构建一个非常简单的 1DCNN 分类算法来区分方波和正弦波。
2.2 代码
这就是我们构建“num (x 2)”时间序列的方法。num 是一个整数。默认设置为 1000,因此我们将生成 2000 个时间序列。我们将有 1000 个方波曲线和 1000 个正弦波曲线。这是如何做到的:
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D7&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D7&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F3eed5524702c49e787bd8073cefb32a9%2Fpreview%2F11d52b39e121448997c358df2d5e4c13%3Fts%3D1724775888492&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian
这些正弦波具有随机的频率、相位和振幅。方波是通过对随机正弦波进行符号操作的结果。让我们看一下,确保它们看起来没问题:
Jovian 上的神经网络时间序列
是的。它们看起来非常好。 🙂
现在我们构建一个具有 32 层和 3 个单位核向量的 1D CNN,并使用 relu 激活函数。我们还进行了一些最大池化操作,然后紧接着是 2 个全连接层。我们编译它,并在训练集上训练模型。虽然有很多词汇,但原理非常简单:
Jovian 上的神经网络时间序列
真美。而且它的表现也非常好,正如我们从这个例子中可以看到:
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D10&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D10&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F3eed5524702c49e787bd8073cefb32a9%2Fpreview%2F11d52b39e121448997c358df2d5e4c13%3Fts%3D1724775888492&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian
许多时候,一维卷积神经网络(1D CNNs)是一个不错的选择,尤其是用于分类。这是因为,它们是简单的神经网络(因为归根结底,它只是卷积操作),但足够复杂以执行复杂的分类任务。与全连接神经网络(FFNN)相比,它们在复杂性上迈出一步,所以你可能需要留意这一点,但再次强调,它们并不是巨大的神经网络。
3. 长短期记忆/循环神经网络
3.1 解释
你还记得第一章,其中我们不得不根据前一个值序列预测正弦波的下一个值吗?
做这件事最常见的方式不是使用 FFNN,而是使用循环神经网络:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/134246d45668d2f9fef001eecf9eebe9.png
由作者制作的照片
现在输入层 y_1,…,y_11 是顺序地通过隐藏状态处理的,这意味着隐藏状态 h_i 的输入不仅包括 yi,还包括前一个隐藏状态 h{i-1}。简而言之,前一个单元的信息在整个层中得以保留。
现在,这种信息的保留方式取决于具体的 RNN。在这个特定的例子中,我们将使用长短期记忆单元。具体来说,我们将执行一个多步预测任务。这基本上与第一章相同,但我们不仅会预测下一步,还会预测接下来的 k 步**。**我们正在生成一个与时间呈二次依赖关系的信号,加上一个小的、高频的小(固定)振幅正弦波。
3.2 代码
当你想使用 LSTM 时,你通常需要进行一些无聊的预处理来将你的输入时间序列分割成块。我在一个函数中完成了这个操作,并将整个流程放在了一个代码片段中:
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D12&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D12&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F3eed5524702c49e787bd8073cefb32a9%2Fpreview%2F11d52b39e121448997c358df2d5e4c13%3Fts%3D1724775888492&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian
让我放大一下预测结果:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8d193d03ac622a17590f6fb81cd51dd2.png
由作者使用上述代码制作的图像
它非常令人印象深刻,它不仅猜对了二次依赖性(即使看起来有一个小的偏差),而且猜对了正弦波的波动行为。
当你使用 LSTM 时,你进入了复杂性的严肃领域。它们是一个相当大的巨兽。它们往往难以训练,并且应该谨慎使用。尽管如此,它们因在众多研究案例中在预测方面处于最前沿而闻名,所以如果你有足够的数据和计算能力,它们确实工作得非常好。如果你不想等待很长时间,在训练期间几乎必不可少的是拥有一个GPU。
4. Transformers
4.1 解释
2017 年发表了一篇论文,截至今天,它已经被引用了 130441 次(截至今天,2024 年 8 月)。这篇论文叫做 “Attention is all you need”,它解释了如何用Transformer模型替换多个序列转换模型,该模型用注意力机制替换了 RNN 和 CNN。
注意力机制允许模型专注于(正如其名所示,放置注意力)输入序列的相关部分。这是因为,当你从序列 A 翻译到序列 B 时,序列 A 的第一个单元“对应”(或翻译)到序列 B 的第一个单元并不一定正确。想想从一种语言翻译到另一种语言。仅仅因为英语句子以 “I” 开头,并不意味着在印度语中,第一个单词是 “I” 的翻译。
注意力机制非常迷人,我强烈建议阅读原始论文,特别是因为它从头开始解释需要花费很长时间。
4.2 代码
现在,我要对您说实话。训练一个 Transformer 是很难的。就像,非常难。想象一下 GPT 中的 T 代表 Transformer。这就是有多难。
因此,我会用一个非常简单的例子来训练一个神经网络,以正弦波作为输入并将其转换为余弦波。这种方法被称为序列到序列。如果您第一次听到“seq2seq”,那是因为我告诉您的 😃。
我们之前使用了 TensorFlow,但现在我们背叛了它,开始使用Pytorch。这是因为如果您想使用 TensorFlow 训练一个 Transformer,您必须自己构建类。TensorFlow 的舒适之处在于您不需要构建自己的类,您可以直接使用 model.fit()(就像我们上面做的那样),其中 model 是迭代定义的。如果我们必须处理类的问题,在我看来,Pytorch 更优越,因为它更直观。
Pytorch 也有这个nn.Transformer函数,它非常酷,因为它与论文非常吻合。
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fjovian.com%2Fembed%3Furl%3Dhttps%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D14&dntp=1&display_name=Jovian&url=https%3A%2F%2Fjovian.ml%2Fpiero-paialunga%2Fneural-networks-time-series%2Fv%2F37%26cellId%3D14&image=https%3A%2F%2Fapi.jovian.com%2Fapi%2Fgist%2F3eed5524702c49e787bd8073cefb32a9%2Fpreview%2F11d52b39e121448997c358df2d5e4c13%3Fts%3D1724775888492&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&scroll=auto&schema=jovian
现在,这个非常简单的任务用 GPU 训练已经非常耗时了。想象一下多个信号。这会变得很混乱。有什么好处呢?好处是您很少需要从头开始训练您的 Transformer。我能想到的唯一情况是:
您有一个非常大的数据集
由于某种原因,没有人听说过这个数据集,而且微调现有的 Transformer 也不是一个选择。
正如您所看到的,这种情况非常罕见。大多数时候,您不需要使用如此复杂的技术。几乎每次您确实需要使用这种复杂技术时,简单地微调现有的 Transformer 就是正确的做法。
5. 结论
感谢您花时间与我一起。这对我很重要。让我们一起阅读这篇文章并总结一下:
我们讨论了神经网络,并讨论了它们在多个领域(音频 vs 图像 vs 文本)和复杂性(FFNN vs CNN vs Transformer)中的多样性。
我们应用了一个前馈神经网络(FFNN),进行了一步预测(回归)任务的正弦波。我们展示了 FFNN 对于计算能力和数据集大小有限的非常简单案例是一个很好的选择。
我们将一维卷积神经网络(1DCNN)应用于分类任务。特别是,我们区分了正弦波和方波。我们展示了非常好的准确率,并展示了 1DCNN 可以在允许稍微更多计算能力的情况下用于分类任务。
我们讨论了长短期记忆网络(LSTM/RNN)**。我们应用 LSTM 进行多步预测。我们讨论了这种神经网络的复杂性以及为什么它需要大量的计算能力,因此需要谨慎。
我们使用“注意力就是一切”论文来描述变换器。我们进行了一个非常简单的 seq2seq 正弦到余弦算法翻译。我们注意到它们在计算上非常昂贵,并指出从头开始训练是非常罕见的,因为大多数情况下,简单的微调是最佳选择。
6. 关于我!
再次感谢您抽出宝贵时间。这对您意义重大 ❤
我叫 Piero Paialunga,就是我这个人:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/5d7ef398c3595facb31fdda9ffa888fb.png
作者制作的照片
我是辛辛那提大学航空航天工程系的博士候选人,也是 Gen Nine 的机器学习工程师。我在博客文章和领英上谈论人工智能和机器学习。如果您喜欢这篇文章,并想了解更多关于机器学习的内容以及关注我的研究,您可以:
A. 在**领英上关注我,我在那里发布所有故事 B. 订阅我的通讯。这将让您了解新故事,并有机会给我发信息,以接收您可能有的所有更正或疑问。C. 成为推荐会员,这样您就不会有“每月故事数量上限”的限制,您可以阅读我(以及成千上万的机器学习和数据科学顶级作家)关于最新技术的所有文章。D. 想和我合作?请查看我在Upwork**上的报价和项目!
如果你想向我提问或开始合作,请在这里或**领英**上留言:
[email protected]