RNN入门(三)训练深度RNN来预测时间序列


该系列的Jupyter放在下方:

原码点击下载

RNN训练速度较慢,请选择算力较强的计算机。

书接上回:我们在第二部分中成功搭建了由单个神经元构成的简单RNN,预测值与真实值的误差如下:




大体趋势预测的差不多,但误差还是有的。这篇文章我们尝试搭建多层的RNN网络来进行预测。

搭建3层SimpleRNN层

首先搭建一个3层的SimpleRNN层:

由于自己笔记本的算力有限,模型训练使用的实验室电脑,然后直接将训练模型的history导进自己的程序。
np.random.seed(42)
tf.random.set_seed(42)

model = keras.models.Sequential([
    keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]),
    keras.layers.SimpleRNN(20, return_sequences=True),
    keras.layers.SimpleRNN(1)
])

model.compile(loss="mse", optimizer="adam")
history = model.fit(X_train, y_train, epochs=20,
                    validation_data=(X_valid, y_valid))

评估均方误差:

model.evaluate(X_valid, y_valid)

绘制损失曲线:



使用深度RNN进行预测后目标值和预测值如下:


可以看到相比于单层神经元,有了很大改进。

但是多层RNN有如下注意事项:
确保为所有的循环层设置了return_sequences=True。如果我们只关注最后一个输出,则最后一个循环层可以不写。
如果不这么写,模型会输出一个2维数组(只包含最后一个时间步长的输出)。而不是一个三维数组(包含所有步长的输出),且下一个循环层会因格式不匹配而报错。

输出层优化:

  • 由于我们预测的是一个单变量时间序列,所以每个时间步长都必须有一个输出值。但最后一层如果只有一个循环神经元,说明隐藏状态只是一个数字,这个隐藏状态没什么用。
  • SimpleRNN默认使用tanh激活函数,因此预测值必须在[-1,1]区间。所以也就没法使用其他激活函数了。

基于以上两点原因,可以把输出层替换成Dense层。优点如下:

  • 运行速度会稍微加快,但精度大致不变
  • 可以选择其他的激活函数了。

注意修改最后一层为Dense层以后,要确保前一个循环层的return_sequences=True删掉。

np.random.seed(42)
tf.random.set_seed(42)

# 搭建模型
np.random.seed(42)
tf.random.set_seed(42)

# 搭建模型
model = keras.models.Sequential([
    keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]),
    keras.layers.SimpleRNN(20),
    keras.layers.Dense(1)
])

评估均方误差:

model.evaluate(X_valid, y_valid)

绘制损失函数:

plot_learning_curves(history["loss"], history["val_loss"])
plt.show()



预测结果如下:



声明:奋斗小刘|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - RNN入门(三)训练深度RNN来预测时间序列


Make Everyday Count