Introduction
见最近股市一片利好,本弱鸡作者跟风赚了些之余心血来潮写下这篇文。博文所提到的用机器学习来预测股市,在现实中是不具有实用意义的,因为作者认为股票市场具有很强的因果关系。但另一方面,用机器学习预测股市是CS专业的学生在学校中很大机率会碰到的作业,因为这两者可以帮助如何理解机器学习可以做些什么,同时在学习的时候不至于太枯燥乏味。作者觉得实际操作的过程还蛮有意思,而且会带过很多有关人工智能的一些概念,于是作为记录。
文章提到的一些技法或许在很多专业人士眼里可能根本是菜鸟的水平,但作者尽量做到在操作流程中井然有序。本菜鸡作者日常虽捣鼓一些机器学习的算法,但在预测这个问题上确实没有太多的经验,但是仅作为工具来用倒是没什么问题。
文章会讲述一个完整的实作流程,同时基于自己的理解做一些白话的讲述。作者水平有限,难以做到网上科普博主那样把内容讲得浅显易懂,相关的定义和专业知识我还无法用一两句话来描述,要描述的话至少也得是三四句话。文章极少教科书式的定义说明,需要定义说明直接“百度する”就好了,同时也不会提到任何代码和使用的任何编程工具。写这个实作记录充其量是希望有人看了单纯是觉得有趣。毕竟,作者玩股票玩基金从来都是靠运气而没有本点技术。
再次声明,这个记录不是为了解决问题,况且文章提到的技法是小学生水平的技法,故不要站在专业人士的角度对待。作者的初衷是结合一个很简单很弱鸡的例子,帮助非专业人士搞清楚人工智能的一些常识性概念。作者认为,专业的东西就留在专业的论文里面让专业的人士去看。至于普及性的东西,过分秀专业就是对读者的不友善,作者更希望站在一个非专业人士的角度去思考。
Artificial Intelligence 人工智能
人工智能其实并不是指一类技术或者是某种技术,人工智能更像是一个口号标语,即“利用人工的方式去实现一种智慧”,这样的“智慧”希望可以用来解决生活中实际的问题。例如造出一台自动驾驶汽车。这张图里面人工智能包含机器学习,机器学习包含深度学习。白话地说,机器学习是实现人工智能的一种方式,为应对特定的问题,机器学习提供了一些解决特定问题的方向和技术,而深度学习指的是某一个方向的一些特定的技术。正如造发电站需要用到工程学(好比是Machine Learning),但同时也可以用爱(好比是其他技术手段),工程学里面又细分有控制论(好比是Deep Learning)。
人工智能经常配合“大数据”,“数据驱动”一起出现,那么所谓的“大数据”,“数据驱动”是什么?就是说开发某一种“智慧”的时候,用到一些技术。离开数据的话,这些技术基本上就进行不了了。数据就是血液,燃料,就是使得技术能够使用的基本要素。
Problem Formulation(问题描述)
利用上证底下的45支股票的走势,来预测上证指数的走势。
主要工具与技术:GRU 神经网络,小波变换(Wavelet Transform)
关键字:特征提取,深度学习
结论:股票的走势和发生地震一样是难以预测的。(这里的预测指的是从大量数据里面,找到数据发展的规律,从而达到预测的效果。而并不是指从一些既有的现象或先兆中推断数据发展的结果。例如:如果事先知道了央行会向市场注入资金,那么学Business Analys的人通过分析就可以做到股票走势的判断。而现在的工作就是只有历史的数据,没有任何外部的信息,站在机器的角度,基于数据达到预测的效果,因此这样的方法便称为是基于“大数据”或者是“数据驱动”的方法。)
Implementation
Step1: 资料搜集(Data Collection)
收集资料涉及网络爬虫,这没点写代码的能力真的是凉凉。以前操作过网络爬虫,试过在微博上面爬过一些资料。但因为太久没碰这块,也没有时间重新研究,于是开始了 “百度する” 编程法。
http://quotes.money.163.com/service/chddata.html?code=0601236&start=20200101&end=20200630
这是作者从知乎上面找到的,通过在浏览器直接输入这行直接可以拿到某支股票的 .csv档案,对本弱鸡来说简直方便快捷。
操作说明:code=股票代码,start=开始日前,end=结束日期
选取的股票列表:
600048,600276,601989,601988,601390,600703,601186,600887,600104,600837,601888,600016,600028,601336,600000,601939,601318,601668,600036,601328,601857,600585,600340,601088,600547,600009,600196,601288,600030,601111,601688,600031,600519,600690,601766,603993,600309,601601,601211,601012,601166,601628,600050,601818,601398,000001
资料说明:
2018/01/01 ~ 2020/06/30,共605笔资料(605行)只取“前收盘”这个栏位的资料。
Step2. 资料预处理(Data Pre-Processing)
补充资料中的缺失值:一般的资料预处理指的是看有没有异常的资料,例如说有的栏位可能没有资料,这时候需要补填资料进去。有的资料明显就是错的,这时候也要做处理。可以通过人工一个一个档案去看,也可以通过写代码的方式批量处理这些档案。在这个实作里面,对空缺的栏位一律补上0这个数值。
实作里面用的是资料是“前收盘”,有45个档案,因此就有45笔“前收盘”的记录。下图为某一支股票这个时间段的前收盘价的走势。
对资料进行标准化:标准化其实是一个压缩资料值域的过程。就像是范围在1~100的数,压缩在0~1这个区间。本弱鸡虽然有些直观的解释为什么要标准化,但考虑到这是个极为专业的问题,所以就此打住。
Step3. 特征工程(Feature Engineering)
特征工程是一个比较重要的研究领域,先抛一个说明:1)好的特征工程可以大大减小后面建模的复杂度。下面来白话地讲一下特征工程到底在做些什么。
所谓的机器学习,就是“让机器进行学习”,“机器”在实作里面就是指某一个模型,某一个算法。“让机器学习”,我们可以称为是“训练一个模型”。例如让模型学会分辨猫和狗,学会预测股票的走势。那么用什么进行”训练“?就是从所谓的“大数据”里面,即如上图所示的这些资料里面。分辨猫和狗通常资料是一张图片,而预测股票则是一笔具有时间性的资料。注意分辨猫狗和预测股市会又是截然不同两个问题,一个对应的是分类问题,一个是回归预测问题,这都是现在机器学习在解决的问题。
举例来说,当人去学习如何分辨猫狗的时候,我们先会看到一图片。然后我们可能通过“体型”,“耳朵的形状”,“脸部的轮廓”来判断是猫还是狗。同样的,判断股票走势的时候,你可能需要用到“趋势”,“周期”这些依据。这些判断的依据就是所谓的特征。同样的,模型最终要学会判断,训练的时候就需要告诉模型可以依据哪一些特征。至于机器怎么学?为什么机器能够学?那就涉及原理了,这篇就不会提到原理的部分。
对于收集到的资料,有很多常用的特征提取的方法,而且每个人对资料的处理可能都不一样。在这个实作里面用到了两个trick, Moving Average 和 Wavelet Transform,可以理解成提取特征的工具。没有人会直接使用原始资料来训练模型,用原始资料通常会是 “garbage in garbage out” 。
Trick1:Moving Average 主要是使得那些锯齿的资料稍微变得平滑,可以理解成让资料变得容易看明白。(俗称就是美颜去噪......为什么要平滑化,只能说是经验所得,玄学的一面体现出来了)
Trick2: Wavelet Transform 用来提取“趋势”这个特征。Wavelet Transform 是个很好用的东西(真心觉得~),Wavelet Transform 非常适合用在时序资料(time series data)里面。Wavelet Transform 其实跟傅立叶变换(Fourier Transform)是一个家族的,Wavelet Transform 对资料保有时间上的特性而傅立叶变换则没有(有点涉及专业,略过)。
注:对于特征工程的很多trick,作者也不能给一个具有逻辑性的说明,说不出为什么要这样做,为什么要那样做。(没人知道机器会怎样从资料中学习,正如你也不知道你的大脑实际上是怎么运作的使你学会认字学会说话。)
Step4. 建构机器学习模型(Model Construction)
建模型这个动作其实说难不难,其实就像是在调用一些函数而已。就像是很多人都会用PPT,建模型就相当于是点选PPT的某个功能。机器学习的模型可以说是解决问题的核心。
为什么说核心?想象有两个人,一个文科好,一个理科好。让文科好的去学数学,让理科好的去学文科,这就叫做是选的模型不对头。机器学习里面,有针对分类问题而设计的模型,也有针对预测问题设计的模型。本实作用的是 GRU(Gate Recurrent Unit) 神经网络模型,这款模型适用于解决时序资料的预测问题。
神经网络:神经网络这个东西是个奇妙的东西,这里就不做解释了,就理解成是解决问题的工具就好了。就像是盖房子需要混凝土,混凝土是个奇妙的东西。但可以说下历史,神经网络其实上世纪就有了,但是限于当时硬件跟不上,电脑算力低下,于是难以发展成能够应用的工具,由此其实可以见得AI其实是个古董级的口号。
图中展现的是MLP,是一种比较古老的神经网络模型,蓝色的圈圈就是一个个所谓的神经元。结合先前的例子,我们就是把一堆特征喂给模型,模型会吐出一个结果,我们用正确的结果来进行指导,模型就会自己调整。所谓的调整就是调整图中每一个连接线的权重(略过)。当然神经网络模型还有很多种,文章预测上证的模型是GRU,还有千奇百怪的例如CNN,LSTM,DNN.......
需要注意的是,神经网络只是机器学习的一种常用的技术方法,他的设计很像是脑袋里面用突触连接的神经元,所以因此得名。当然,在解决问题的时候,技术方法有很多,有的方法就不是神经网络的特性,像是随机森林(Random Forest),支持向量机(SVM),这些方法都可以用来解决分类或预测的问题。方法之间各有各的好处和缺点,至于没有神经网络特性的方法也就难以谈得上深度学习,深度学习一般是基于神经网络的模型来讨论的。补充一点的就是往往简单明了的模型在工业界最为常用(暗指逻辑回归,线性回归之流...)。
深度学习:先抛出一个概括性的白话的描述,深度学习就是模型的叠加,大于三层的模型都可以叫做深度,不要脸一点三层以下也是可以。深度学习这个词之所以出现还是归功于硬件设备的发展,先前提到了上世纪已经有神经网络模型了,但受限于运算能力不够,深层的模型就难以发展。现在运算能力指数级飞越,深层的学习就得以实现。因此按照这个逻辑,其实是硬件的发展推动了相关技术的发展。
为什么需要深度学习:也先抛出一个结论性的白话的描述,深层的网络可以学习更多潜在的资料特性。依然举例判断猫和狗,假如我一开始不知道猫有什么“轮廓”诸如此类的这些特征,那么我就是仅仅看图片。好巧不巧我渐渐发现猫的图片都比狗的图片更小张,又发现猫的图片背景往往是草地,而狗的图片背景往往是海滩。“小” 和 “背景” 就是人自己发现的,当然你可以不知道什么是草地,什么是海滩,但是你发现了一种规律。模型也是如此,当模型更为复杂的时候,往往模型自己会摸索到一些奇奇怪怪的特征,这些特征是人类无法理解的,人类也不知道模型是如何摸索出来的。
回到在先前特征工程提到的 “好的特征工程可以大大减小后面建模的复杂度。” 就是说假如知道有哪些特征便于学习,那么就不需要机器自己去发现潜在的特征,那么就是说不需要建构太复杂的模型。
神经网络其实是什么:非专业的其实就把它想成是一个工具就好。至于涉及专业的说法,本菜鸡的理解是神经网络其实是在学习一个高维度的非线性函数,它更像是一个极度复杂的多项式,一个个神经元像极了多项式的每一项。我们知道一个连续的函数可以通过多项式的方式来拟合(联想到泰勒级数...),学习的过程就是不断调整多项式的各个系数(就是 y=ax+b 的那个a )。
Summary:我们用到的是 GRU 神经网络。如下图,这个神经网络里面的每一个神经元是一个个 GRU Cell,因此称为 GRU 神经网络。仅仅需要知道的是这是为了时序资料而专门设计的,对本弱鸡而言就是一个工具,实作的时候叠加了 5 个 hidden layer,越往后每层的神经元个数半数递减。
Step5. 建构输入资料(Input Data)
先前提到训练一个模型靠的是数据,模型的建构在实作中无非是框架的调用。各公司开发的机器学习框架不一样,因此操作起来也不太一样。举例来说 Microsoft 开发了 Office Word,那么Office Word 就是一个框架,而Office Word 里面像是Copy,Paste的功能就是要开发者具体实现的功能。机器学习框架其实现在有很多,像是Google开发的 Tensorflow,Facebook开发的 PyTorch。有了这个框架,建模型就是调用功能的事情,因为开发者都把复杂的部分完成了,最后使用者只需要输入一行简单的代码就可以调用他们实现的背后复杂的功能。
训练方式:训练一个模型需要不断喂模型数据,还是举例分辨猫和狗,人的话就是不断去看一张张猫狗的图片,看了一百张,一千张之后,往往就学会了,模型也是如此。
学习的过程:如何进行学习其实是一个涉及很多数学的问题,作者无意去讨论数学,仅用最白话的方式,结合例子给出比较感性的说明。作为人类,判断猫和狗在不断看图片的时候还不够,因为你如果印象中一直把猫的但成狗,把狗当成猫,那看再多也学不会。就如一加一总认为等于三的话,永远都学不会加减法。给出一种正确的引导,是人类在学习中必不可少的,如你在判断一张图片是猫还是狗之后,需要有一个老师站出来跟你讲真实的答案,以免闭门造车。对于模型本身来说也是一样的,在一笔资料输入进去之后,模型会给出一个他认为的结果,这个时候就需要给出一个正确的答案来引导模型之后的学习。数学实现这个引导过程是通过“损失函数”和“反向传播”来进行的(略过)。因此老师给出的正确答案就是所谓的“标签资料”(Label),模型吃进肚子里的叫做“输入资料”。
简单地理解,还是判断猫和狗。画册上面有一张图片,图片上面有真实的答案,作为人先把答案盖住,先通过观察来判断是猫还是狗,当你说出一个答案的时候,再看看画册上面的真实答案,你就知道自己是对的还是错了。这个过程就是在分类问题和预测问题里面常见的学习过程的逻辑。解决不一样的问题,会有不一样的学习的逻辑。
输入资料:判断猫和狗,输入资料就是一张图片,有一万张图片,模型就要看一万次。预测股市往往就是某一段的走势,例如 6/1~6/4 的“前收盘”,一共四天,结合刚刚提取的两个特征,一只股票其实是 4 x 2 一个 8 个数字。我们又有 45 支股票, 因此就有 8 x 45 个数字。当然输入模型还需要些代码的操作。
标签资料:既然输入 6/1~6/4 的“前收盘”,那么我们就是预测 6/5 的上证前收盘,因此标签资料只有1个数字,假如是预测 6/5~6/6,那么标签资料就有 2 个数字。数学表示都是向量的形式。
分割训练资料和测试资料:训练一个模型往往需要分为训练阶段和测试阶段。就好比学生做练习是训练阶段,考试就是测试阶段,测试阶段是评估一个模型好坏的过程。那么相对应的,我们一支股票有 605 笔资料,一共两年半的资料。训练资料和测试资料的比例我们设置为 8 : 2。用 80% 资料来训练模型,再用20%的资料来测试这个模型的好坏。
Step6. 整合代码开始训练
考验代码能力的时候到了,把刚刚所做的一切整合起来,最后在 terminal 输下一个 python xxx.py。
Experiment Result(实验结果)
为什么不直接用上证的资料,而用上证底下的45支股票:其实也可以直接用单独上证一支股票来做。但作者提出一种想法,当想要了解一个老师的水平的时候,往往不会直接问老师的种种情况。通常是从老师的学生口中得知一些情况,然后加以判断。作者在实作中也是单纯出于这种思想,这在预测股票的时候无关紧要,但是在很多信息安全领域就会有这种考量。
实验结果分析:模型对测试资料的准确率达到 74%,当然这只是预测下一天的情况,如果是预测两天或者是更多的天数,准确率会大打折扣。至于这个模型能不能拿来预测未来七月份和八月份的上证走势,答案是否定的。一方面因为74%是一个非常低的准确度(而且是预测下一步而已,预测下一步其实直接用一些滤波器的方法就出结果了,用神经网络其实有点过犹不及),同时最主要还是因为股票市场具有很强的因果关系,他是一种基于数据的分析和推断,而不是基于数据寻找一种事物发展的规律,可以说解决问题的出发点一开始就是错的。
当然现在的研究也开始往因果推断的反向发展,渐渐也开发了很多具有创意的模型,但本弱鸡设备实在不行,作者拿着六年前的笔记本训练一个模型,还要时时刻刻担心电脑会不会因为过热而爆掉。但至少可以说明的是,很多研究人员都试图用人工智能的方式来预测股市,相信很多投行也有这样的部门,但是具体用什么特殊技术,可能只有做的人自己才知道。
预测股票在网上一搜就一大堆,回归本弱鸡的初衷,本弱鸡还是很注重体验整个实作的过程,毕竟在准确率上面我是花了不少力气从一开始的 13% 改进到 74%。同时在实作的过程里面又回顾了很多人工智能,机器学习,深度学习的很多概念,从理论到实际应用的过程,这对我来说都是极为有意思的事情,当然也希望有人看完也觉得人工智能其实也是挺有意思的东西。因此欢迎留言让本弱鸡完善一些内容上的描述。
最后再次想强调的是,基于大数据配合一些机器学习的方法是不能预测股票的。如果真的有人认为可以,那在专业人士就觉得你太天真了。
[1] C. Zhang, P. Patras and H. Haddadi, "Deep Learning in Mobile and Wireless Networking: A Survey," in IEEE Communications Surveys & Tutorials, vol. 21, no. 3, pp. 2224-2287, thirdquarter 2019, doi: 10.1109/COMST.2019.2904897.
[2] https://towardsdatascience.com/gate-recurrent-units-explained-using-matrices-part-1-3c781469fc18