自创数据集,用TensorFlow预测股票教程 !(附代码)

STATWORX 团队近日从 Google Finance API 中精选出了 S&P 500 数据,该数据集包含 S&P 500 的指数和股价信息。有了这些数据,他们就希望能利用深度学习模型和 500 支成分股价预测 S&P 500 指数。STATWORX 团队的数据集十分新颖,但只是利用四个隐藏层的全连接网络实现预测,读者也可以下载该数据尝试更加优秀的循环神经网络

本文非常适合初学者了解如何使用 TensorFlow 构建基本的神经网络,它全面展示了构建一个 TensorFlow 模型所涉及的概念与模块。本文所使用的数据集可以直接下载,所以有一定基础的读者也可以尝试使用更强的循环神经网络处理这一类时序数据。

数据集地址:http://files.statworx.com/sp500.zip

导入和预处理数据

STATWORX 团队从服务器爬取股票数据,并将它们保存为 csv 格式的文件。该数据集包含 n=41266 分钟的记录,范围从 2017 年的 4 月到 8 月的 500 支股票和 S&P 500 指数,股票和股指的范围分布十分广。

# Import data
data = pd.read_csv('data_stocks.csv')
# Dimensions of dataset
n = data.shape[0]
p = data.shape[1]

该数据集已经经过了清理与预处理,即损失的股票和股指都通过 LOCF'ed 处理(下一个观测数据复制前面的),所以该数据集没有任何缺损值。

我们可以使用 pyplot.plot('SP500') 语句绘出 S&P 时序数据。

S&P 500 股指时序绘图


预备训练和测试数据


该数据集需要被分割为训练和测试数据,训练数据包含总数据集 80% 的记录。该数据集并不需要扰乱而只需要序列地进行切片。训练数据可以从 2017 年 4 月选取到 2017 年 7 月底,而测试数据再选取剩下到 2017 年 8 月的数据。

# Training and test data
train_start = 0
train_end = int(np.floor(0.8*n))
test_start = train_end + 1
test_end = n
data_train = data[np.arange(train_start, train_end), :]
data_test = data[np.arange(test_start, test_end), :

时序交叉验证有很多不同的方式,例如有或没有再拟合(refitting)而执行滚动式预测、或者如时序 bootstrap 重采样等更加详细的策略等。后者涉及时间序列周期性分解的重复样本,以便模拟与原时间序列相同周期性模式的样本,但这并不不是简单的复制他们的值。


数据标准化

大多数神经网络架构都需要标准化数据,因为 tanh 和 sigmoid 等大多数神经元的激活函数都定义在 [-1, 1] 或 [0, 1] 区间内。目前线性修正单元 ReLU 激活函数是最常用的,但它的值域有下界无上界。不过无论如何我们都应该重新缩放输入和目标值的范围,这对于我们使用梯度下降算法也很有帮助。缩放取值可以使用 sklearn 的 MinMaxScaler 轻松地实现。

# Scale data
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(data_train)
scaler.transform(data_train)
scaler.transform(data_test)
# Build X and y
X_train = data_train[:, 1:]
y_train = data_train[:, 0]
X_test = data_test[:, 1:]
y_test = data_test[:, 0]pycharm

注意,我们必须谨慎地确定什么时候该缩放哪一部分数据。比较常见的错误就是在拆分测试和训练数据集之前缩放整个数据集。因为我们在执行缩放时会涉及到计算统计数据,例如一个变量的最大和最小值。但在现实世界中我们并没有来自未来的观测信息,所以必须对训练数据按比例进行统计计算,并将统计结果应用于测试数据中。不然的话我们就使用了未来的时序预测信息,这常常令预测度量偏向于正向。

TensorFlow 简介

TensorFlow 是一个十分优秀的框架,目前是深度学习和神经网络方面用户最多的框架。它基于 C++的底层后端,但通常通过 Python 进行控制。TensorFlow 利用强大的静态图表征我们需要设计的算法与运算。这种方法允许用户指定运算为图中的结点,并以张量的形式传输数据而实现高效的算法设计。由于神经网络实际上是数据和数学运算的计算图,所以 TensorFlow 能很好地支持神经网络和深度学习。

总的来说,TensorFlow 是一种采用数据流图(data flow graphs),用于数值计算的开源软件库。其中 Tensor 代表传递的数据为张量(多维数组),Flow 代表使用计算图进行运算。数据流图用「结点」(nodes)和「边」(edges)组成的有向图来描述数学运算。「结点」一般用来表示施加的数学操作,但也可以表示数据输入的起点和输出的终点,或者是读取/写入持久变量(persistent variable)的终点。边表示结点之间的输入/输出关系。这些数据边可以传送维度可动态调整的多维数据数组,即张量(tensor)。

执行加法的简单计算图

在上图中,两个零维张量(标量)将执行相加任务,这两个张量储存在两个变量 a 和 b 中。这两个值流过图形在到达正方形结点时被执行相加任务,相加的结果被储存在变量 c 中。实际上,a、b 和 c 可以被看作占位符,任何输入到 a 和 b 的值都将会相加到 c。这正是 TensorFlow 的基本原理,用户可以通过占位符和变量定义模型的抽象表示,然后再用实际的数据填充占位符以产生实际的运算,下面的代码实现了上图简单的计算图:

# Import TensorFlow
import tensorflow as tf
# Define a and b as placeholders
a = tf.placeholder(dtype=tf.int8)
b = tf.placeholder(dtype=tf.int8)
# Define the addition
c = tf.add(a, b)
# Initialize the graph
graph = tf.Session()
# Run the graph
graph.run(c, feed_dict{a: 5, b: 4})

如上在导入 TensorFlow 库后,使用 tf.placeholder() 定义两个占位符来预储存张量 a 和 b。随后定义运算后就能执行运算图得出结果。


占位符


正如前面所提到的,神经网络的初始源自占位符。所以现在我们先要定义两个占位符以拟合模型,X 包含神经网络的输入(所有 S&P 500 在时间 T=t 的股票价格),Y 包含神经网络的输出(S&P 500 在时间 T=t+1 的指数值)。

因此输入数据占位符的维度可定义为 [None, n_stocks],输出占位符的维度为 [None],它们分别代表二维张量和一维张量。理解输入和输出张量的维度对于构建整个神经网络十分重要。

# Placeholder
X = tf.placeholder(dtype=tf.float32, shape=[None, n_stocks])
Y = tf.placeholder(dtype=tf.float32, shape=[None])

以上代码中的 None 指代我们暂时不知道每个批量传递到神经网络的数量,所以使用 None 可以保持灵活性。我们后面会定义控制每次训练时使用的批量大小 batch_size。


变量


除了占位符,变量是 TensorFlow 表征数据和运算的另一个重要元素。虽然占位符在计算图内通常用于储存输入和输出数据,但变量在计算图内部是非常灵活的容器,它可以在执行中进行修改与传递。神经网络的权重和偏置项一般都使用变量定义,以便在训练中可以方便地进行调整,变量需要进行初始化,后文将详细解释这一点。

该模型由四个隐藏层组成,第一层包含 1024 个神经元,然后后面三层依次以 2 的倍数减少,即 512、256 和 128 个神经元。后面的层级的神经元依次减少就压缩了前面层级中抽取的特征。当然,我们还能使用其它神经网络架构和神经元配置以更好地处理数据,例如卷积神经网络架构适合处理图像数据、循环神经网络适合处理时序数据,但本文只是为入门者简要地介绍如何使用全连接网络处理时序数据,所以那些复杂的架构本文并不会讨论。

# Model architecture parameters
n_stocks = 500
n_neurons_1 = 1024
n_neurons_2 = 512
n_neurons_3 = 256
n_neurons_4 = 128
n_target = 1
# Layer 1: Variables for hidden weights and biases
W_hidden_1 = tf.Variable(weight_initializer([n_stocks, n_neurons_1]))
bias_hidden_1 = tf.Variable(bias_initializer([n_neurons_1]))
# Layer 2: Variables for hidden weights and biases
W_hidden_2 = tf.Variable(weight_initializer([n_neurons_1, n_neurons_2]))
bias_hidden_2 = tf.Variable(bias_initializer([n_neurons_2]))
# Layer 3: Variables for hidden weights and biases
W_hidden_3 = tf.Variable(weight_initializer([n_neurons_2, n_neurons_3]))
bias_hidden_3 = tf.Variable(bias_initializer([n_neurons_3]))
# Layer 4: Variables for hidden weights and biases
W_hidden_4 = tf.Variable(weight_initializer([n_neurons_3, n_neurons_4]))
bias_hidden_4 = tf.Variable(bias_initializer([n_neurons_4]))
# Output layer: Variables for output weights and biases
W_out = tf.Variable(weight_initializer([n_neurons_4, n_target]))
bias_out = tf.Variable(bias_initializer([n_target]))

理解输入层、隐藏层和输出层之间变量的维度变换对于理解整个网络是十分重要的。作为多层感知机的一个经验性法则,后面层级的第一个维度对应于前面层级权重变量的第二个维度。这可能听起来比较复杂,但实际上只是将每一层的输出作为输入传递给下一层。偏置项的维度等于当前层级权重的第二个维度,也等于该层中的神经元数量。

设计神经网络的架构

在定义完神经网络所需要的权重矩阵与偏置项向量后,我们需要指定神经网络的拓扑结构或网络架构。因此占位符(数据)和变量(权重和偏置项)需要组合成一个连续的矩阵乘法系统。

此外,网络隐藏层中的每一个神经元还需要有激活函数进行非线性转换。激活函数是网络体系结构非常重要的组成部分,因为它们将非线性引入了系统。目前有非常多的激活函数,其中最常见的就是线性修正单元 ReLU 激活函数,本模型也将使用该激活函数。

# Hidden layer
hidden_1 = tf.nn.relu(tf.add(tf.matmul(X, W_hidden_1), bias_hidden_1))
hidden_2 = tf.nn.relu(tf.add(tf.matmul(hidden_1, W_hidden_2), bias_hidden_2))
hidden_3 = tf.nn.relu(tf.add(tf.matmul(hidden_2, W_hidden_3), bias_hidden_3))
hidden_4 = tf.nn.relu(tf.add(tf.matmul(hidden_3, W_hidden_4), bias_hidden_4))
# Output layer (must be transposed)
out = tf.transpose(tf.add(tf.matmul(hidden_4, W_out), bias_out))

下图将展示本文构建的神经网络架构,该模型主要由三个构建块组成,即输入层、隐藏层和输出层。这种架构被称为前馈网络或全连接网络,前馈表示输入的批量数据只会从左向右流动,其它如循环神经网络等架构也允许数据向后流动。

前馈网络的核心架构


损失函数


该网络的损失函数主要是用于生成网络预测与实际观察到的训练目标之间的偏差值。对回归问题而言,均方误差(MSE)函数最为常用。MSE 计算预测值与目标值之间的平均平方误差。

# Cost function
mse = tf.reduce_mean(tf.squared_difference(out, Y))

然而,MSE 的特性在常见的优化问题上很有优势。


优化器


优化器处理的是训练过程中用于适应网络权重和偏差变量的必要计算。这些计算调用梯度计算结果,指示训练过程中,权重和偏差需要改变的方向,从而最小化网络的代价函数。稳定、快速的优化器的开发,一直是神经网络和深度学习领域的重要研究。

# Optimizer
opt = tf.train.AdamOptimizer().minimize(mse)

以上是用到了 Adam 优化器,是目前深度学习中的默认优化器。Adam 表示适应性矩估计,可被当作 AdaGrad 和 RMSProp 这两个优化器的结合。


初始化器


初始化器被用于在训练之前初始化网络的变量。因为神经网络是使用数值优化技术训练的,优化问题的起点是找到好的解决方案的重点。TensorFlow 中有不同的初始化器,每个都有不同的初始化方法。在这篇文章中,我使用的是 tf.variance_scaling_initializer(),是一种默认的初始化策略。

# Initializers
sigma =
weight_initializer = tf.variance_scaling_initializer(mode="fan_avg", distribution="uniform", scale=sigma)
bias_initializer = tf.zeros_initializer()

注意,用 TensorFlow 的计算图可以对不同的变量定义多个初始化函数。然而,在大多数情况下,一个统一的初始化函数就够了。

拟合神经网络

完成对网络的占位符、变量、初始化器、代价函数和优化器的定义之后,就可以开始训练模型了,通常会使用小批量训练方法。在小批量训练过程中,会从训练数据随机提取数量为 n=batch_size 的数据样本馈送到网络中。训练数据集将分成 n/batch_size 个批量按顺序馈送到网络中。此时占位符 X 和 Y 开始起作用,它们保存输入数据和目标数据,并在网络中分别表示成输入和目标。

X 的一个批量数据会在网络中向前流动直到到达输出层。在输出层,TensorFlow 将会比较当前批量的模型预测和实际观察目标 Y。然后,TensorFlow 会进行优化,使用选择的学习方案更新网络的参数。更新完权重和偏差之后,下一个批量被采样并重复以上过程。这个过程将一直进行,直到所有的批量都被馈送到网络中去,即完成了一个 epoch。

当训练达到了 epoch 的最大值或其它的用户自定义的停止标准的时候,网络的训练就会停止。

# Run initializer
net.run(tf.global_variables_initializer())
# Setup interactive plot
plt.ion()
fig = plt.figure()
ax1 = fig.add_subplot(111)
line1, = ax1.plot(y_test)
line2, = ax1.plot(y_test*0.5)
plt.show()
# Number of epochs and batch size
epochs = 10
batch_size = 256for e in range(epochs):
# Shuffle training data
 shuffle_indices = np.random.permutation(np.arange(len(y_train)))
 X_train = X_train[shuffle_indices]
 y_train = y_train[shuffle_indices]
# Minibatch training
for i in range(0, len(y_train) // batch_size):
 start = i * batch_size
 batch_x = X_train[start:start + batch_size]
 batch_y = y_train[start:start + batch_size]
# Run optimizer with batch
 net.run(opt, feed_dict={X: batch_x, Y: batch_y})
# Show progress
if np.mod(i, 5) == 0:
# Prediction
 pred = net.run(out, feed_dict={X: X_test})
 line2.set_ydata(pred)
 plt.title('Epoch ' + str(e) + ', Batch ' + str(i))
 file_name = 'img/epoch_' + str(e) + '_batch_' + str(i) + '.jpg'
 plt.savefig(file_name)
 plt.pause(0.01)

在训练过程中,我们在测试集(没有被网络学习过的数据)上评估了网络的预测能力,每训练 5 个 batch 进行一次,并展示结果。此外,这些图像将被导出到磁盘并组合成一个训练过程的视频动画。模型能迅速学习到测试数据中的时间序列的位置和形状,并在经过几个 epoch 的训练之后生成准确的预测。太棒了!

可以看到,网络迅速地适应了时间序列的基本形状,并能继续学习数据的更精细的模式。这归功于 Adam 学习方案,它能在模型训练过程中降低学习率,以避免错过最小值。经过 10 个 epoch 之后,我们完美地拟合了测试数据!最后的测试 MSE 等于 0.00078,这非常低,因为目标被缩放过。测试集的预测的平均百分误差率等于 5.31%,这是很不错的结果。

预测和实际 S&P 价格的散点图(已缩放)

请注意其实还有很多种方法能进一步优化这个结果:层和神经元的设计、不同的初始化和激活方案的选择、引入神经元的 dropout 层、早期停止法的应用,等等。此外,其它不同类型的深度学习模型,比如循环神经网络也许能在这个任务中达到更好的结果。不过,这在我们的讨论范围之外。

结论和展望

TensorFlow 的发布是深度学习研究的里程碑事件,其高度的灵活性和强大的性能使研究者能开发所有种类的复杂神经网络架构以及其它机器学习算法。然而,相比使用高级 API 如 Keras 或 MxNet,灵活性的代价是更长的建模时间。尽管如此,我相信 TensorFlow 将继续发展,并成为神经网路和和深度学习开发的研究和实际应用的现实标准。我们很多客户都已经在使用 TensorFlow,或正在开发应用 TensorFlow 模型的项目。我们的 STATWORX 的数据科学顾问(https://www.statworx.com/de/data-science/)基本都是用 TensorFlow 研究课开发深度学习以及神经网络。

谷歌未来针对 TensorFlow 的计划会是什么呢?至少在我看来,TensorFlow 缺少一个简洁的图形用户界面,用于在 TensorFlow 后端设计和开发神经网络架构。也许这就是谷歌未来的一个目标:)

原文发布时间为:2017-11-15

本文来自合作伙伴“数据派THU”,了解相关信息可以关注“数据派THU”微信公众号

时间: 2024-10-29 06:47:01

自创数据集,用TensorFlow预测股票教程 !(附代码)的相关文章

教你用TensorFlow实现神经网络(附代码)

如果你一直关注数据科学/机器学习,你就不能错过深度学习和神经网络的热潮.互联网公司正在寻找这方面的人,而且从竞赛到开源项目,都有巨额奖金.  如果你对深度学习所提供的前景感到兴奋,但是还没有开始,在这里或许是你开始的第一步.  在这篇文章中,我将介绍TensorFlow.阅读本文后,你将能够理解神经网络的应用,并使用TensorFlow解决现实生活中的问题,本文中的代码是用Python编写的,Python最近的火爆也和深度学习有关. 何时使用神经网络? 有关神经网络和深度学习的更详细的解释, 请

手把手教你由TensorFlow上手PyTorch(附代码)

当我第一次尝试学习 PyTorch 时,没几天就放弃了.和 TensorFlow 相比,我很难弄清 PyTorch 的核心要领.但是随后不久,PyTorch 发布了一个新版本,我决定重新来过.在第二次的学习中,我开始了解这个框架的易用性.在本文中,我会简要解释 PyTorch 的核心概念,为你转入这个框架提供一些必要的动力.其中包含了一些基础概念,以及先进的功能如学习速率调整.自定义层等等.   PyTorch 的易用性如何?Andrej Karpathy 是这样评价的 资源 首先要知道的是:P

如何优雅地用TensorFlow预测时间序列:TFTS库详细教程

前言 如何用TensorFlow结合LSTM来做时间序列预测其实是一个很老的话题,然而却一直没有得到比较好的解决.如果在Github上搜索"tensorflow time series",会发现star数最高的tgjeon/TensorFlow-Tutorials-for-Time-Series已经和TF 1.0版本不兼容了,并且其他的项目使用的方法也各有不同,比较混乱. 在刚刚发布的TensorFlow 1.3版本中,引入了一个TensorFlow Time Series模块(源码地

Tensorflow实例:利用LSTM预测股票每日最高价(一)

RNN与LSTM 这一部分主要涉及循环神经网络的理论,讲的可能会比较简略. 什么是RNN RNN全称循环神经网络(Recurrent Neural Networks),是用来处理序列数据的.在传统的神经网络模型中,从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的.但是这种普通的神经网络对于很多关于时间序列的问题却无能无力.例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的.RNN之所以称为循环神经网路,即一个序列当前的输出与

《BI那点儿事》Microsoft 逻辑回归算法——预测股票的涨跌

原文:<BI那点儿事>Microsoft 逻辑回归算法--预测股票的涨跌 数据准备:一组股票历史成交数据(股票代码:601106 中国一重),起止日期:2011-01-04至今,其中变量有"开盘"."最高"."最低"."收盘"."总手"."金额"."涨跌"等 UPDATE FactStock SET [涨跌] = N'涨' WHERE [涨幅] >

独家 | 10分钟带你上手TensorFlow实践(附代码)

这篇TensorFlow教程的目标读者是那些对机器学习有一定基本概念并且想尝试上手TensorFlow的人.首先你需要安装好TensorFlow(可以跟着本教程进行安装http://cv-tricks.com/artificial-intelligence/deep-learning/deep-learning-frameworks/tensorflow/install-tensorflow-1-0-gpu-ubuntu-14-04-aws-p2-xlarge/). 本教程共分为两部分: 第一部

tensorflow笔记:多层LSTM代码分析

标签(空格分隔): tensorflow笔记 tensorflow笔记系列:  (一) tensorflow笔记:流程,概念和简单代码注释  (二) tensorflow笔记:多层CNN代码分析  (三) tensorflow笔记:多层LSTM代码分析  (四) tensorflow笔记:常用函数说明  (五) tensorflow笔记:模型的保存与训练过程可视化  (六)tensorflow笔记:使用tf来实现word2vec 之前讲过了tensorflow中CNN的示例代码,现在我们来看RN

AJAX教程实例,ASP+AJAX+ACCESS数据库应用教程(附源码)

access|asp+|数据|数据库|ajax教程 AJAX教程实例[阿里西西原创]  其实说起AJAX的初级应用是非常简单的,通俗的说就是客户端(javascript)与服务端(asp或php等)脚本语言的数据交互. 看完本篇ajax实例教程,我相信你也可以轻松做出一个初级的AJAX应用. 你也可以直接访问:http://www.alixixi.com/web/web/ajax/jiaocheng.html预览此篇ajax教程的源码示例. 好,下面我们就始一步步让你了解AJAX+ASP基础应用

BOSS制作教程+详细代码解释+源代码

教程|源代码 见截图先: OSS制作教程+详细代码解释+源代码-速卖通详细描述源代码"> 点击这里下载原文件 大家好,,,,第一次写这个东东~~心理好紧张挖```` 大家了很多的FLASH飞机游戏,,,但是真正象"灵动碰射"那样完整的少之又少,大部分都是没有BOSS的,,,只是在一个画面内循环出现敌机,趣味自然降低了不少... 近来FLASH8游戏版块新教程太少,我也写个教程,,算是对FLASH8游戏版块的一个回报:-) 在这里我只谈做BOSS的制作思想,其他的主角啊,