如何优雅地用TensorFlow预测时间序列:TFTS库详细教程

作者:何之源 转载自知乎专栏:AI Insight 量子位 已获授权编辑发布

这篇文章中,作者详细介绍了TensorFlow Time Series(TFTS)库的使用方法。主要包含数据读入、AR模型的训练、LSTM模型的训练三部分内容。内容翔实有趣,量子位转载分享给大家。

前言

如何用TensorFlow结合LSTM来做时间序列预测其实是一个很老的话题,然而却一直没有得到比较好的解决。如果在Github上搜索“tensorflow time series”,会发现star数最高的tgjeon/TensorFlow-Tutorials-for-Time-Series已经和TF 1.0版本不兼容了,并且其他的项目使用的方法也各有不同,比较混乱。

tgjeon/TensorFlow-Tutorials-for-Time-Series地址:

https://github.com/tgjeon/TensorFlow-Tutorials-for-Time-Series**

在刚刚发布的TensorFlow 1.3版本中,引入了一个TensorFlow Time Series模块(以下简称为TFTS)。TFTS专门设计了一套针对时间序列预测问题的API,目前提供AR、Anomaly Mixture AR、LSTM三种预测模型

TFTS模块源码地址:

https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/timeseries

由于是刚刚发布的库,文档还是比较缺乏的,我通过研究源码,大体搞清楚了这个库的设计逻辑和使用方法,这篇文章是一篇教程帖,会详细的介绍TFTS库的以下几个功能:

  • 读入时间序列数据(分为从numpy数组和csv文件两种方式)
  • 用AR模型对时间序列进行预测
  • 用LSTM模型对时间序列进行预测(包含单变量和多变量)

先上效果图,使用AR模型预测的效果如下图所示,蓝色线是训练数据,绿色为模型拟合数据,红色线为预测值:

使用LSTM进行单变量时间序列预测:

使用LSTM进行多变量时间序列预测(每一条线代表一个变量):

文中涉及的所有代码已经保存在Github上了,以下提到的所有代码和文件都是相对于这个项目的根目录来说的

Github地址:

https://github.com/hzy46/TensorFlow-Time-Series-Examples

时间序列问题的一般形式

一般地,时间序列数据可以看做由两部分组成:观察的时间点和观察到的值。以商品价格为例,某年一月的价格为120元,二月的价格为130元,三月的价格为135元,四月的价格为132元。

那么观察的时间点可以看做是1,2,3,4,而在各时间点上观察到的数据的值为120,130,135,132。

从Numpy数组中读入时间序列数据

如何将这样的时间序列数据读入进来?TFTS库中提供了两个方便的读取器NumpyReader和CSVReader。前者用于从Numpy数组中读入数据,后者则可以从CSV文件中读取数据。

我们利用np.sin,生成一个实验用的时间序列数据,这个时间序列数据实际上就是在正弦曲线上加上了上升的趋势和一些随机的噪声:

我们利用np.sin,生成一个实验用的时间序列数据,这个时间序列数据实际上就是在正弦曲线上加上了上升的趋势和一些随机的噪声:

如图:

横坐标对应变量“x”,纵坐标对应变量“y”,它们就是我们之前提到过的“观察的时间点”以及“观察到的值”。TFTS读入x和y的方式非常简单,请看下面的代码:

我们首先把x和y变成python中的词典(变量data)。变量data中的键值tf.contrib.timeseries.TrainEvalFeatures.TIMES实际就是一个字符串“times”,而tf.contrib.timeseries.TrainEvalFeatures.VALUES就是字符串”values”。

所以上面的定义直接写成“data = {‘times’:x, ‘values’:y}”也是可以的。写成比较复杂的形式是为了和源码中的写法保持一致。

得到的reader有一个read_full()方法,它的返回值就是时间序列对应的Tensor,我们可以用下面的代码试验一下:

不能直接使用sess.run(reader.read_full())来从reader中取出所有数据。原因在于read_full()方法会产生读取队列,而队列的线程此时还没启动,我们需要使用tf.train.start_queue_runners启动队列,才能使用sess.run()来获取值。

我们在训练时,通常不会使用整个数据集进行训练,而是采用batch的形式。从reader出发,建立batch数据的方法也很简单:

tf.contrib.timeseries.RandomWindowInputFn会在reader的所有数据中,随机选取窗口长度为window_size的序列,并包装成batch_size大小的batch数据。换句话说,一个batch内共有batch_size个序列,每个序列的长度为window_size

以batch_size=2, window_size=10为例,我们可以打出一个batch内的数据:

这部分读入代码的地址: https://github.com/hzy46/TensorFlow-Time-Series-Examples/blob/master/test_input_array.py

从CSV文件中读入时间序列数据

有的时候,时间序列数据是存在CSV文件中的。我们当然可以将其先读入为Numpy数组,再使用之前的方法处理。更方便的做法是使用tf.contrib.timeseries.CSVReader读入。

项目中提供了一个test_input_csv.py代码,示例如何将文件./data/period_trend.csv中的时间序列读入进来。

代码地址:

https://github.com/hzy46/TensorFlow-Time-Series-Examples/blob/master/test_input_csv.py

假设CSV文件的时间序列数据形式为:

CSV文件的第一列为时间点,第二列为该时间点上观察到的值。将其读入的方法为:

从reader建立batch数据形成train_input_fn的方法和之前完全一样。下面我们就利用这个train_input_fn来训练模型。

使用AR模型预测时间序列

自回归模型(Autoregressive model,可以简称为AR模型)是统计学上处理时间序列模型的基本方法之一。在TFTS中,已经实现了一个自回归模型。使用AR模型训练、验证并进行时间序列预测的示例程序为train_array.py。

train_array.py地址:

https://github.com/hzy46/TensorFlow-Time-Series-Examples/blob/master/train_array.py

先建立一个train_input_fn:

针对这个序列,对应的AR模型的定义就是:

这里的几个参数比较重要,分别给出解释。

第一个参数periodicities表示序列的规律性周期。我们在定义数据时使用的语句是:“y = np.sin(np.pi * x / 100) + x / 200. + noise”,因此周期为200。

input_window_size表示模型每次输入的值,output_window_size表示模型每次输出的值。input_window_size和output_window_size加起来必须等于train_input_fn中总的window_size

在这里,我们总的window_size为40,input_window_size为30,output_window_size为10,也就是说,一个batch内每个序列的长度为40,其中前30个数被当作模型的输入值,后面10个数为这些输入对应的目标输出值。

最后一个参数loss指定采取哪一种损失,一共有两种损失可以选择,分别是NORMAL_LIKELIHOOD_LOSS和SQUARED_LOSS。

num_features参数表示在一个时间点上观察到的数的维度。我们这里每一步都是一个单独的值,所以num_features=1

除了程序中出现的几个参数外,还有一个比较重要的参数是model_dir。它表示模型训练好后保存的地址,如果不指定的话,就会随机分配一个临时地址。

使用变量ar的train方法可以直接进行训练:

TFTS中验证(evaluation)的含义是:使用训练好的模型在原先的训练集上进行计算,由此我们可以观察到模型的拟合效果,对应的程序段是:

如果要理解这里的逻辑,首先要理解之前定义的AR模型:它每次都接收一个长度为30的输入观测序列,并输出长度为10的预测序列。

整个训练集是一个长度为1000的序列,前30个数首先被当作“初始观测序列”输入到模型中,由此就可以计算出下面10步的预测值。接着又会取30个数进行预测,这30个数中有10个数就是前一步的预测值,新得到的预测值又会变成下一步的输入,以此类推。

最终我们得到970个预测值(970=1000-30,因为前30个数是没办法进行预测的)。这970个预测值就被记录在evaluation[‘mean’]中。evaluation还有其他几个键值,如evaluation[‘loss’]表示总的损失,evaluation[‘times’]表示evaluation[‘mean’]对应的时间点等等。

evaluation[‘start_tuple’]会被用于之后的预测中,它相当于最后30步的输出值和对应的时间点。以此为起点,我们可以对1000步以后的值进行预测,对应的代码为:

这里的代码在1000步之后又像后预测了250个时间点。对应的值就保存在predictions[‘mean’]中。我们可以把观测到的值、模型拟合的值、预测值用下面的代码画出来:

画好的图片会被保存为“predict_result.jpg”

使用LSTM预测单变量时间序列

注意:以下LSTM模型的例子必须使用TensorFlow最新的开发版的源码。具体来说,要保证“from tensorflow.contrib.timeseries.python.timeseries.estimators import TimeSeriesRegressor”可以成功执行。

给出两个用LSTM预测时间序列模型的例子,分别是train_lstm.py和train_lstm_multivariate.py。前者是在LSTM中进行单变量的时间序列预测,后者是使用LSTM进行多变量时间序列预测。

为了使用LSTM模型,我们需要先使用TFTS库对其进行定义,定义模型的代码来源于TFTS的示例源码,在train_lstm.py和train_lstm_multivariate.py中分别拷贝了一份。

TFTS的示例源码地址:

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/timeseries/examples/lstm.py

我们同样用函数加噪声的方法生成一个模拟的时间序列数据:

此处y对x的函数关系比之前复杂,因此更适合用LSTM这样的模型找出其中的规律。得到y和x后,使用NumpyReader读入为Tensor形式,接着用tf.contrib.timeseries.RandomWindowInputFn将其变为batch训练数据。

一个batch中有4个随机选取的序列,每个序列的长度为100。

接下来我们定义一个LSTM模型:

num_features = 1表示单变量时间序列,即每个时间点上观察到的量只是一个单独的数值。num_units=128表示使用隐层为128大小的LSTM模型。

训练、验证和预测的方法都和之前类似。在训练时,我们在已有的1000步的观察量的基础上向后预测200步:

将验证、预测的结果取出并画成示意图,画出的图像会保存成“predict_result.jpg”文件:

使用LSTM预测多变量时间序列

所谓多变量时间序列,就是指在每个时间点上的观测量有多个值。在data/multivariate_periods.csv文件中,保存了一个多变量时间序列的数据:

这个CSV文件的第一列是观察时间点,除此之外,每一行还有5个数,表示在这个时间点上的观察到的数据。换句话说,时间序列上每一步都是一个5维的向量

使用TFTS读入该CSV文件的方法为:

与之前的读入相比,唯一的区别就是column_names参数。它告诉TFTS在CSV文件中,哪些列表示时间,哪些列表示观测量。

接下来定义LSTM模型:

区别在于使用num_features=5而不是1,原因在于我们在每个时间点上的观测量是一个5维向量。

训练、验证、预测以及画图的代码与之前比较类似,可以参考代码train_lstm_multivariate.py,此处直接给出最后的运行结果:

参考代码地址:

https://github.com/hzy46/TensorFlow-Time-Series-Examples/blob/master/train_lstm_multivariate.py

图中前100步是训练数据,一条线就代表观测量在一个维度上的取值。100步之后为预测值。

总结

这篇文章详细介绍了TensorFlow Time Series(TFTS)库的使用方法。主要包含三个部分:数据读入、AR模型的训练、LSTM模型的训练。

文章里使用的所有代码都保存在Github上了,地址是:https://github.com/hzy46/TensorFlow-Time-Series-Examples。如果觉得有帮助,欢迎点赞或star~~~

原文发布于微信公众号 - 量子位(QbitAI)

原文发表时间:2017-09-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏专知

【干货】计算机视觉实战系列01——用Python做图像处理

【导读】在当今互联网飞速发展的社会中,数量庞大的图像和视频充斥着我们的生活,让我们需要对图片进行检索、分类等操作时,利用人工手段显然是不现实的,于是,计算机视觉...

90612
来自专栏程序员的诗和远方

人人都可以学的人工智能:TensorFlow 入门例子

这是用 TensorFlow 来识别手写数字的官方经典入门例子,数据都是已经处理过准备好了的,但是只到计算准确度概率那就停了,缺少拿实际图片运用的例子,初学者...

60610
来自专栏人工智能头条

如何用TensorFlow预测时间序列:TFTS库详细教程

1813
来自专栏机器之心

NIPS 2018 | 将RNN内存占用缩小90%:多伦多大学提出可逆循环神经网络

循环神经网络(RNN)在语音识别 [1]、语言建模 [2,3] 和机器翻译 [4,5] 等多种任务上都取得了极优的性能。然而,训练 RNN 需要大量的内存。标准...

844
来自专栏机器之心

专栏 | 在PaddlePaddle上实现MNIST手写体数字识别

机器之心专栏 来源:百度PaddlePaddle 不久之前,机器之心联合百度推出 PaddlePaddle 专栏,为想要学习这一平台的技术人员推荐相关教程与资源...

2795
来自专栏刁寿钧的专栏

使用 Tensorflow 构建 CNN 进行情感分析实践

本次实验参照的是 Kim Yoon 的论文,代码放在我的 github 上,可直接使用。

2.8K1
来自专栏专知

【最新TensorFlow1.4.0教程02】利用Eager Execution 自定义操作和梯度 (可在 GPU 运行)

点击上方“专知”关注获取更多AI知识! 【导读】主题链路知识是我们专知的核心功能之一,为用户提供AI领域系统性的知识学习服务,一站式学习人工智能的知识,包含人工...

5266
来自专栏贾志刚-OpenCV学堂

SSD网络tensorflow版本源码深入分析

以VGG-16作为特征提取层实现SSD网络的代码,解读SSD网络代码实现的各个细节,从输入参数、默认框的位置匹配、宽高比率、放缩比率、各层默认框的生成、到损失函...

2964
来自专栏人工智能

使用Keras在训练深度学习模型时监控性能指标

Keras库提供了一套供深度学习模型训练时的用于监控和汇总的标准性能指标并且开放了接口给开发者使用。

1.9K10
来自专栏深度学习思考者

目标检测:选择性搜索策略(C++ / Python)

导读:通过本教程,我们将彻底理解一个重要的概念:目标检测中的常用方法“Selective Search”。文末也会给出使用C++或者Python的Opencv代...

5947

扫码关注云+社区