首页 > 编程知识 正文

lstm时间序列预测讲解(双向lstm神经网络原理)

时间:2023-05-05 17:02:11 阅读:91429 作者:4859

点击上面关注,All in AI中国

本文重点介绍LSTM神经网络架构的使用方法,使用Keras和Tensorflow提供时间序列预测,特别是在股市数据集上提供股价的动量指标。

此框架的代码位于以下GitHub repo中: (这是基于python 3.5.x版和requirements.txt文件的要求版本的假设。 如果偏离这些版本,可能会发生错误。 (https://Github.com/Jaungiers/lstm-neural-network-for-time-series-prediction

什么是LSTM神经元?

长期困扰传统神经网络体系结构的基本问题之一是如何解释依赖于信息和上下文的输入序列。 该信息可以是句子内的上一个单词,也可以是根据上下文容易预测下一个单词是什么,或者是序列的时间序列信息。

简单地说,传统的神经网络每次都采用独立的数据向量,没有存储器概念来处理需要存储器的任务。

早期解决这个问题的方法是对网络中的神经元使用简单的反馈类型的方法,其中输出反馈到输入,从而提供最后看到的输入的上下文。 这些被称为递归神经网络(RNN )。 这些RNN在某种程度上起作用,但有相当大的缺点,因此在一些重要的用途中存在消失梯度的问题。 我们没有进一步扩展讨论它,而是说为了这个问题,RNN不符合大部分现实问题,所以有必要另找解决办法。

这就是长期短期记忆(LSTM )神经网络工作的地方。 与RNN神经元一样,LSTM神经元可以在管道内保存记忆,以便能够解决顺序和时间问题,而不会产生影响性能的消失梯度问题。

其研究论文和xydtd大多刊登在网络上,从数学上详细讨论了LSTM细胞的结构。 但是,本文不讨论LSTM的复杂工作原理。 因为,我们更关心它们的使用。

关于上下文,LSTM神经元的典型内部工作图如下所示。 它由几个层和一点一点的操作构成,这些操作起到数据输入、输出的闸门的作用,为LSTM单元的状态提供信息。 这种单元状态通过网络和输入来保持长期记忆和上下文。

一个简单的正弦波例子

为了展示LSTM神经网络在预测时间序列中的使用,让我们从最基本的事情开始。 这被认为是可以信赖的正弦波这一时间序列。 为LSTM网络制作训练该函数的许多“振动模型”所需的数据吧。

代码文件夹中的数据包含我们创建的sinewave.csv文件。 该文件包含5001个正弦波时间段,振幅和频率为1 (角频率为6.28 ),时间差为0.01。 的结果如下。

数据集是正弦波

现在我们有数据了。 我们实际上想实现什么? 简单来说,我们只是希望LSTM从提供给LSTM的数据的设定窗口大小中学习正弦波,希望LSTM预测这个系列的第n步,继续输出正弦波。

首先,将CSV文件的数据转换加载到pandas数据帧中,并将其用于输出。 这为LSTM提供了数据的numpy数组。 Keras LSTM层使用三维(n、w、f )的编号数组进行操作。 其中,n是训练序列的数量,w是序列长度,f是每个序列的特征数。 因为选择了使用50个序列长度(读取窗口大小)来允许网络,所以希望能够在各序列中看到正弦波的形状,自己创建基于序列的序列模式。

由于序列本身是滑动窗口,因此每次移动一个时,序列都会与上一个窗口重叠。 绘制时,序列长度为50的典型训练窗口如下所示。

Sinewave数据集培训窗口

为了加载这些数据,我们在代码中创建了数据加载器类,并抽象出了数据加载层。 请注意,初始化DataLoader对象时,会传递文件名,确定用于训练和测试的数据百分比的分割变量,并可以为一个或多个列中的数据选择列变量进行一维或多维分析。

一旦有了可以加载数据的数据对象,就需要构建深度神经网络模型。 同样,对于抽象,我们的代码框架使用模型类和config.json文件,可以通过指定存储在配置文件中的所需架构和超级参数来轻松构建模型实例。 我们构建网络的主要功能是build_model (函数,接收已解析的配置文件。

tps://p3.toutiaoimg.com/origin/pgc-image/153605624194326c2e1ff9a?from=pc">

此功能代码如下所示,可以轻松扩展,以便将来在更复杂的体系架构上使用。

加载数据并建立模型后,我们现在可以继续使用我们的训练数据训练模型。为此,我们创建了一个单独的运行模块,它将利用我们的模型和模块抽象将它们组合起来进行训练、输出和可视化。

下面是训练我们模型的一般运行线程代码:

对于输出,我们将运行两种类型的预测:第一种将以逐点方式进行预测,即我们每次仅预测单个点,将此点绘制为预测,然后沿着下一个窗口进行预测使用完整的测试数据并再次预测下一个点。

我们要做的第二个预测是预测一个完整的序列,我们只用训练数据的第一部分初始化一次训练窗口。然后模型预测下一个点,我们就移动窗口,就像逐点方法一样。不同之处在于我们使用我们在先前预测中预测的数据来进行下一步预测。在第二步中,这意味着只有一个数据点(最后一个点)来自先前的预测。在第三个预测中,最后两个数据点将来自先前的预测,依此类推。经过50次预测后,我们的模型将随后根据自己的先前预测进行预测。这使我们可以使用该模型预测未来的许多时间步骤,但由于它是在预测的基础上进行预测,这反过来可以反过来又可以预测,将增加预测的错误率,我们会预测的更远。

下面我们可以看到逐点预测和完整序列预测的代码和相应的输出。

逐点正弦波预测

正弦波全序列预测

作为参考,可以在下面的配置文件中看到用于正弦波示例的网络架构和超参数。

在真实数据的叠加下我们可以看到,只需1个时期和相当小的训练数据集,LSTM深度神经网络就可以很好地预测正弦函数。

您可以看到,随着我们对未来越来越多的预测,误差幅度会随着先前预测中的误差在用于未来预测时被越来越多地放大并且增加。因此,我们看到在完整序列示例中,预测越远,我们预测预测的频率和幅度与真实数据相比就越不准确。然而,由于sin函数是一个非常简单的零噪声振荡函数,它仍然可以在没有过度拟合的情况下很好地预测它。这很重要,因为我们可以通过增加时期和取出dropout 层来轻松地过度拟合模型。这个训练数据几乎完全准确,与测试数据具有相同的模式,但对于其他现实世界的例子,将模型过度拟合到训练数据上会导致测试精度直线下降,因为模型不会一概而论。

在下一步中,我们将尝试在此类真实数据上使用该模型来查看效果。

不那么简单的股票市场

我们在精确的逐点基础上预测了几百个正弦波的步长。因此,我们现在可以在股市时间序列中做同样的事情并立即获利,对吗?不幸的是,在现实世界中,这并不是那么简单。

与正弦波不同,股票市场时间序列不是可以映射的任何特定静态函数。描述股票市场时间序列运动的最佳属性是随机游走。作为随机过程,真正的随机游走没有可预测的模式,因此尝试对其进行建模将毫无意义。幸运的是,许多方面都在持续争论说股票市场不是一个纯粹的随机过程,这使我们可以理解时间序列可能有某种隐藏模式。正是这些隐藏的模式,LSTM深度网络成为预测的主要候选者。

此示例将使用的数据是数据文件夹中的sp500.csv文件。此文件包含2000年1月至2018年9月的标准普尔500股票指数的开盘价、最高价、最低价、收盘价以及每日交易量。

在第一个例子中,我们将仅使用收盘价创建单维模型。调整config.json文件以反映新数据,我们将保持大部分参数相同。然而,需要做出的一个改变是,与只有-1到+1之间的数值范围的正弦波不同,收盘价是股票市场不断变化的绝对价格。这意味着如果我们试图在不对其进行标准化的情况下训练模型,它就永远不会收敛。

为了解决这个问题,我们将采用每个n大小的训练/测试数据窗口,并对每个窗口进行标准化以反映从该窗口开始的百分比变化(因此点i = 0处的数据将始终为0)。我们将使用以下等式进行归一化,然后在预测过程结束时进行去标准化,以获得现实世界数量的预测:

n =价格变化的标准化列表[窗口]

p =调整后的每日回报价格的原始清单[窗口]

正常化:

反规范化:

我们已将normalise_windows()函数添加到DataLoader类以执行此转换,并且配置文件中包含布尔规范化标志,表示这些窗口的规范化。

随着窗口的标准化,我们现在可以运行模型,就像我们针对正弦波数据运行模型一样。但是,我们在运行这些数据时做了一个重要的改变,而不是使用我们框架的model.train()方法,只是使用我们创建的model.train_generator()方法。我们这样做是因为我们发现在尝试训练大型数据集时很容易耗尽内存,因为model.train()函数将完整数据集加载到内存中,然后将规范化应用于内存中的每个窗口,容易导致内存溢出。因此,我们使用了Keras的fit_generator()函数,允许使用python生成器动态训练数据集来绘制数据,这意味着内存利用率将大大降低。下面的代码详细说明了用于运行三种类型预测的新运行线程(逐点,完整序列和多序列)。

如上所述,在单个逐点预测上运行数据可以非常接近匹配返回的内容。但这有点欺骗性。经过仔细检查,会发现预测线由奇异的预测点组成,这些预测点在它们后面具有整个先前的真实历史窗口。因此,网络不需要了解时间序列本身,除了下一个点很可能不会离最后一点太远。因此,即使它得到错误点的预测,下一个预测也将考虑真实的历史并忽略不正确的预测,然后再次允许产生错误。

虽然这对于下一个价格点的精确预测而言最初听起来并不乐观,但它确实有一些重要的用途。虽然它不知道确切的下一个价格是多少,但它确实能够准确地表示下一个价格的范围。

此信息可用于诸如波动率预测等应用(能够预测市场中高或低波动的时段对特定交易策略非常有利),或远离交易这也可用作良好指标用于异常检测。可以通过预测下一个点,然后将其与真实数据进行比较来实现异常检测,并且如果真实数据值与预测点显著不同,则可以针对该数据点标出异常标记。

标准普尔500指数逐点预测

继续进行完整的序列预测,似乎这被证明是对这种类型的时间序列最不有用的预测(至少使用这些超参数训练这个模型)。我们可以看到预测开始时的轻微碰撞,其中模型遵循某种类型的动量,但是很快我们可以看到模型确定最佳模式是收敛到时间序列的某个均衡。在这个阶段,这可能看起来并没有提供太多价值,但是均值回归交易者可能会在那里宣称,该模型只是找到价格序列在波动率被消除时将恢复的平均值。

标准普尔500指数全序列预测

最后,我们对该模型进行了第三种预测,我将其称为多序列预测。这是完整序列预测的混合,因为它仍然使用测试数据初始化测试窗口,预测下一个点,然后使用下一个点创建一个新窗口。但是,一旦它到达输入窗口完全由过去预测组成的点,它就会停止,向前移动一个完整的窗口长度,用真实的测试数据重置窗口,然后再次启动该过程。实质上,这为测试数据提供了多个趋势线预测,以便能够分析模型获得未来动量趋势的程度。

标准普尔500指数多序列预测

我们可以从多序列预测中看出,网络似乎正确地预测了绝大多数时间序列的趋势(和趋势幅度)。虽然不完美,但它确实表明了LSTM深度神经网络在顺序和时间序列问题中的有用性。通过仔细的超参数调整,肯定可以实现更高的准确性。

结论

虽然本文的目的是在实践中给出LSTM深度神经网络的一个工作实例,但它只是触及了它们在顺序和时间问题中的潜力和应用的表面。

在撰写本文时,LSTM已成功应用于众多现实问题中,从此处所述的经典时间序列问题到文本自动纠正、异常检测和欺诈检测,以及开发自动驾驶汽车技术的核心。

目前使用上述LSTM存在一些局限性,特别是在使用金融时间序列时,该系列本身具有很难建模的非平稳特性(尽管在使用贝叶斯深度神经网络方法方面取得了进展)解决时间序列的非平稳性问题。同样对于一些应用,还发现基于注意力的神经网络机制的新进展已经超过LSTM(并且LSTM与这些基于注意力的机制相结合也优于其自身)。

然而,截至目前,LSTM在更经典的统计时间序列方法上提供了显著的进步,能够非线性地建模关系,并且能够以非线性方式处理具有多个维度的数据。

我们开发的框架的完整源代码可以在以下GitHub页面上的MIT许可证下找到:https: //github.com/jaungiers/LSTM-Neural-Network-for-Time-Series-Prediction

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。