循环神经网络第10课:神经网络基础篇十一
循环神经网络第10课:神经网络基础篇十一如何根据前面的数据预测接下来的数据,比如知道上图0-50之间的数据,预测第51个数据;知道1-51之间的数据,预测第52个数据每个数据组成了一个正弦曲线,即曲线上的每个点是由表格中的数据组成的每个时间点产生不同的数据,每个数据之间没有相关性,可以用卷机神经网络CNN或传统的神经网络来计算。若t2时刻的数据随着t1时刻产生数据的变化而变化,t3时刻的数据被t1和t2时刻产生的数据所影响,即前面的数据对后面的数据产生影响,这种彼此之间有相关性的数据需要用递归神经网络RNN来计算。训练数据
承接上文神经网络基础篇十
简介
本文介绍下,使用Keras工具包、LSTM网络,进行一个时间序列的预测(比如股票走势预测)
时间序列数据
每个时间点产生不同的数据,每个数据之间没有相关性,可以用卷机神经网络CNN或传统的神经网络来计算。
若t2时刻的数据随着t1时刻产生数据的变化而变化,t3时刻的数据被t1和t2时刻产生的数据所影响,即前面的数据对后面的数据产生影响,这种彼此之间有相关性的数据需要用递归神经网络RNN来计算。
训练数据
每个数据组成了一个正弦曲线,即曲线上的每个点是由表格中的数据组成的
如何根据前面的数据预测接下来的数据,比如知道上图0-50之间的数据,预测第51个数据;知道1-51之间的数据,预测第52个数据
这是RNN网络结构图,结合训练数据
每次输入的序列大小要一致,即第一次输入序列长度为20的,后面每一次输入都需是长度20的序列数据,x0到xt就是一个序列数据。
比如序列长度为50,即对应表格中从上到下的50个数据,每个数据都是一个1维的数值,表示成[N 50 1];如果数据是文字,比如“我们”,将文本转换成300维的向量,则表示成[N 50 300]。
RNN网络模型的整体定义
这个是RNN的网络结构,输入层的数据是序列长度是49,每个序列是一个数值,然后经过一次LSTM(转换成了50维度的向量,是中间结果,中间结果有时候不重要,只需要关注最终输出结果即可),然后Dropout1,然后第二次LSTM(转换成了100维度的向量),然后第二次Dropout,最后是全连接层计算(输出一个一维的数据,一个值)。输入0-49个数据,预测第51个数据。这是一个回归任务,预测一个值。
config.json文件
所有的参数和网络结构的定义都在这个json文件中,从上至下说明:
数据属性
- filename 数据所在的文件名称
- 读取文件中的哪些列
- 序列长度是50
- 训练数据占0.8,验证集数据占0.2
- normalise 是否归一化(预处理)
模型数据
- loss mse均方误差通常作为回归模型的损失函数
- optimizer 优化器
- save_dir 模型保存位置
- layers RNN模型每一层定义
每一层都是一一对应的
- type lstm or dropout
- neurons 隐层神经元的数量
- input_timestaps 时间序列长度
- input_dia 输入数据的维度 比如第一次lstm 输入序列长度为49,1维的数值数据,输出序列长度是49和50维度的向量
- return_seq 是否返回整个序列的结果 第一次lstm返回了整个序列的结果,所以设置为true,第二次lstm返回了一个值,所以设置为false
读取json文件配置
读取数据
数据初始化
读取到数据,第一列是索引,第二列是实际的值
因训练:验证=0.8:0.2=4,所以训练数据有4000条,验证数据是1000条
这是4000条数据训练,
这是1000条验证数据
构建网络模型-初始化模型对象
构建模型
读取json文件配置,一层一层的构建网络结构,for循环json文件网络结构的定义
初始化第一次层
第一层是LSTM层
第二层dropout
依次将所有层都初始化好之后,整个模型就定义好了
将定义好的模型保存。模型有了,接下来加载数据
- 入参seq_len序列长度是50
- range(self.len_train-seq_len) 表示计算有多少个长度为50的序列 4000-50=3950个,因为最后一个序列不能越界,到最后一个序列之后,就没法再往后移动了
- next_window是滑动窗口
- i 为开始位置0
- seq_len序列长度50
- normalise 为false 即不做归一化处理
获取到第一个窗口0-49之间的数据
判断是否需要归一化处理,因为这些数据本来就是0-1之间的,所以不需要归一化
- 前49个数据是输入,最后一个即第50个数据是输出
经过一个for循环,就可以得到第一个窗口的数据
以此类推,得到所有窗口的序列数据
一共得到3095个窗口的序列数据
输入数据x是有3095个窗口,每个窗口有49个数据,1维的数值数据;输出数据y,每个窗口一个输出数据,共3095个输出数据,每个输出数据是一维的数值。
模型训练
有了模型和数据,就可以训练了
- EarlyStopping
比如loss下下降的过程中,基本饱和了,没有太大变化了
右侧的loss曲线平了,800和1万没有什么区别了,就可以提前终止
- ModelCheckpoint
监视val_loss指标,如果连续2次没有变化,就停止训练 - save_best_only 每个epoch都会选择训练最好的模型保存
模型训练
获取并展示测试结果
预测结果和实际结果整体是吻合的
股票数据预测
这是一份真实的股票数据,包含开盘价、最高价、最低价、收盘价、交易量
配置json文件
- filename 读取股票数据
- 读取收盘价Close列数据
- 3个LSTM层
- 不对输入数据做归一化处理
使用mse做损失计算,输入数据的数值越大,loss值越大,对于回归任务来说,不要觉着loss值越大,训练的效果就不好,而是相对的去比较,不像分类任务有准确率,可以直接来进行对比。
绘图展示结果
可以看到预测成了一条直线,说明网络什么都没有学到,原因是数值浮动范围大,没有具体的走势,像是随机数,怎样才能看到走势?第二天的数据相对第一天的,第三天的数据相对第一天的....,让模型记录相对变化的趋势,而不是只看具体的值。
对输入数据做预处理(归一化)
网络结构图
- config配置了输入数据是一个Close列,也可以配置多个列,这里分别对每个列进行归一化处理(for循环)
- shape 0是行,1是列,对每一列都进行归一化操作
- window[: col_i] 获取当前列的所有数据
- 对当前列的每一个数据进行这样的操作:转换成数值类型,然后每一个数据除以当前列的第一个数据,然后-1,获取每个值相对序列中第一个值的相对变化的趋势
学习到每个值针对第一个值相对变化的趋势之后,再将二维数据转换成一个列数据,
- predict_sequences_multiple 基于已有序列,预测后面连续50点的序列,跟之前正弦函数的预测是一样的即根据前50个数据预测后50个数据
- 这个预测效果就不太好了,输入0-50的数据,预测51-100的数据,上图只是预测出了一个大概的趋势,还有几处预测错了,比如图中标红的地方实际数据是上升,预测成下降了(一个序列一个序列的预测)
- predict_point_by_point 点对点的预测即一个长度序列预测一个点即根据前49个数据预测第50个数据(一个点一个点的预测)
所以用LSTM预测一个点还是可以的,但预测一个时间长度的序列,难度就大了
两列的输入数据
网络结构图
输入层输入数据是序列长度是49,每个长度序列中的2个值,预测的最终结果还是一个值。传入多个指标,预测的效果不一定好
一个点一个点的预测
红色圈的地方显示二个指标拟合的好一些,蓝色圈住的地方显示1个指标拟合的好一些
一个序列一个序列的预测
差距就非常大了,所以点对点比较容易,预测序列的还要用到之前预测的结果,效果就没有预测一个点那么直接了。