关于算法:Python中TensorFlow的长短期记忆神经网络LSTM指数移动平均法预测股票市场和可视化

3次阅读

共计 8006 个字符,预计需要花费 21 分钟才能阅读完成。

原文链接:http://tecdat.cn/?p=23689 

本文摸索 Python 中的长短期记忆(LSTM)网络,以及如何应用它们来进行股市预测。

在本文中,你将看到如何应用一个被称为长短时记忆的工夫序列模型。LSTM 模型很弱小,特地是在保留长期记忆方面。在本文中,你将解决以下主题。

  • 了解为什么你须要可能预测股票价格的变动。
  • 下载数据 – 应用从雅虎财经收集的股市数据
  • 宰割训练 - 测试数据,并进行数据归一化
  • 利用单步预测技术。
  • 探讨 LSTM 模型。
  • 用以后的数据预测和可视化将来的股票市场

为什么你须要工夫序列模型?

你心愿对股票价格进行正确的建模,所以作为一个股票买家,你能够正当地决定何时买入股票,何时卖出股票以取得利润。这就是工夫序列模型的作用。你须要好的机器学习模型,它能够察看一连串数据的历史,并正确预测该序列的将来数据。

提醒:股票市场的价格是高度不可预测和稳定的。这意味着数据中没有统一的模式,使你可能近乎完满地模仿股票价格随工夫变动。

然而,咱们不要一味地认为这只是一个随机的或者随机的过程,机器学习没有心愿。咱们至多对数据进行建模,做出的预测与数据的理论行为相干。换句话说,你不须要将来确切的股票价值,而是须要股票价格的变动(也就是说,如果它在不久的未来会上涨或上涨)。

# 可用的库
import numpy as np
import tensorflow as tf

下载数据

股票价格有几种不同的变量。它们是

  • 收盘:当天的收盘股票价格
  • 收盘价:当天的开盘股价
  • 高点:数据中最高的股票价格
  • 低点:当天的最低股价

获取数据

你要利用航空公司的股票市场价格来进行预测,所以你把股票代码设置为 “AAL”。此外,你还定义了一个 url\_string,它将返回一个 JSON 文件,其中蕴含航空公司过来 20 年的所有股市数据,以及一个 file\_to_save,它是你保留数据的文件。

接下来,指定条件:如果你还没有保留数据,从你在 url\_string 中设置的 URL 中抓取数据;把日期、低点、高点、成交量、收盘价、开盘价存储到一个 pandas DataFrame df 中,把它保留到 file\_to_save。

    # 从 URL 中抓取数据
    # 将日期、低点、高点、成交量、收盘价、开盘价存储到 Pandas DataFrame 中

            #提取股票市场数据
            df = pd.DataFrame(columns=\['Date', 'Low', 'High', 'Close', 'Open'\])      
        print('数据保留到:%s'%file\_to\_save)        
    # 如果数据曾经存在,只需从 CSV 中加载即可
    否则。print('文件曾经存在,从 CSV 中加载数据')
        df = pd.read\_csv(file\_to_save)

数据摸索

在这里你将把收集的数据输入到 DataFrame 中。你还应该确保数据是按日期排序的,因为数据的程序在工夫序列建模中至关重要。

# 按日期对数据框架进行排序
df = df.sort_values('Date')

# 仔细检查后果
df.head()

数据可视化

当初让咱们来看看是什么样的数据。

plot(range(df.shape\[0\]),(df)/2.0)

这张图曾经阐明了很多问题。我抉择这家公司而不是其余公司的起因是,这张图随着工夫的推移,股票价格有不同体现行为。这将使模型学习更加持重,并且给你一个价格变动来测试对各种状况的预测有多好。

另一个须要留神的是,靠近 2017 年的数值要比靠近 20 世纪 70 年代的数值高得多,而且稳定也大。因而,你须要确保数据在整个工夫范畴内体现为相似的价格范畴,须要将数据标准化。

将数据宰割成训练集和测试集

你将应用通过取一天中最高和最低价格的平均值计算出的两头价格。

当初你能够把训练数据和测试数据离开。训练数据将是工夫序列的前 4000 个数据点,其余的将是测试数据。

train_data = mid\[:4000\]
test_data = mid\[4000:\]

标准化数据

当初你须要定义 标准化 来标准数据。将训练和测试数据变动为 [data\_size, num\_features] 的维度。

将测试数据和训练数据绝对于训练数据归一。scaler = MinMaxScaler()

因为你先前的察看,即不同时间段的数据有不同的值范畴,通过将全序列宰割成窗口来标准化数据。如果你不这样做,晚期的数据将靠近于 0,对学习过程不会有太大的价值。这里你抉择了一个 800 的窗口大小。

提醒:在抉择窗口大小时,不要太小,因为当你进行窗口标准化时,会在每个窗口的最末端引入一个断点,因为每个窗口都是独立标准化的。

# 用训练数据和平滑数据训练
window_size = 800
scaler.transform(train\_data\[di:di+window\_size,:\])

将数据重塑为 [data_size] 的形态。

# 重塑训练和测试数据
reshape(-1)

# 对测试数据进行标准化解决
scaler.transform(test_data).reshape(-1)

当初你能够应用指数挪动平均线对数据进行平滑解决。

请留神,你应该只平滑训练数据。

# 当初进行指数挪动均匀平滑解决
# 所以数据会比原来的锯齿状数据有一个更平滑的曲线

  EMA = gamma\*train\[i\] + (1-gamma)\*EMA
  train\[i\] = EMA

通过平均法进行单步超前预测

 

平均法 容许你通过将将来的股票价格示意为以前察看到的股票价格的平均值来进行预测(通常是提前一个工夫步)。上面看两种均匀技术;规范平均法和指数挪动平均法。你将对这两种算法产生的后果进行定性(目测)和定量(均匀平方误差)的评估。

均匀平方误差(MSE)的计算方法是:取前一步的实在值和预测值之间的平方误差,并对所有的预测值进行均匀。

规范均匀

能够通过首先尝试将其作为一个均匀计算问题的模型来了解这个问题的难度。首先,尝试预测将来的股票市场价格(例如,xt+1),作为一个固定大小的窗口(例如,xt-N,…,xt)(例如之前的 100 天)内先前察看到的股票市场价格的平均值。尔后,尝试更高级的 “ 指数挪动均匀 “ 办法,看看它的成果如何。而后,进入长短期记忆模型

首先,失常的平均数。

换句话说,你说 t + 1 的预测是你在 t 到 t - N 的窗口内察看到的所有股票价格的平均值。

    pred.append(np.mean(train\[idx-window_size:idx\]))
    mse\_errors.append((std\_avg\[-1\]-train\[pred_idx\])**2)
MSE: 0.00418

看一下上面的均匀后果。它与股票的理论行为相当靠近。接下来,你将看到一个更精确的一步预测办法。

plt.plot(std\_avg\_pred)

plt.legend(fontsize=18)
plt.show()

那么,下面的图表(和 MSE)阐明了什么?

仿佛对于十分短的预测(提前一天)来说,这个模型还不算太差。鉴于股票价格不会在一夜之间从 0 变动到 100,这种行为是正当的。接下来,应用指数挪动平均线。

指数挪动平均线

你可能曾经在互联网上看到一些文章,应用非常复杂的模型,并预测了简直精确的股票市场行为。然而请留神! 这些只是视觉上的错觉,并不是因为学到了有用的货色。你将在上面看到如何用一个简略的平均法来复制这种行为。

在指数挪动平均法中,你计算 xt+ 1 为。

其中  和  是在一段时间内放弃的指数挪动均匀数值。.

上述公式基本上是计算 t + 1 工夫步长的指数挪动平均线,并将其作为超前一步的预测。γ 决定最近的预测对 EMA 的奉献是什么。例如,γ=0.1 只能失去以后值的 10% 进入 EMA。因为你只取最近的一小部分,它容许保留你在平均数中很早看到的更早的值。请看上面用于预测向前一步的状况。

for idx in range(1,N):
    mean = mean\*dec + (1.0-de)\*train\[idx-1\]
    pred.append(mean)
MSE: 0.00003
plt.plot(mid_data)
plt.plot(pred)

如果指数式挪动平均数这么好,为什么还须要更好的模型?

拟合后果很好,遵循实在的散布(并且由非常低的 MSE 证实)。实际上,仅凭第二天的股票市场价格是没有意义的。就我集体而言,我想要的不是第二天的确切股市价格,而是将来 30 天的股市价格是上涨还是上涨。尝试这样做,你会发现 EMA 办法的缺点。

当初尝试在窗口中进行预测(比方你预测将来 2 天的窗口,而不是仅仅预测将来一天)。而后你会意识到 EMA 会有多大的误差。上面是一个例子。

预测超过一步的将来股价

咱们假如数值,比方 xt=0.4,EMA=0.5,γ=0.5

  • 假如你失去的输入有以下公式

所以你有 

所以 

所以下一个预测 Xt+ 2 变成了

这就是 

或者在这个例子中, 

所以,无论你对将来进行多少步预测,你都会在所有将来的预测步中一直失去雷同的答案。

你有一个解决方案,能够输入有用的信息,就是看看基于动量的算法。它们依据过来最近的数值是回升还是降落(不是精确的数值)进行预测。例如,它们会说第二天的价格可能会升高,如果过来几天的价格始终在降落,这听起来很正当。然而,咱们应用一个更简单的模型:LSTM 模型。

这些模型曾经在工夫序列预测畛域十分热门,因为它们在工夫序列数据的建模方面十分杰出。你将看到数据中是否真的暗藏有你能够利用的模式。

LSTM 简介:对股票走势进行远期预测

长短期记忆模型是极其弱小的工夫序列模型。它们能够预测将来任意步。LSTM 模块(或单元)有 5 个根本组成部分,使其可能对长期和短期数据进行建模。

  • 单元状态(ct)– 这代表了单元的外部记忆,它同时存储了短期记忆和长期记忆
  • _暗藏状态_(ht)– 这是依据以后输出、以前的_暗藏状态_和以后的单元输出计算出来的输入状态信息,你最终会用它来预测将来的股市价格。此外,暗藏状态能够决定只检索存储在单元状态中的短期或长期或两种类型的记忆来进行下一次预测。
  • 输出门(it)– 决定以后输出的信息有多少流向单元状态
  • 忘记门(ft)– 决定有多少来自以后输出和前一个单元状态的信息流入以后单元状态
  • 输入门(ot)– 决定多少信息从以后单元状态流入暗藏状态,因而,如果须要,LSTM 能够只筛选长期记忆或短期记忆和长期记忆。

TensorFlow 为实现工夫序列模型提供了一个不错的 API(称为 RNN API)。

数据生成器

你首先要实现一个数据生成器来训练你的模型。这个数据生成器将有一个名为.unroll\_batches(…)的办法,它将输入一组顺次取得的 num\_unrollings 批次的输出数据,其中一个批次的数据大小为[batch_size, 1]。那么每一批输出数据都会有一个相应的输入数据批。

例如,如果 num\_unrollings=3,batch\_size=4,一组 unrolled 批次。

  • 输出数据
  • 输入数据: 

数据加强(_Data_ _Augmentation_)

数据加强 (_Data_ _Augmentation_) 又称为数据增广。另外,为了使你的模型持重,你不会让 x\_t 的输入总是 x\_t+1。相同,你将从 x\_t+1,x\_t+2,…,xt+ N 的汇合中随机抽取一个输入,其中 N 是一个小窗口大小。

这里你要做以下假如:

  • x\_t+1,x\_t+2,…,xt+ N 不会彼此相距很远。

我集体认为这对股票走势预测来说是一个正当的假如。

上面你直观地阐明一批数据是如何产生的。

定义超参数

在本节中,你将定义几个超参数。D 是输出的维度。这很简略,因为你把之前的股票价格作为输出,并预测下一个股票价格,这应该是 1。

而后你有 num\_unrollings,这是一个与用于优化 LSTM 模型的通过工夫的反向流传(BPTT)无关的超参数。这示意你在一个优化步骤中思考多少个间断的工夫步骤。能够认为,不是通过查看单个工夫步骤来优化模型,而是通过查看 num\_unrollings 工夫步骤来优化网络。越大越好。

而后,你有 batch_size。批量大小是指在一个工夫步长中思考多少个数据样本。

接下来你定义 num_nodes,它代表每个单元中暗藏神经元的数量。你能够看到,在这个例子中,有三层 LSTMs。

D = 1 # 数据的维度。因为你的数据是一维的,所以是 1
unrollings = 50 # 将来的工夫步数。batch_size = 500 # 一个批次中的样本数
num_nodes = \[200,200,150\] # 咱们所应用的深层 LSTM 堆栈中每一层的暗藏节点数量
n\_layers = len(num\_nodes) # 层的数量
dropout = 0.2 # 抛弃量

定义输出和输入

接下来你要为训练输出和标签定义占位符。你有一个输出占位符的列表,其中每个占位符都蕴含一个批次的数据。而列表中有 num_unrollings 占位符,这些占位符将被一次性用于一个优化步骤。

# 输出数据
train\_inputs, train\_outputs = \[\],\[\]

定义 LSTM 和回归层的参数

你将有三层 LSTM 和一个线性回归层,用 w 和 b 示意,它采取最初一个长短期记忆单元的输入,并输入下一个工夫步骤的预测。此外,你能够让 dropout 实现 LSTM 单元,因为它们能够进步性能,缩小过拟合。

计算 LSTM 输入并将其传递到回归层以取得最终预测后果

在这一节中,你首先创立 TensorFlow 变量(c 和 h),这些变量将放弃长短时记忆单元的状态和暗藏状态。而后,你将训练输出的列表转换为 [unrollings, batch\_size, D] 的形态。而后用 ynamic\_rnn 函数计算 LSTM 输入,并将输入宰割成 num 张量列表。

# 创立单元格状态和暗藏状态变量放弃 LSTM 的状态

for li in range(n):
  c.append(tf.Variable(tf.zeros(\[batch\_size, num\_nodes\[li\]\])))
  h.append(tf.Variable(tf.zeros(\[batch\_size, num\_nodes\[li\]\])))

# 做几次张量转换,因为函数 dynamic_rnn 要求输入必须是一种特定的格局。

损失计算和优化器

当初,要计算损失。对于每一批预测和实在输入,都要计算出均匀平方误差。而你把所有这些均方差损失加在一起(不是均匀)。最初,定义你要应用的优化器来优化神经网络。在这种状况下,你能够应用 Adam,它是一个十分新的、体现良好的优化器。

# 在计算损失时,你须要留神精确的模式,因为你计算的是所有未滚动的步的损失
# 因而,取每个批的平均误差,并失去所有未滚动步的总和

range(n)\]):
  for ui in range(nums):
    loss += tf.mean(0.5*(splits\[ui\]-train\[ui\])**2)

预测相干的计算

在这里,你定义了预测相干的 TensorFlow 操作。首先,定义一个用于输出的占位符(sample\_inputs),而后与训练阶段相似,你定义预测的状态变量(sample\_c 和 sample\_h)。最初,你用 dynamic\_rnn 函数计算预测后果,而后通过回归层(w 和 b)发送输入。你还应该定义 reset\_sample\_state 操作,它能够重置单元状态和暗藏状态。

# 为预测阶段放弃 LSTM 状态
for li in range(n_layers):
  sample\_c.append(tf.Variable(tf.zeros(\[1, num\_nodes\[li\]\]))
  sample\_h.append(tf.Variable(tf.zeros(\[1, num\_nodes\[li\]\])))

运行 LSTM

在这里,你将训练并预测几个历时的股票价格走势,并察看预测后果是否随着工夫的推移而变得更好或更差。

  • 在工夫序列上定义一个测试终点集(test\_points\_seq)来评估模型。
  • 对于每个训练轮数
  • 对于训练数据的残缺序列长度
  • 通过迭代测试点之前的 num_unrollings 数据点来更新 LSTM 状态
     
  • 间断进行 n\_predict\_once 步骤的预测,将之前的预测作为以后输出。
  • 计算预测的 n\_predict\_once 点与这些工夫戳的实在股票价格之间的 MSE 损失
  • 开展一组 num_unrollings 的批次
  • 用未滚动的批次训练神经网络
  • 计算均匀训练损失
  • 对于测试集的每个终点

预测可视化

你能够看到 MSE 损失是如何随着训练量的减少而降落的。这是一个好兆头,表明模型正在学习一些有用的货色。你能够将网络的 MSE 损失与你做规范均匀时失去的 MSE 损失(0.004)进行比拟。你能够看到,LSTM 比规范平均法做得更好。而且你晓得,规范平均法(尽管不完满)正当地遵循了实在的股票价格变动。

best_epoch = 28 # 用失去最佳后果的 epoch


# 绘制预测值随工夫变动的状况
# 绘制低 α 值的旧预测和高 α 值的新预测

        plt.plot(xval,yval)


# 预测你失去的最佳测试预测值
plt.plot(range(df.shap),mid_data)

    plt.plot(xval,yval)

尽管不完满,但 LSTM 仿佛可能在大多数时候正确预测股票价格行为。请留神,你所做的预测大抵在 0 和 1.0 的范畴内(也就是说,不是实在的股票价格)。这没关系,因为你预测的是股票价格的走势,而不是价格自身。

总结

在本教程中,首先介绍了你为什么须要为股票价格建模的动机。接着是解释数据。而后两种均匀技术,它们容许你对将来一步进行预测。接下来你看到,当你须要预测超过一步的将来时,这些办法是无用的。尔后,探讨了如何应用 LSTM 来进行将来多步的预测。最初,将后果可视化,看到模型(尽管不完满)在正确预测股票价格走势方面相当杰出。

在这里,我陈说一下本教程的几个播种。

  1. 股票价格 / 走势预测是一项极其艰难的工作。我集体认为,不应该把任何一个股票预测模型视为天经地义,自觉地依赖它们。然而模型可能在大多数时候可能正确预测股票价格走势,但不总是如此。
  2. 不要被里面那些显示预测曲线与实在股票价格齐全重合的文章所蛊惑。这能够用一个简略的均匀技术来复制,在实践中它是没有用的。更理智的做法是预测股票价格的变动。
  3. 该模型的超参数对你取得的后果十分敏感。因而,要做的一件十分好的事件是对超参数运行一些超参数优化技术(例如,网格搜寻 / 随机搜寻)。上面我列出了一些最要害的超参数
  • 优化器的学习率
  • 层数和每层的暗藏单元的数量
  • 优化器。我发现 Adam 的体现最好
  • 模型的类型。你能够尝试 GRU/ 规范 LSTM 和评估性能差别。

最受欢迎的见解

1.r 语言用神经网络改良 nelson-siegel 模型拟合收益率曲线剖析

2.r 语言实现拟合神经网络预测和后果可视化

3.python 用遗传算法 - 神经网络 - 含糊逻辑控制算法对乐透剖析

4. 用于 nlp 的 python:应用 keras 的多标签文本 lstm 神经网络分类

5. 用 r 语言实现神经网络预测股票实例

6.R 语言基于 Keras 的小数据集深度学习图像分类

7. 用于 NLP 的 seq2seq 模型实例用 Keras 实现神经机器翻译

8.python 中基于网格搜索算法优化的深度学习模型剖析糖

9.matlab 应用贝叶斯优化的深度学习

正文完
 0