预测模型搭建:深度学习模型
在这一章节,我们接着之前的两个章节,继续尝试使用一些深度学习模型,进行股票价格和收益率的预测。在这一章节,我们主要使用TensorFlow和Keras这两个库,搭建一个基本的多层感知器和长短时记忆模型,来进行对数收益率的预测,并且与之前的线性模型和机器学习模型的结果进行对比。
1. 准备工作
我们首先来了解一下深度学习基本的一些概念。按照维基百科上的定义,深度学习(deep learning)是机器学习的分支,是一种以人工神经网络为架构,对数据进行表征学习的算法。深度学习可以认为是机器学习的一个子集,而机器学习是更广义的人工智能的一部分。在2000年之后,数据量的上涨、运算力的提升和深度学习算法的出现极大的促进了人工智能行业的发展。2012年,AlexNet首次在大规模图像数据集上实现了深层卷积神经网络结构,点燃了深度学习这把火,在ImageNet LSVRC-2012目标识别的top-5 error为15.3%,同期第二名仅为26.2%,碾压其他传统的基于手工设计的特征方法。从那以后,以ImageNet为代表的各类图像挑战赛都被深度学习模型霸占着榜首。
深度学习中的基本架构就是人工神经网络,它是试图模拟人类神经元的工作方式,通过数据进行学习。例如我们要用到的多层感知器(Multilayer Perceptron,缩写MLP)就是一种前向结构的人工神经网络,它会将一组输入向量到一组输出向量,我们可以通过调整网络结构来指明输出元素的个数,如下图所示:
在神经网络的每一层,我们都可以看到一个个基本单元,即神经元。在每个神经元中,对于输入的x,会按照权重w进行加权求和,然后应用一个非线性函数后输出,这里的权重w是可以进行学习的参数:
我们把神经元中的非线性函数称作激活函数,这里列出了一些常见的激活函数,不同类型的激活函数会影响模型的最终效果,我们可以通过参数搜索的方式找到最好的激活函数:
神经元中的权重的更新是在训练的过程中,通过反向传播算法实现的,我们首先正向计算输出结果,跟真实结果计算误差,然后根据误差反向更新神经元中的权重参数,如下图所示:
在我们使用神经网络的过程中,并不是每一个神经元都必须用上,我们可以舍弃一些神经元和它们的连接关系,即Dropout:
这样网络结构会变得更加“稀疏”:
这样做的好处是可以更好地发挥剩余的神经元的作用,同时减少过拟合现象的影响。
除了普通的前向全连接网络,我们还会用到循环神经网络(Recurrent Neural Network,RNN),循环神经网络是一类具有短期记忆能力的神经网络。除了普通的输入层、隐藏层和输出层,它还有一个延迟器来实现记录前一个输入的信息的功能:
我们用到的是长短期记忆网络(long short-term memory,LSTM),它是循环神经网络的一个变体,可以有效地解决简单循环神经网络的梯度爆炸或消失问题。LSTM引入了“门机制”来控制信息传递的路径。从概念上,不同的门会控制不同的信息进行遗忘、保存或者输出的操作:
- 遗忘门
控制上一个时刻的内部状态需要遗忘多少信息;
- 输入门
控制当前时刻的候选状态有多少信息需要保存;
- 输出门
控制当前时刻的内部状态有多少信息需要输出给外部状态。
一个基本的LSTM循环单元结构如下图所示:
当我们在使用LSTM网络时,它会根据我们输入的序列,通过参数调节是否要输出一段序列,我们后面的代码中也会看到这个参数:
要实现这些深度学习模型,我们使用的是TensorFlow和Keras这两个库。TensorFlow是一个使用数据流图进行数值计算的开放源代码软件库。图中的节点代表数学计算,而图中的边则代表在这些节点之间传递的张量(Tensor)。TensorFlow最初是由Google Brain团队(隶属于Google机器智能研究部门)中的研究人员和工程师开发的,旨在用于进行机器学习和深度神经网络研究。现在TensorFlow已经成为了最流行的深度学习框架之一。相比其他深度学习框架,TensorFlow有一系列优势。首先是TensorFlow提供了Python接口,同时也支持其他语言的调用。然后TensorFlow具有高度的灵活性,只要你可以将你的计算表示为一个数据流图,你就可以使用Tensorflow。TensorFlow也具有真正的可移植性,可以在CPU和GPU上运行,也可以运行在台式机、服务器、手机移动设备等。基于梯度的机器学习算法受益于Tensorflow自动求微分的能力。最后,由于谷歌公司强大的品牌号召力,TensorFlow具有庞大的社区支持,网上有大量的教程和学习资料。
Keras是一个用Python编写的高级神经网络API,它能够以TensorFlow作为后端运行。Keras的中文网站上也列出了Keras的指导原则,首先是用户友好,Keras提供了一致且简单的API,可以把用户操作数量降至最低,然后是模块化,Keras中的神经网络层、损失函数、优化器、初始化方法、激活函数、正则化方法都被组装成了模块。Keras也具有易扩展性,很容易添加新的模块。最后Keras是基于Python实现的。
安装CPU版本的TensorFlow比较简单,可以通过pip命令进行安装。由于我使用的演示代码仍然是1.13.1的版本,因此我需要在pip命令中指明版本:pip install tensorflow==1.13.1。TensorFlow从2.0版本开始进行了比较大的改动,包括Keras也直接被集成到了TensorFlow中,不过基本的使用方法没有大的改动,对之前的版本的兼容性也不错。要安装支持GPU版本的TensorFlow,需要提前安装GPU的驱动程序等步骤,可以参考这篇文章。
我们可以使用pip安装Keras:pip install keras。我们可以通过修改Keras的配置文件,来指明我们使用的后端为TensorFlow。Keras配置文件一般在:C:\Users\username.keras文件夹中,是一个名为keras.json的文件,我们可以修改其内容为:
{ "epsilon": 1e-07, "floatx": "float32", "image_data_format": "channels_last", "backend": "tensorflow" }
安装完成后,我们导入会使用的库:
import pandas as pd import numpy as np import matplotlib.pyplot as plt import math %config InlineBackend.figure_format = 'svg' import warnings warnings.filterwarnings('ignore') # 忽略一些warnings import sklearn import tensorflow as tf print(tf.__version__) import keras print(keras.__version__)
我在演示中使用的TensorFlow版本为1.13.1,Keras版本为2.2.4。
与上一章节类似,我们载入数据,并把数据分成训练、验证和测试集:
def split_data(): df = pd.read_csv('1.csv', dtype={'trade_date': str}) df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d') df = df.set_index('trade_date', drop=False) # 指明drop=False保留trade_dt这一列 df = df.sort_index() # 按照时间顺序排序 # 计算log return df['close1'] = df['close'].shift(-1) # 1天之后的收盘价 df['log_ret'] = np.log(df['close1'] / df['close']) # 1天之后的log return df = df.dropna() train = df['2010-01-01':'2017-12-31'] # 我们使用2010-2017年的数据作为训练集 cv = df['2018-01-01': '2018-12-31'] # 我们使用2018年的数据作为验证集 train_cv = df['2010-01-01':'2018-12-31'] # 训练集和验证集 test = df['2019-01-01': '2019-12-31'] # 我们使用2019年的数据作为测试集 return df, train, cv, train_cv, test df, train, cv, train_cv, test = split_data() print('Train dataset shape: %s' % str(train.shape)) print('Validation dataset shape: %s' % str(cv.shape)) print('Test dataset shape: %s' % str(test.shape))
输出为:
Train dataset shape: (1874, 13) Validation dataset shape: (243, 13) Test dataset shape: (243, 13)
定义均方根误差的评价指标:
def get_rmse(y_true, y_pred): ''' Compute root mean squared error (RMSE) ''' # 把输入的变量转成numpy的array格式 y_true, y_pred = np.asarray(y_true), np.asarray(y_pred) return np.sqrt(((y_true - y_pred) ** 2).mean())
回顾前两个章节中的对数收益率的预测结果:
oneday_rmse = 0.028567 mov_avg_rmse = 0.020553 arima_rmse = 0.020049 xgboost_rmse = 0.020222 rf_rmse = 0.020000 print('one-day prediction:\t %f' % oneday_rmse) print('mov_avg prediction:\t %f' % mov_avg_rmse) print('arima prediction:\t %f' % arima_rmse) print('xgboost regression prediction:\t %f' % xgboost_rmse) print('random foreset regression prediction:\t %f' % rf_rmse)
输出为:
one-day prediction: 0.028567 mov_avg prediction: 0.020553 arima prediction: 0.020049 xgboost regression prediction: 0.020222 random foreset regression prediction: 0.020000
2. 预测对数收益率
我们基于对数收益率本身的规律进行预测。
train_data = train[['log_ret']] cv_data = cv[['log_ret']] train_cv_data = train_cv[['log_ret']] test_data = test[['log_ret']]
对数据进行z-score归一化:
# 基于训练集的均值和方差对验证集进行归一化 from sklearn.preprocessing import Standar
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
<p> 在这个专刊中,我们会学习Python在金融中的应用: ·掌握Python进行数据分析和处理的方法; ·了解Python在量化投资中的应用; ·转行到金融数据分析和量化交易领域的基础等内容。 这个专刊适合: ·想要学习Python编程的在校学生; ·想要转行到金融领域的在职人士; ·想要利用业余时间进行量化投资的在职人士等。 本专刊购买后即可解锁所有章节,故不可以退换哦~ </p>