做者:chen_h
微信号 & QQ:862251340
微信公众号:coderpai
简书地址:http://www.jianshu.com/p/f9ca...git
本文的代码请点击这里。Talk is cheap, show me the code.github
在过去的几个月中,我对深度学习很是着迷,特别是它在天然语言处理中的应用。个人大部分职业生涯都是在金融领域度过的,特别是在算法交易和交易数据替换方面。算法
我写这篇文章的想法直接来自个人工做经验。我做为一名“深度学习”的爱好者时,对于深度学习我没有很深刻的了解。可是我但愿个人理解能够表达到位,而且能够帮助到你。sass
在不少的 NLP 问题中,咱们最终会把序列编码成一个固定大小的表示,而后将这个编码再解码成另外一个序列。例如,咱们可能会在文本中进行实体标记,从英文翻译成法语,或将音频转换成文本。在这些领域都出现了大量的工做,而且不少成果都取得了最早进的表现。微信
在我看来,NLP 与金融数据分析之间的最大不一样在于,语言有必定的结构性,虽然这个结构性比较模糊难懂。另外一方面,金融市场数据多是没有任何结构能够学习的。网络
在这个文章中,咱们假设金融市场数据是存在结构性的,固然这个假设多是不成立的,咱们这个文章可能也会直接推翻这个假设。咱们按照 NLP 的语义编码模型来类比这个市场结构,若是你以为这个想法没有意义,那么请阅读下去,我相信你会以为会有意义的。架构
词向量的模型有不少的,Richard Socher 的讲座是一个很是好的教程。简而言之,咱们能够用语言模型来描述全部的单词,而且在坐标图中进行显示,而且利用几何图形来捕捉单词之间的关联性。有一个经典的例子是 “King - man + woman = Queen” ,或者相似别的例子。函数
词嵌入是很是酷的一个应用,由于咱们能够利用一个很浓缩的方式来表示一个词信息。比较传统的词嵌入方法是构建一个包含全部单词的词表,若是当前词是查询词,那么该位置设置为 1 ,其他设置为 0 。可是这不是一个有效的方法,并且也没有任何词关联意义。可是经过词嵌入,咱们用一个固定维度的向量来表示一个单词,而后利用更高维度的几何特性来寻找词之间的关联性。post
下图展现了一个例子。词向量的模型是须要一个大型的语料库进行训练。通过几天的高密度训练,每一个词都会获得一个高维度的词向量。这个“空间”向量会有相似于“距离”的概念,因此咱们能够计算哪些词是互相接近的。该方法的做者举了一个例子(就是下图),用来计算跟 Frog 距离近的词。学习
可是除了词,咱们对别的事物也能够进行高维度的编码,好比咱们接下来要介绍的金融市场数据。
第一个我据说的词嵌入算法是 word2vec 。我想在金融市场数据上面获得相同的效果,虽然我会使用一些比较不一样于 word2vec 的算法。个人输入数据是 csv 格式的。第一类表示日期,另外的 4*1000 列对应于 1000 只股票的高低开仓价。那么,咱们的输入向量就是 4000 维度的,这个维度太大了。因此,咱们第一件事就是把这个高维度的向量压缩到一个低维度的向量,好比说 300 维度(由于咱们喜欢这个电影 ^_^)。
若是你以为把一个 4000 维度的向量压缩到 300 维度是一件很难的事,那么你就大错特错了。其实这很简单,咱们只须要乘以一个矩阵,矩阵就至关于一个巨大的 excel 表格,每一个单元格中都会有一个数字,而且不存在任何的格式。想象一下,咱们有一个 4000 列和 300 行的 excel 表格,咱们把这个表格与上面的 4000 维度向量进行相乘,那么咱们就能够获得一个 300 维度的向量。这个就是最基础的线性代数知识,你确定能明白。
那么,如今的难点就是如何去设置这个巨大的表格矩阵,“深度学习” 就是用在这个矩阵的初始化和更新上面。最终,这个电子表格矩阵将会是一个不错的转移矩阵,能够将咱们的 4000 维度向量转换成一个简洁的 300 维度向量。
接下来,咱们要作一些比较神奇的事,那就是激活函数。咱们要给每个值加上一个激活函数。将这个激活函数添加到每个值上面,将每一个值的大小归到 0 到 1 之间。那么,为何这样作可使得咱们的向量更加特别,能够学习和理解更加复杂的事。你能够点击这里进行学习。
那么接下来咱们须要处理的重要的事就是如何去找到这个转移矩阵,使得咱们能够损失更少的信息,将高维的股票向量转换成低维的股票向量。咱们但愿能利用这个向量来挖掘各个股票之间的相关性,也许咱们会发现当某个行业下滑时,另外一个行业的股票也会下滑。固然,咱们可能也会发现一些别的特征,我认为这对咱们未来的研究会很是有用。
让咱们先把股票向量放在一边,来谈谈语言模型。Andrej Karpathy 写了一篇很流行的文章 The Unreasonable effectiveness of Recurrent Neural Networks 。对这篇文章能够简单总结以下:
而后这个模型会产生一大堆看起来像莎士比亚风格的文字。而后,咱们也能够将这个思想用在 Linux 源码上面,而后程序来产生代码。或者,咱们能够用在几何代数课本上面,让程序来产生内容。
这个魔术盒的实现机制咱们会在后续进行介绍,可是让咱们先来假想一下,Karpathy 是利用前面的一些字符来预测下一个字符,那么咱们是否能够根据以前的市场向量,来预测下一个市场表现、市场向量或者别的东西,而这个预测模型就是这个魔术盒。咱们尚未决定咱们想要预测的是什么,可是没有关系,由于咱们不会将咱们的输出反馈到咱们的输入中。
因此,Karpathy 向咱们介绍了一些 Linux 例子的输出,下面的代码就是魔术盒的内容:
static void action_new_function(struct s_stat_info *wb) { unsigned long flags; int lel_idx_bit = e->edd, *sys & ~((unsigned long) *FIRST_COMPAT); buf[0] = 0xFFFFFFFF & (bit << 4); min(inc, slist->bytes); printk(KERN_WARNING "Memory allocated %02x/%02x, " "original MLL instead\n"), min(min(multi_run - s->len, max) * num_data_in), frame_pos, sz + first_seg); div_u64_w(val, inb_p); spin_unlock(&disk->queue_lock); mutex_unlock(&s->sock->mutex); mutex_unlock(&func->mutex); return disassemble(info->pending_bh); }
请注意,该魔术盒能够知道如何去打开和关闭括号,而且能遵照程序的缩进约定,也就是函数代码的正确缩进,多行 printk 语句也具备正确的内部缩进。这也就意味着这个魔术盒能够理解代码的远程依赖关系,即魔术盒能够联系到前面的代码进行分析推敲。当它预测在 print 语句中时,它会知道它在一个 print 语句中,而且会记住它是在一个函数中(或者至少记住是在另外一个缩进范围)中。太好了,这就很容易理解,具备捕捉细节和记住长期依赖关系的算法是很是有用的,由于咱们也是但愿能在市场上找到长期的依赖关系。
那么这个神奇的魔术盒里面有什么呢?它是一种被称为 LSTM 的循环神经网络(RNN)。RNN 是一种深度学习算法,它擅长的是对序列进行操做(如字符序列)。在每一步,它对会对下一个字符进行预测,而且使用一个矩阵记性表示,就像咱们以前看到的那样。由于 RNN 有一些内部的记忆,因此它能够记住一些之前看到的东西。它会使用这个内部记忆来决定下一次输入中应该如何操做。使用该内存记忆,RNN 能够记住它在必定范围内的内容,这就是咱们为何能够对输入文本进行预测处理。
RNN 有一个很好的变体称为 LSTM,LSTM 巧妙的设计了 RNN 内部的记忆单元,这个单元能够作如下事:
因此,当一个 LSTM 看到一个 “{” ,而且对本身说“这个很是重要,我应该把它记住” 。而当它这样作时,它基本上就记住了这是一个嵌套的范围。一旦看到相应的 “}” ,它就会决定忘记原来的大括号,所以忘记它在一个嵌套的范围内。
咱们能够将几个 LSTM 堆叠在一块儿,这样 LSTM 能够学习到更多的抽象概念。如今,前一个 LSTM 的输出变成了下一个 LSTM 的输入,每一个 LSTM 会学习到更加抽象的数据。在上面的例子中(这个只是说明性的猜想解释),第一层的 LSTM 可能会学习由空格分割的字符,下一层可能会学习像(static void action_new_function)这样的字符类型,下一层可能会学习函数的概念以及参数等等。虽然 Karpathy 在博客中已经有很是好的说明例子了,可是要清楚的说明每一层的具体任务仍是很是苦难的。
你可能会注意到,Karpathy 使用字符做为他模型的输入,而不是词嵌入(技术上是使用 0-1 编码)。可是,Lars Eidnes 在 Auto-Generating Clickbait With Recurrent Neural Network 文章中使用词嵌入来处理。
上图显示了他使用的网络。咱们先不考虑 softmax 部分(这部分咱们后续介绍),先来看看 LSTM 堆栈和模型的输入部分。咱们发现模型的底部输入是一系列的单词向量(记住,一个词向量表示的是一个单词的语义)。Lars 输入一个字向量序列,其中每个做用以下:
虽然咱们要作一样的事情,可是可能有一点小小的区别,咱们不是把字向量做为输入,而是咱们的 Market2Vec ,这个市场向量就是咱们以前描述出来的。咱们来回顾一下,对于给定的时间点,咱们的 MarketVectors 应该包含在这个时间点发生的市场状况的总和。经过 LSTM 的序列化,咱们但愿可以捕捉到市场上发生的一个长期依赖关系。经过几个 LSTM 的堆栈,咱们但愿能够获得更高层次的市场行为抽象数据。
到目前为止,咱们尚未谈到算法是如何在实际环境中工做的,咱们上面只是谈论了如何对数据作巧妙的转换,把一个高维度的数据转换成低维度的数据。在接下来的文章中,咱们会来具体说如何应用这个算法,可是请记住,正是由于前面的铺垫才使得后面的应用有了价值。
在 Karpathy 的例子中,LSTM 的输出是抽象的表示下一个字符的预测向量。在 Eidnes 的例子中,LSTM 是输出下一个字符向量。这两种状况的下一步都是将一个抽象的事物表示成一个几率向量,这是一个几率列表,说明每一个字符或者单词在下一个位置出现的可能性。这里则是 softmax 函数在工做了,一旦咱们拥有了这个几率列表,咱们则须要选择出最有可能出现的单词或者字符。
当咱们处理“市场预测”的问题时,咱们须要问本身,咱们真正想要预测的是市场的什么状况?我这里有一些本身的想法,你们能够参考一下:
第一和第二个就是回归问题,咱们必须预测的是一个实际的数字而不是一个特定事件的几率(好比字符 n 出现或者市场上涨)。这个很是准确,可是不是我想作的事。
第三和第四是两个很是类似的问题,他们都要求预测一个事件(技术术语,就是一个类标签)。这个事件多是接下来出现字母是 n ,或者接下来10分钟内某只股票是否会上升 5%,而不会降低超过 3%。第三和第四之间的权衡关系是,第三个问题更加常见,所以更容易学习到,而第四个问题更加有价值,它不但对利润有预测,并且对风险也有必定的约束。
第五个问题是咱们在这篇文章须要解决的,这个问题跟第三个和第四个问题很是相似,可是它更加容易一些,由于咱们有一些机制能够遵循。VIX 指数被称为恐怖指数,它表明了 S&P 500 指数的股票波动。它是经过观察指数中每一个股票的隐含波动率得出来的。
那么咱们为何会去预测 VIX 这个指数呢?缘由主要以下:
在将来几分钟内,咱们如何使用以前的数据来预测 VIX 的变化呢?对于咱们数据集中的每个点,我会在 5 分钟后再次看到该数据点的 VIX 变化。若是在那段时间内上升了超过 1%,可是没有超过 0.5%。那么,咱们的模型将输出 1,不然就是输出 0。而后咱们会获得以下一系列的标签:
0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0 ….
咱们想利用以前压缩的市场向量,而后输入到 LSTM 模型中得出最终的几率结果,从技术上来分析,由于咱们最终只要输出一个标签,咱们也可使用 sigmoid 函数,可是若是咱们作二分类结果,仍是建议使用 softmax 函数。
因此,在咱们深刻分析这个算法应用以前,让咱们先来回顾一下咱们已经学习了哪些内容:
如今是最有趣的部分。咱们如今所作的一切均可以被称为是一个前向的过程。当咱们训练算法时,咱们也会去作以上的那些步骤,而后部署到生产环境中使用它。如今咱们须要讨论的是一个反馈的过程,这个反馈是咱们须要在算法中进行学习的过程。
在训练的过程当中,咱们不只准备了数年的历史训练数据,还手动准备了一系列的预测目标,0 和 1 都是咱们对历史数据进行打的标签。
为了学习,咱们须要将市场数据输入咱们的神经网络,而且将网络的输出结果和咱们的标签数据进行对比,最后获得一个损失值,这个对比函数就是一个损失函数。在咱们的例子中这个对比比较简单,咱们能够将咱们的损失函数设计以下:
ERROR = (1/2)*(((precomputed)— (predicted probability))² )
这就是一个损失函数。也就是说,咱们能够去计算出深度学习模型的输出值与准确值之间的偏差有多大。根据这些偏差,咱们能够利用一些更新函数来更新一整个网络的权重,从而获得一个比较好的模型。
该更新过程会一直更新到模型的开始,因此模型会不断的调整咱们的 MarketVectors 向量,以便咱们的 MarketVectors 能够表示更多的信息。
LSTM 模型能够选择去记住哪些内容和忘记哪些内容,以便模型能够分析那些与咱们任务最相关的量。
LSTM 模型还能够学习数据的更加抽象表示,以便模型学习数据更多的特征。
这一点是很是让我吃惊的,由于深度学习能够学习那么多负责和抽象的东西。咱们从前都没有接触过这种模型。
对于这个项目我还有一些更加深刻的想法,一些我可能还会尝试的想法,而且我认为这些想法对实际项目时有用的。
通常来讲,特定市场的流动性越高资金的利用效率越高。我认为这是一个鸡与蛋以前的循环,而市场变得更加的流动,它可以吸取更多的资本交易,而且资本收到的损害最小。随着市场变得更加流动,更多的资本能够在市场中使用,你会发现更多复杂的交易玩家会进入市场。
一个快速的推论是,在一个比较不流动的市场中,竞争并非那么复杂,因此这样的机制可能会带来机会,我会在这样的市场尝试交易。
这些算法的知识和架构对计算机领域是比较陈旧的,可是在股票金融领域的应用是一个全新的应用。咱们假设一些顶级玩家已经在使用这些技术进行套利,而且可能已经很长一段时间了。可是正如我前面提到的,他们多是在一个流动性很大的市场进行套利工做,他们须要很大的市场资金规模,这样才能去平摊他们的运营成本。我认为,下一次的市场应用会在那些流动性比较小的市场,这些市场尚未被开发彻底,存在很大的套利空间。
虽然我在上面提到的是输入一个单通道的数据流,但我认为一个更加有效的训练方法是在多个时间通道上面对市场数据进行训练。也就是说,我目前采用的是 30 秒采样一次,我但愿网络能够解决几个小时的数据依赖关系。
我不知道这个想法是否有意义,可是我认为若是咱们能够将计算成本下降到必定程度,那么咱们能够把多个时间点进行融合训练。这个融合模型的训练我还在思考中,目前有点困难。
当咱们在天然语言处理中,使用的词向量模型都是在一个预训练模型之上进行微调的。可是在咱们的状况下,没有一个预训练好的市场向量可使用,也没有一个明确的算法去进行训练。
我原来的想法是使用一个自动编码器来进行训练,就好像这篇论文,可是端到端的训练好像看起来更加酷。
更重要的考虑是,端到端的序列模型在机器翻译领域已经比较成熟了,也就是说咱们能够把一些文本编码成一个向量,而且进行解码。在这种观点下,我所描述的整个架构本质上就是一个编码器,可是我尚未真正的设计出一个解码器。
可是,对于网络的第一层,我想设计一个特殊层,即咱们须要把输入的 4000 维度向量降维到一个 300 维度的向量。经过这些低维度的向量,咱们须要去找到各个股票之间的一些关联度。
另外一个替代的方向是对每一个 LSTM 输入一个数据,而后编码成一个输出向量。但我认为这个多是无效的,由于各个数据模型之间的相关度会降低不少,而且这种方法会须要 10 倍的计算资源,比较浪费。可是从另外一方面来讲,这种架构能够多个 GPU 进行训练,能够提升一点速度。
最近,字符级的机器翻译方面出现了不少的论文。这篇论文带给了我不少的启发,由于这篇文章试图采用 CNN 来解决长距离的依赖关系,而不是 RNN 。我尚未深刻的去阅读这篇论文,可是咱们能够假想一下,咱们把每一个股票当作一个通道(相似于 RGB图像的三个通道),而后把每一个通道输入卷积模型中进行卷积操做,从而来捕捉市场的长期依赖信息。这种方法跟他们从字符级别上进行语义编码的方式是相同的。
算法社区直播课:请点击这里
做者:chen_h
微信号 & QQ:862251340
简书地址:http://www.jianshu.com/p/f9ca...
CoderPai 是一个专一于算法实战的平台,从基础的算法到人工智能算法都有设计。若是你对算法实战感兴趣,请快快关注咱们吧。加入AI实战微信群,AI实战QQ群,ACM算法微信群,ACM算法QQ群。长按或者扫描以下二维码,关注 “CoderPai” 微信号(coderpai)