如何用 Keras 调试LSTM超参数解决时间序列预测问题
配置神经网络十分困难,因为并没有关于如何进行配置的好理论。
你必须用系统化的思维从动态结果和客观结果这两个角度探讨不同配置,设法理解给定预测建模问题。
在本教程中,您将学会探讨如何配置LSTM网络解决时间序列预测问题的方法。
在学完此教程后,你将懂得:
如何调试和解释训练epoch个数的结果;
如何调试和解释训练批大小的结果;
如何调试和解释神经元数量的结果。
让我们开始学习吧。
教程概览
本教程分为 6 部分;它们分别是:
洗发水销量数据集
试验测试工具
调试 epoch 次数
调试批大小
调试神经元数量
结果总结
环境
本教程假设您已安装 PythonSciPy 环境。您在学习本示例时可使用Python 2 或 3。
本教程假设您已使用TensorFlow或 Theano后端安装Keras(2.0或更高版本)。
本教程还假设您已安装scikit-learn、Pandas、 NumPy 和 Matplotlib。
如果您在安装Python环境时需要帮助,请查看这篇文章:
如何使用Anaconda安装机器学习和深度学习所需的 Python 环境
http://machinelearningmastery.com/setup-python-environment-machine-learning-deep-learning-anaconda/
洗发水销量数据集
该数据集描述某洗发水在3年内的月度销量。
数据单位为销售量,共有36个观察值。原始数据集由 Makridakis、Wheelwright和Hyndman(1998)提供。
您可通过此链接下载和进一步了解该数据集:https://datamarket.com/data/set/22r0/sales-of-shampoo-over-a-three-year-period。
下方示例代码加载并生成已加载数据集的视图。
运行该示例,以Pandas序列的形式加载数据集,并打印出头5行。
然后就可生成显示明显增长趋势的序列线图。
接下来,我们将看一下本试验中使用的LSTM配置和测试工具。
试验测试工具
此部分描述本教程使用的测试工具。
数据划分
我们将把洗发水销量数据集分为两个集合:一个训练集和一个测试集。
前两年的销售数据将作为训练数据集,最后一年的数据将作为测试集。
我们将使用训练数据集创建模型,然后对测试数据集进行预测。
对测试数据集的持续性(persistence)预测(天真预测)的误差为136.761(单位:洗发水月度销量)。这种预测方法为测试工具提供了一个较低的性能合格界限。
模型评测
我们将使用滚动预测的方式,也称为步进式模型验证。
以每次一个的形式运行测试数据集的每个时间步。使用模型对时间步作出预测,然后收集测试组生成的实际预期值,模型将利用这些预期值预测下一时间步。
这模拟了现实生活中的场景,新的洗发水销量观察值会在月底公布,然后被用于预测下月的销量。
训练数据集和测试数据集的结构将对此进行模拟。我们将一步生成所有的预测。
最后,收集所有测试数据集的预测,计算误差值总结该模型的预测能力。采用均方根误差(RMSE)的原因是这种计算方式能够降低粗大误差对结果的影响,所得分数的单位和预测数据的单位相同,即洗发水月度销量。
数据准备
在用数据集拟合LSTM模型前,我们必须对数据进行转化。
在匹配模型和进行预测之前须对数据集进行以下三种数据转化。
转化序列数据使其呈静态。具体来说,就是使用 lag=1差分移除数据中的增长趋势。
将时间序列问题转化为监督学习问题。具体来说,就是将数据组为输入和输出模式,上一时间步的观察值可作为输入用于预测当前时间步的观察值。
转化观察值使其处在特定区间。具体来说,就是将数据缩放带 -1 至1的区间内,以满足LSTM模型默认的双曲正切激活函数。
在进行计算和得出误差分数之前,对预测值进行这些转化的逆转化使它们恢复至原来的区间内。
试验运行
每种试验方案将进行10次试验。
这样做的原因是LSTM网络的初始条件随机生成,得出的结果会大不相同,每进行一次试验,给定配置都会受到训练。
我们将使用诊断方法研究模型配置。在诊断中,我们将生成模型在各时段(训练迭代,称为 epoch )预测水平的线图,通过研究该线图来理解给定配置的性能以及如何通过调整使其实现出更好的性能。
在每个epoch结束时分别使用训练数据集和测试数据集评测该模型,并记录均方根误差分数。
在每个方案试验结束时打印训练和测试的均方根误差分数,以显示出正在进行的效果。
在运行完试验时,生成训练和测试的均方根误差分数序列线图。训练分数为蓝色,测试分数位橙色。
让我们开始研究这些结果吧。
调试Epoch个数
我们在调试时将要看的第一个LSTM参数就是训练epoch的个数。
该模型使用的批大小将为4,神经元个数为1。我们将将探讨用不同Epoch个数训练该配置所产生的影响。
用500个Epoch训练的诊断
该诊断完整的代码编写如下所示。
该代码有适当的注释,应该易于理解。它将作为本教程中所有未来试验的基础,并且本教程将只会列出各后续试验中有更改的地方。
运行试验,每运行完一个试验(共10个),打印训练和测试数据集的均方根误差。
并且在每个训练epoch结束后生成训练数据集和测试数据集均方根误差分数的序列线图。
这些结果清楚地表明,在几乎所有的试验运行中,随着训练epoch的增加,均方根误差都呈下降趋势。
这是个好迹象,因为它表明此模型正在学习该预测问题并且已具备几分预测能力。实际上,所有的最终测试分数都小于简单持久性模型(天真预测)的预测误差,该模型在预测此问题时所得均方根误差为136.761。
这些结果表明,训练epoch越多,模型的预测水平就越高。让我们将epoch个数从500 倍增至1000。
用1000个Epoch训练的诊断
在本部分,我们将使用同样的试验设置,用1000个训练epoch拟合该模型。
具体就是,将run()函数中的n_epochs 参数设定为1000。
运行示例,打印训练数据集和测试数据集最后一个epoch所得的均方根误差。
另外再生成一个描述每个epoch数据集和测试数据集均方根误差的线图。
我们可以看出,模型误差的下行趋势继续保持,并且下降的速度很慢。
训练数据集和测试数据集的轨迹线变得越拉越水平,虽然变化速率较低,但是总体上仍热呈现下行趋势,某些测试误差的例子在600 epoch附近显示出一个可能的转折点和上行趋势。
进一步增大epoch很有效果。我们认为,模型预测测试数据集的平均性能继续增强,并且性能还会进一步增强。
让我们试着把epoch的数量从1000增至2000。
用2000个Epoch训练的诊断
在本部分,我们将使用同样的试验设置,用2000个训练epoch拟合该模型。
具体就是,将run()函数中的n_epochs 参数设定为2000。
运行示例,打印训练数据集和测试数据集最后一个epoch所得的均方根误差。
另外再生成一个描述每个epoch数据集和测试数据集均方根误差的线图。
正如我们预测的那样,训练数据集和测试数据集误差的下行趋势在增加的1000个epoch内都继续存在。
值得注意的是,大约一半例子的误差继续减小直至试验结束运行,但是剩余的那部分例子却显示出增加趋势的迹象。
增加趋势是过度拟合的标志。这种情况就是模型过渡拟合训练数据集,代价是模型预测测试数据集的性能变差。如图所示,模型对训练数据集的预测性能继续增强,这种增强之后紧跟着一个转折点,并且模型预测测试数据集的性能越来越差。近一半的试验运行表明,这种变化出现在测试数据集上。
但是,最后的epoch对测试数据集预测结果非常好,如果通过更长的训练观察我们能够有机会看到性能进一步增强,我们就必须对其进行探索。
让我们试着将epoch数从2000增至4000.
用4000个Epoch训练的诊断
在本部分,我们将使用同样的试验设置,用4000个训练epoch拟合该模型。
具体就是,将run()函数中的n_epochs 参数设定为4000。
运行示例,打印训练数据集和测试数据集最后一个epoch所得的均方根误差。
另外再生成一个描述每个epoch数据集和测试数据集均方根误差的线图。
类似的变化模式保持继续。
线图显示出性能增强的总体趋势,即使是在4000 epoch之后。其中一个例子出现过度拟合,测试失误大幅增加。
同样,大部分例子在最后都得到一个“良好”(好于persistence模型)的最终测试误差。
结果总结
上文进行的诊断对探讨该模型的动态行为很有帮助,但是却缺乏一个客观且可作为比较的平均性能。
通过重复相同的试验,计算并比较每个配置的总结统计,我们可以解决这个问题。在本例中,我们分别用不同的epoch 值(500、1000、2000、4000和6000)各运行30次试验。
目的是利用通过运行更多试验而得出的总结统计对各配置进行比较,然后观测到底哪个配置的平均性能更好。
完整的代码示例如下所示:
运行代码,首先打印每个配置(共5个)的总结统计。值得注意的是,它包括从每个结果样本群得出的均方根误差的均值偏差和标准偏差。
通过均值偏差可以看出配置的平均预期性能,而通过标准偏差则可以看出配置性能的离散程度。通过最小和最大的均方根误差还可以分别看出预期可能出现的最好和最坏的例子。
通过均值均方根误差分数,这些结果表明epoch值为1000的模型可能更好。这些结果还表明,如果epoch值在1000和2000之间,则可能需要进一步的研究。
还通过一个箱须图显示该数据分布。此图可以帮助读者理解数据分布的比较情况。
绿线显示中值,方框显示数据第25和第75个百分点或者中间50%。这种比较还表明,选择将epoch设定为1000要比选择其他受测试的epoch值更好。它还表明,epoch值设为2000或4000可得到最佳预期性能,代价是平均性能最差。
下面,我们来探讨批大小的影响。
调试批大小
批大小控制更新网络权重的频率。
尤为重要的是,在keras中,批大小必须作为测试数据集和训练数据集大小的一个因子。
在上一部分中,我们在探讨训练epoch数量的影响时将批大小设为4,数据刚好可被分配至测试数据集(大小为12)和截断版的测试数据集(大小为20)。
在本部分中,我们将探讨批大小不同所产生的影响。我们将把训练epoch的数量设定为常量1000。
epoch数量为1000、批大小为4的诊断
作为提醒,上一部分的第二个试验用1000个epoch评估了批大小为4的模型。
结果显示,大部分试验中误差的下行趋势一直持续至最后的训练epoch。
epoch数量为1000、批大小为2的诊断
在本部分,我们观察将批大小从4减小至2所产生的影响。
修改run()函数中的n_batch参数来完成该改变;例如:
运行示例,显示出的性能总体趋势与批大小为4时一样,最后一个epoch的均方根误差可能更高。
试验可能很快显示均方根误差稳定的行为,而不是似乎继续下行的趋势。
每次试验最后得出的均方根误差如下所示。
另外还生成了一个描述每个epoch测试和训练均方根误差分数的线图。
让我们试着再将批大小减少一半。
数量为1000、批大小为1的诊断
批大小为1的模型严格来说是在执行在线学习。
在这种情况中,完成每个训练模式后网络都会进行更新。相比之下,批量学习中只有在每个epoch结束时才对权重进行更新。
我们可以改变run()函数中的n_batch参数;例如:
同样,运行示例,打印每次运行最后一个epoch的均方根误差分数。
另外还生成了一个描述每个epoch测试和训练均方根误差分数的线图。
该线图表明,测试均方根误差随着时间的递增越不稳定,批大小越小训练均方根误差稳定得可能就越早。鉴于对网络作出的较大改变在每次更新时作出的反馈极少,我们预料到测试均方根误差会更不稳定。
该图还表明,如果配置获得更多的训练epoch,均方根误差递减的趋势可能会继续存在。
结果总结
和改变训练epoch一样,我们可以通过改变批大小客观地比较网络性能。
对每个配置进行30次试验并且在最终结果中计算总结统计。
从平均性能的角度看,这些结果表明:批大小为1时均方根误差较低。正如前一部分所述,训练epoch越多,平均性能可能越强。
借助另外生成的数据箱须图可以图形的方式对分布进行比较。平均性能在该图中表示为绿线,可以看出批大小为4的例子最不稳定,而且中值均方根误差最低。
调试神经网络是在平均性能和性能稳定性之间进行权衡,以获得平均误差较低并且稳定性较好的理想结果,这意味着该神经网络大体上良好并且可以复制。
调试神经元数量
在本部分中,我们将研究改变神经网络中神经元的数量所产生的影响。
神经元数量影响网络的学习能力。一般而言,神经元越多的神经网络能够从问题中学到更多的结构,代价是训练时间更长。更多的学习能力还可能会造成过度拟合训练数据的问题。
我们将选择使用批大小为4、训练epoch为1000的配置。
Epoch数为1000、神经元数为1的诊断
我们将先以1个神经元起步。
作为提醒,这是epoch试验中测试的第二个配置。
Epoch数为1000、神经元数为2的诊断
我们可以将神经元数从1增至2。这预计将改进神经网络的学习能力。
我们可以通过改变run() 函数中的n_neurons变量实现这步。
运行此配置,打印每次试验最后一个epoch的均方根误差分数。
这些结果表明整体性能良好但不优异。
另外还生成一个描述每个epoch测试盒训练均方根误差分数的线图。
通过该线图能获得更多信息。它显示测试均方根误差在快速将至大约epoch 500-750后出现了一个转折点,该点之后所有试验的测试均方根误差几乎全面增加。同时可以看出,训练数据集的均方根误差继续将至最后一个epoch。
这是过度拟合训练数据集的良好标志。
让我们看看神经元更多时这个趋势是否继续存在。
Epoch数为1000、神经元数为3的诊断
在此部分中,我们将继续观测同一配置,但将神经元数增至3。
我们可以通过设置run() 函数中的n_neurons变量实现这步。
运行此配置,打印每次试验最后一个epoch的均方根误差分数。
结果与上一部分的结果类似;我们看到,神经元数为2和3这两种配置的最后一个epoch测试分数之间并未有何大的整体差异。神经元数为3,最终的训练分数似乎更低,可能显示出过度拟合的加速。
训练数据集中的转折点似乎比两个神经元的试验更早出现,大约出现在epoch 300-400之间。
作出额外改变以减慢学习速度可能使神经元数量增加的配置获益。例如使用以下调整方法:dropout、减少至批大小和减少至训练epoch的数量。
另外还生成了一个描述每个epoch测试和训练均方根误差分数的线图。
结果总结
同样,我们可以在保存所有其他网络配置固定不变的同时,客观地比较增加神经元数量所产生的影响。
在本部分中,我们将每个试验重复30次,然后比较神经元数量(1至5)不同时的平均测试均方根误差性能。
运行试验,打印每个配置的总计统计。
从平均性能的角度看,这些结果表明神经元数为1的网络配置在epoch数为1000并且批大小为4时的性能最好。该配置还显示出最密集的差异。
从该箱须图可以看出,中值测试数据集性能显示出明显的趋势,神经元数量增加,测试均方根误差也相应会增加。
所有结果的总结
我们在本教程中完成了很多关于洗发水销售数据集的LSTM试验。
总体而言,配置如下的有状态LSTM可能是一个好的配置:神经元数为1、批大小为4、epoch数为1000。
这些结果还表明,批次大小为1并且拟合更多epoch的配置可能值得我们进一步探讨。
调试神经网络是一项困难的工作,调试LSTM也不例外。
本教程阐述了对配置随时段变化的性能进行诊断研究以及对测设均方根误差进行客观研究的好处。
但是,还有更多可以进行的研究。下一部分罗列了部分想法。
延 伸
此部分罗列了部分延伸想法,这些想法针对的是本教程中进行的试验。
如果你对以下想法进行了探索,请在评论区报告你的成果;我非常愿意查看你提出的内容。
Dropout。通过调整方法减慢学习,例如在环式LSTM连接上应用dropout。
网络层。通过增加网络层和每层上的不同神经元数,探索额外的分级学习能力。
调整。探讨如何使用权重调整(如L1和L2)减慢学习和某些配置上网络的过度拟合。
优化算法。探索替代优化算法的使用,例如经典的梯度下降法,检查特定配置加快或减慢学习速度是否能够带来好处。
损失函数。探索替代损失函数的使用,检查此类函数能否用于改善性能。
特征和时间步。探索将滞后观察作为输入特征或者特征的输入时间步,检查将它们作为输出能否改善模型的学习和/或预测能力。
更大的批大小。探索大于4的批次大小,可能需要对训练和测试数据集的大小实施进一步控制。
总 结
在本教程中,你学会了如何系统化地研究LSTM网络用于预测时间序列的配置。
具体而言,你学习了:
如何设计系统的测试工具,来用于评估模型配置。
如何使用随时间变化的模型诊断,以及解释模型的客观预测失误。
如何探讨和解释训练epoch数、批大小和神经元数的影响。
本文作者 Jason Brownlee 博士是一位学术研究员、作家、专业开发者和机器学习从业人员。他致力于帮助开发者开始学习并掌握机器学习应用。
本文由 AI100 编译,转载需得到本公众号同意。
编译:AI100
原文链接:http://machinelearningmastery.com/seed-state-lstms-time-series-forecasting-python/
关于AI100
AI100致力于打造人工智能技术和产业社区。为人工智能开发者提供信息和技术交流的平台;为人工智能创业者提供行业数据及智能应用的商业场景;为行业提供人工智能化的技术商业应用。请快快关注AI100公众号吧!