长短期记忆模型
Recurrent Neural Networks & Long-Short Term Memory Model递回神经网络(Recurrent Neural Networks)神经网络的预测路径是单向的,也就是从输入资料,透过隐藏层计算之后传送成输出资料,然而,对于有些资料来说这会产生一个问题,这些资料的出现实际上有高度的时间性,也就是这期的值很大一部分受到上期的影响。我们天津市环湖医院数据中心因此对神经网络做出一些修正:
Source:https://towardsdatascience.com/recurrent-neural-networks-and-lstm-4b601dd822a5我们利用上一次的预测结果作为一组新的特征输入到神经网络之中,这就构成了递回神经网络(RNN模型),这样做的好处不仅在于提供时间资料或前后相关资料更好的预测结果,同时它可以支援多种输出如下:
透过回传前次的输出结果,我们可以组合出非常多种输出方式,这样的架构在语言处理上非常好用,前不久流行的TF-IDF算法,即是把文本中的辞汇拆解成向量,并根据辞汇在文本中出现的频率作相对运算来做分类的一种方法,这时候输入的资料维度就会变得非常大(想像一下一份文本中可能用到的单字数量)。好在文字的出现通常都有一定的规则,当你说了“我今天想吃...” ,后面不太可能出现泥土、水泥这类的单字,这时候就仰赖RNN模型来更精准地得到预测结果。
图片来源:https://brohrer.mcknote.com/zh-Hant/how_machine_learning_works/how_rnns_lstm_work.html但这样做会遭遇到一个瓶颈,也就是梯度消失问题,我们知道神经网络的基础是建构在透过梯度下降去搜索权重,但如果今天在很初期的时候我们的梯度就接近平坦,则没有办法最佳化损失函数(更正确地说,即使最佳化了,效果也不甚理想)长短期记忆模型(Long-Short Term Memory)天津市环湖医院,上世纪末,也就是二十年前, S. Hochreiter and J. Schmidhuber. 提出了长短期记忆模型来有效解决这个问题,把从输出端反馈进来的特征(也就是记忆)新增了一个闸门以控制它的流入流出,换言之,我们可以选择性地遗忘某些记忆,让它们不要干扰现有的模型拟合,从而更有用地找到权重更新。想像一个原始的RNN模型要回答时间相关的问题,举例来说“我今天想吃…”,这句话可以根据吃这个单字去猜测出后期的意思,但有时,这个时间轴会被拉得很长。举例来说“前两天才吃了一堆汉堡,所以我今天想吃…” 这个句子,如果模型能够精确抓到汉堡这个词语,就能更精确地去猜测今天想吃的东西可能也不会是类似的油炸食品。但要这么做的话,RNN就需要被加入一些机制,也就是我们要谈的LSTM模型。模型的建立分成两个步骤:遗忘与储存,透过Activation Function来实现这件事。假设我们今天有一个Sigmoid函数,把输出值压在0到1之间,其中0代表不允许通过,1代表完全可通过,0~1之间则代表部分通过。此时我们就创造了一个简单的遗忘与储存闸门,图示如下:
Source:https://www.zybuluo.com/hanbingtao/note/581764原始的RNN只有当期输出的x(t)以及上期输出的h(t-1)来运行神经网络,但我们在这之上加入了一个长期记忆的Cell,举例来说这个Cell代表了,在出现新的主词之前,我都记住这个主词的资讯,每次预测的结果都会跟这个主词有关直到新的主词出现。因此这个有用的资讯就被保存了下来,接着就可以进入到神经网络,并且运用我们说的黑箱作业(就是程式自己调整权重但根本没人知道发生了什么事,所以我们通常会说程序人员必须事后检验模型,来取得这台机器思考的方法),来执行预测分析。*要注意的是,这整个LSTM会有两种地方出现Activation Function,除了大神经网络的输出端以外,还有各个闸门自己的输出端。训练LSTM模型LSTM模型可以用在时间资料的预测上,我们先来实际操作看看,首先因为模型对于Scale问题比较敏感,一般的数据上我们先对其做标准化,而这边我们则使用diff方法差分后转换成Scaled Data,这样可以将资料压在活化函数的输出范围(上一篇没有提到,详细的理由可以参考最下方的延伸阅读):
接下来我们要导入LSTM模型,但是在这之前,我们必须先介绍几个比较特别的参数:Sample:也就是我们上一篇提到过的Batch SizeTimeStep:这边也就是RNN的重点,我们要回头取多少的过去预测结果当作新的感知器输入值,这边我们就先假定为1Features:有点像是input shape,以我们的资料而言就是1因此,我们的模型summary会像是这样:
其中units参数代表输出维度数量(某种程度上可以想像成几个Nodes),最后一层代表输出变数,以回归问题而言我们都把最后一层设定为1,中间层的节点数量我们可以留待之后调参再调整。接着我们要对资料做出一些处理。这边要将资料切分成Train与Test,这是我们很久以前提到过为了检验模型效度以及避免Overfitting所使用的方法,我们这边比例设定为8:2。
另外要注意的是,LSTM输入的维度必须是三维度资料,所以我们这边需要多一个dim()方法去将数组划分维度,接下来,把数据塞进去模型:
这样一来我们就可以得到RMSE值,这个结果在1.567,优于一般的线性回归(1.7),而劣于XGBoost(1.475)。不过一来我们还可以透过参数调整的方式来得到更好的结果,此外因为这组数据经过Train_Test_Split,得到的数据应该比前两个模型更可靠一点。具体的参数调整包括调整Timestep, Optimizer等等,这边就不一一示范。结尾终于!把这一篇自学日记告一个段落,后期也不知道写什么了。虽然感觉时间序列分析实际上还有很多方向值得探索,但目前为止也算是整体性地浏览过了整体样貌。整个系列一直没有提到一些很精细的模型原理或是比较深入的比较,一来是演算法以及分析模型的确是非常广大,现阶段很难做到精通大多数,另一方面则是本文的目的一直是以商业角度出发的自学纪录,很多东西也就点到为止。