本节简介本节关于TFTS模块的使用参考知乎-何之源-如何优雅地用TensorFlow预测时间序列:TFTS库详细教程。 如何在TensorFlow上使用LSTM来做时间序列预测是一个很老的话题,然而一直没有比较好的解决方案。在刚刚发布的TensorFlow1.3版本中,在tf.contrib包下引入了一个Time Series模块(TensorFlow Time Series,TFTS)。其源码地址在github timeseries。TFTS提供了一套基础的时间序列模型API。目前提供AR、Anomaly Mixture AR、LSTM三种预测模型。 这里因为是刚刚发布的库,文档匮乏,我们着重于介绍TFTS的以下几个功能:
先看效果图,
这里涉及到的代码保存在github-hzy46.网速不好的同学可以到或者在CSDN上下载。 TensorFlow更新注意 后面使用的LSTM模型的例子须使用TensorFlow最新的开发版的源码。具体来说,要保证下面这句话可以成功执行。 from tensorflow.contrib.timeseries.python.timeseries.estimators import TimeSeriesRegressor
如果执行不成功,则需要下面的更新操作。 下载最新源码(编译源码更新) 1. 首先卸载当前的tensorflow pip uninstall tensorflow #gpu版 就是tensorflow-gpu
2. 参考官方的从源码安装tensorflow 参考TensorFlow官方安装教程。我的开发环境是Ubuntu16.04+1080显卡,需要安装gpu版本。
''' 编译 ''' bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package ''' 挺长的一段编译时间 生产pip包 ''' bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg ''' 安装 ''' sudo pip install /tmp/tensorflow_pkg/tensorflow-1.3.0-py2-none-any.whl
如果出啥问题,建议直接看官方教程来整,有啥小问题,上stackoverflow上找找原因。(从源码编译tensorflow前前后后花费了我2天的时间,现在整出来了,踩了不少的坑,感觉下次会快很多了~) 现在9月初tensorflow的pip安装版本还不支持这个TimeSeriesRegressor类,等到后面版本稳定更新了,应该可以用下面pip工具更新。 直接使用pip工具更新 因为本次用到的库需要运行在TensorFlow1.3版本,而我的环境是Ubuntu下的1.0.1版本的TensorFlow。如果你不知道自己的TensorFlow是啥版本,有一个简单的方法: 激活python编程环境,键入以下代码运行即可。 import tensorflow as tf print(tf.__version__) # 查看tensorflow版本 print(tf.__path__) # 查看tensorflow安装位置 ''' 输出: 1.0.1 ['/root/anaconda2/lib/python2.7/site-packages/tensorflow'] '''
更新方法也很简单,如果你的TensorFlow是普通的安装,直接在命令行键入以下命令: $: sudo pip install --upgrade tensorflow-gpu # 我安装的是gpu版
等待更新完成即可。 import tensorflow as tf print(tf.__version__) # 查看tensorflow版本 print(tf.__path__) # 查看tensorflow安装位置 ''' 输出: 1.3.0 ['/root/anaconda2/lib/python2.7/site-packages/tensorflow'] '''
更新后可能会遇到的异常
到这里,算是大功告成了~ 自定义LSTM循环神经网络进行时间序列预测在使用TFTS库前,我们先利用自定义循环神经网络预测正弦函数。初步学习一下如何使用LSTM循环神经网络进行时间序列预测,这里我们会使用TensorFlow的一个高级封装工具-TFLearn(集成在tf.contrib.learn). 工程实现 1. 需要用到的模块 # coding:utf8 import numpy as np import tensorflow as tf from tensorflow.contrib.learn.python.learn.estimators.estimator import SKCompat import matplotlib.pyplot as plt learn = tf.contrib.learn
2. 生成训练数据与测试数据 因为是要预测正弦函数,这里我们使用np模块下的np.sin函数生成训练数据和测试数据。 TRAINING_EXAMPLES = 10000 # 训练数据大小 TESTING_EXAMPLES = 1000 # 测试数据大小 SAMPLE_GAP = 0.01 #采样间隔 TIMESTEPS = 10 # 循环神经网络截断长度 def generate_data(seq): ''' 定义生成正弦函数数据函数 :param seq: :return: X为训练数据序列,y为预测数据 ''' X = [] y = [] for i in range(len(seq) - TIMESTEPS - 1): X.append([seq[i: i + TIMESTEPS]]) # 截取以i下标开始的以TIMESTEPS为batch的数据 y.append([seq[i + TIMESTEPS]]) # 预测i+TIMESTEPS的数据 return np.array(X, dtype=np.float32), np.array(y, dtype=np.float32) # 生成数据 # TRAINING_EXAMPLES训练数据个数 SAMPLE_GAP采样间隔 test_start = TRAINING_EXAMPLES * SAMPLE_GAP # 训练数据和测试数据个数 test_end = (TRAINING_EXAMPLES + TESTING_EXAMPLES) * SAMPLE_GAP # np.linspace生成等差数列 即采样横轴数据 # 从0到test_start,生成TRAINING_EXAMPLES个数据(即采样间隔为SAMPLE_GAP) train_X, train_y = generate_data(np.sin(np.linspace( 0, test_start, TRAINING_EXAMPLES, dtype=np.float32))) # np.linspace生成等差数列 # test_X, test_y = generate_data(np.sin(np.linspace( test_start, test_end, TESTING_EXAMPLES, dtype=np.float32)))
注解: 训练数据TRAINING_EXAMPLES加上测试数据TESTING_EXAMPLES一共需要11000组。 这里我们设置是采样间隔SAMPLE_GAP是0.01。故我们整个采样距离是11000*0.01=110.也就是在sin函数上,x轴为[0,110]这段距离上均分为11000份。 训练数据是以网络的截断长度为分割间距。这里循环神经网络的截断长度TIMESTEPS为10。故我们的数据也是10个采样点和对应的sin值为一组,预测第11个点。(训练时候就是回归第11个点的值).
下面是np.linspace和np.sin的用法示例: 3. 定义网络模型 我们使用BasicLSTMCell和MultiRNNCell构成一个hidden_size为30的2层的LSTM循环神经网络。需要注意的是不同版本下在创建LSTMCells的方法是不一样的。 HIDDEN_SIZE = 30 # 隐藏单元个数 NUM_LAYERS = 2 #LSTM层数 TRAINING_STEPS = 3000 # 训练数据轮数 BATCH_SIZE = 32 # batch大小 def lstm_model(X, y): ''' 定义LSTM模型 :param X: 训练数据 :param y: 预测标签 :return: ''' # 1.2版本后,tensorflow对使用BasicLSTMCell等 RNNCells生成cells有不同的处理方法,这里多层的RNN建议采用这种创建cell方法 stacked_rnn = [] for iiLyr in range(NUM_LAYERS): stacked_rnn.append(tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True)) cell = tf.nn.rnn_cell.MultiRNNCell(cells=stacked_rnn, state_is_tuple=True) #lstm_cell = tf.contrib.rnn.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True) #1.2版本前 #cell = tf.contrib.rnn.MultiRNNCell([lstm_cell] * NUM_LAYERS) # 将多层LSTM结构连接成RNN网络并计算其前向传播结果 output, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32) # 只关注网络的最后一个输出结果,即为下一时刻的预测输出 output = tf.reshape(output, [-1, HIDDEN_SIZE]) # 通过无激活函数的全联接层计算线性回归,并将数据压缩成一维数组的结构。 predictions = tf.contrib.layers.fully_connected(output, 1, None) labels = tf.reshape(y, [-1]) predictions = tf.reshape(predictions, [-1]) # 定义平方差损失 loss = tf.losses.mean_squared_error(predictions, labels) # 创建模型优化器并得到优化步骤 train_op = tf.contrib.layers.optimize_loss( loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad', learning_rate=0.1) return predictions, loss, train_op
4. 创建模型并训练 这里我们使用了tf.contrib.learn下的一个封装模型工具Estimator。使用Estimator封装好一个预测模型后((已训练),我们对测试数据进行了预测,再计算了下均方误差,大体上的评估了一下模型的预测性能。 # 封装之前定义的lstm # 如果你的tensorflow1.2版本前已经训练好了这样的的一个模型,在tensorflow更新后,重新生成模型。 # 因为在新版本的Tensorflow里,LSTM单元的文件改变了,这里我们简单的把以前的model_dir修改了,保证创建了新的模型 regressor = SKCompat(learn.Estimator(model_fn=lstm_model, model_dir='Models/model_3')) # 拟合数据 regressor.fit(train_X, train_y, batch_size=BATCH_SIZE, steps=TRAINING_STEPS) # 计算预测值 predicted = [[pred] for pred in regressor.predict(test_X)] # 计算MSE rmse = np.sqrt(((predicted - test_y) ** 2).mean(axis=0)) print ('Mean Square Error is: %f' % rmse[0])
Estimator工具 这里我们简单的介绍以下Estimator工具。 参考TensorFlow 0.12 Estimators Models Layers学习笔记。Estimators的作用是:
总的来说,我们可以认为tf.estimator工具是用来提供一个自定义模型的框架,我们照着定义好的格式配置好输入即可。
5. 绘图 使用plt将预测数据和测试数据绘制出来,有一个直观上的认识。 fig = plt.figure() plot_predicted, = plt.plot(predicted, label='predicted') plot_test, = plt.plot(test_y[0:399], label='real_sin') plt.legend([plot_predicted, plot_test],['predicted', 'real_sin']) plt.show() fig.savefig('pre_sin.png')
利用TFTS进行时间序列预测到这里算是切入主题了,下面介绍如何使用TFTS模块进行时间序列预测。 载入数据部分 对于时间序列预测问题,我们可以把数据抽象成:{观察点:观察值}。例如某年一月的价格为120元,二月的价格为130元,三月的价格为135元,四月的价格为132元。那么观察的时间点可以看做是1,2,3,4,而在各时间点上观察到的数据的值为120,130,135,132。 TFTS库提供了两个数据读取器NumpyReader和CSVReader. NumpyReader用于从Numpy数组中读入数据,下面举一个demo: import numpy as np import matplotlib.pyplot as plt x = np.array(range(1000)) noise = np.random.uniform(-0.2, 0.2, 1000) # 随机生成-0.2~0.2之间的数据 y = np.sin(np.pi * x * 0.01) + x * 0.005 + noise # y=sin(0.01*pi*x) + 0.005*x + noise p = plt.plot(x, y) plt.show()
横轴即’采样点x’,纵轴为’采样值y’. TFTS提供的读入x和y的接口非常简单,使用demo如下: data = { tf.contrib.timeseries.TrainEvalFeatures.TIMES: x, tf.contrib.timeseries.TrainEvalFeatures.VALUES: y, } reader = NumpyReader(data)
我们首先把x和y转为Python中的dict.我们来分析以下上面data的写法。tf.contrib.timeseries.TrainEvalFeatures.TIMES就是一个字符串’times’,而对应tf.contrib.timeseries.TrainEvalFeatures.VALUES也是一个字符串’values’.上面的data定义也可以写成: data = { 'times' : x, 'values': y, }
至于为什么写成上面的那个形式,也是为了配合规范化。 NumpyReader返回的对象有一个read_full()方法,该方法用于从Reader中读取所有的数据,但需要注意的是:read_full()会产生读取队列(这样的处理训练数据的方法和TensorFlow开源的AlexNet网络上对输入数据做增强操作使用的方法类似),这要求我们在使用该方法前,需要先调用tf.train.start_queue_runners启动队列,然后才能读取数据。使用的demo如下: with tf.Session() as sess: full_data = reader.read_full() coord = tf.train.Coordinator() # 创建一个线程协调器 threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 启动线程队列 print('times shape:', full_data['times']) print('values shape:', full_data['values']) print(sess.run(full_data)['times'][0:10]) print(sess.run(full_data)['values'][0:10]) coord.request_stop() ''' 输出: times shape: Tensor('Squeeze_1:0', shape=(1000,), dtype=int64) values shape: Tensor('Squeeze:0', shape=(1000, 1), dtype=float64) [0 1 2 3 4 5 6 7 8 9] [[-0.09581681] [ 0.01284531] [ 0.1107236 ] [ 0.08856841] [ 0.19104294] [ 0.32795446] [ 0.17780316] [ 0.35017529] [ 0.10477021] [ 0.16101822]] '''
通常在训练模型时,我们采需要的是minibatch形式的训练数据,TFTS库提供了tf.contrib.timeseries.RandomWindowInputFn方法用于在reader中随机选取window_size大小的数据组成一组序列数据。demo如下: train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=2, window_size=10) with tf.Session() as sess: batch_data = train_input_fn.create_batch() coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) one_batch = sess.run(batch_data[0]) coord.request_stop() print('one_batch_data:', one_batch) ''' 即一个batch为2组序列数据,每组序列数据有10条数据。 输出: one_batch_data: { 'values': array([[[ 1.21827106], [ 1.37975747], [ 1.15419451], [ 1.07579377], [ 1.19008057], [ 1.32173953], [ 1.2152622 ], [ 1.31092923], [ 1.26184174], [ 1.25915473]], [[ 0.08465949], [-0.0859257 ], [-0.02987006], [ 0.17472125], [ 0.23542243], [ 0.2032668 ], [ 0.07650485], [ 0.20822309], [ 0.30753332], [ 0.16054565]]]), 'times': array([[61, 62, 63, 64, 65, 66, 67, 68, 69, 70], [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])} '''
TFTS从Numpy中读取数据的流程大概操作就是这样了~ 从CSV文件中读入时间序列数据 TFTS还提供了CSVReader用于读取CSV文件。 项目中提供了一个input_input_csv.py文件用于处理csv文件,这里处理的文件是’./data/period_trend.csv’. 这里CSV的文件形式如下(截取): 1,-0.6656603714 2,-0.1164380359 3,0.7398626488 4,0.7368633029 5,0.2289480898 6,2.257073255 7,3.023457405 8,2.481161007 9,3.773638612 10,5.059257738 11,3.553186083 12,4.554486452 13,3.655475698 14,3.419647598 15,4.303376245 16,4.830153934 17,7.253057441 18,5.064802335 19,5.448082106 20,6.251301517 ...
CSV的第一列数据为时间点,第二列数据为对应的观察值。 CSVReader的操作步骤除了读取文件的部分不同,后面的操作和前面的NumpyReader是一样的。操作的demo如下: from __future__ import print_function import tensorflow as tf csv_file_name = './data/period_trend.csv' reader = tf.contrib.timeseries.CSVReader(csv_file_name) with tf.Session() as sess: data = reader.read_full() coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) print(sess.run(data)) coord.request_stop() train_input_fn = tf.contrib.timeseries.RandomWindowInputFn(reader, batch_size=4, window_size=16) with tf.Session() as sess: data = train_input_fn.create_batch() coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) batch1 = sess.run(data[0]) batch2 = sess.run(data[0]) coord.request_stop() print('batch1:', batch1) print('batch2:', batch2) ''' 输出: {'values': array([[ -0.66566038], [ -0.11643804], [ 0.73986262], [ 0.73686332], [ 0.22894809], [ 2.25707316], [ 3.02345729], ... dtype=float32), 'times': array([ 1, 2, 3, 4, 5, 6, ...,500])} batch1: {'values': array([[[ 9.75562382], [ 9.1494894 ], [ 8.94796562], [ 9.1767683 ],dtype=float32), 'times': array([[ 98, 99,...,129]])} batch2: {'values': array([[[ 4.97288084], [ 5.21278238],...,dtype=float32), 'times': array([[ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97],...,226]])} '''
到这里为止,载入数据部分到这里就算结束了。 使用AR模型预测时间序列 AR模型是一种线性预测,即已知N个数据,可由模型推出第N点前面或后面的数据(设推出P点),所以其本质类似于插值,其目的都是为了增加有效数据,只是AR模型是由N点递推,而插值是由两点(或少数几点)去推导多点,所以AR模型要比插值方法效果更好。 代码实现 产生数据 产生数据的方法就是上面介绍的方法。 x = np.array(range(1000)) noise = np.random.uniform(-0.2, 0.2, 1000) y = np.sin(np.pi * x / 100) + x / 200. + noise plt.plot(x, y) plt.savefig('timeseries_y.jpg') data = { tf.contrib.timeseries.TrainEvalFeatures.TIMES: x, tf.contrib.timeseries.TrainEvalFeatures.VALUES: y, } reader = NumpyReader(data) train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=16, window_size=40)
创建ar模型 创建ar模型,我们需要使用tf.contrib.timeseries.ARRegressor类 先看下ARRegressor类 class ARRegressor(_TimeSeriesRegressor): ''' ARRegressor是基于滑窗模型的。这要求输入窗口大小要固定为'input_window_size',输出窗口大小固定为'output_window_size'. 同时这两个参数的和必须等于window_size(满足训练或评估时使用的input_fn)。建议使用'RandomWindowInputFn'(就是上面讲的随机产生batch数据的函数)产生训练或者评估。 ''' def __init__(self, periodicities, input_window_size, output_window_size, num_features, num_time_buckets=10, loss=ar_model.ARModel.NORMAL_LIKELIHOOD_LOSS, hidden_layer_sizes=None, anomaly_prior_probability=None, anomaly_distribution=None, optimizer=None, model_dir=None, config=None): ''' 参数: periodicities: value or a list of values. 输入信号的周期。 input_window_size: 回归时给定的输入数据时间步数. output_window_size: 预测时间步数,建议设置>1. num_features: 时间序列的维度.(数据的观察值) loss: SQUARED_LOSS 或者 NORMAL_LIKELIHOOD_LOSS. hidden_layer_sizes: 默认即可. anomaly_distribution;anomaly_distribution: 默认即可,指定即构成混合模型 optimizer: defaults to Adagrad with step size 0.1. model_dir:模型存储地址.(上面Estimator有讲) config: See `Estimator`. '''
总的来说,需要填的参数有periodicities,input_window_size,output_window_size,num_features,loss。其它的参数默认即可。 这里需要注意的有input_window_size + output_window_size = window_size.(RandomWindowInputFn生成数据里面的window_size).我们在上面的生成数据使用的window_size=40.下面使用的是input_window_size=30, output_window_size=10.就是输入序列30个,预测10个。 num_features即时间序列的维度。就是在一个时间点上观察到的数据维度。我们这里每一步都是一个单独的值,所以num_features=1。 periodicities是信号的周期分量的周期,我们信号的表达式为: y=sin(0.01∗π∗x)+0.005∗x+noise y=sin(0.01∗π∗x)+0.005∗x+noise y的周期分量的frequency为2∗π∗(1/f) 2∗π∗(1/f),故f=200,所以periodicities=200 f=200,所以periodicities=200。 loss的取值现在支持NORMAL_LIKELIHOOD_LOSS和SQUARED_LOSS。 ar = tf.contrib.timeseries.ARRegressor( periodicities=200, input_window_size=30, output_window_size=10, num_features=1, loss=tf.contrib.timeseries.ARModel.NORMAL_LIKELIHOOD_LOSS) ''' (input_window_size=30) + (output_window_size=10) = (window_size=40) '''
训练评估模型并预测 使用train函数传入创建好的数据train_input_fn训练模型即可. ar.train(input_fn=train_input_fn, steps=6000)
接下来就是对模型进行评估,首先我们使用AR模型提供的evaluate函数,这里evaluation的处理是使用训练好的模型在原先的训练集上进行计算,由此我们可以观察到模型的拟合效果. evaluation_input_fn = tf.contrib.timeseries.WholeDatasetInputFn(reader) evaluation = ar.evaluate(input_fn=evaluation_input_fn, steps=1) # keys of evaluation: ['covariance', 'loss', 'mean', 'observed', 'start_tuple', 'times', 'global_step'] # evaluation['covariance']代表协方差 evaluation['loss']代表损失 etc..
如果要理解这里evaluate函数的逻辑,这里AR模型:每次都接收长度为30的输入观测序列,并输出长度为10的预测序列。以此为规则,每次移动步长为1,以此类推,整个训练集长度为1000的序列,最终我们得到970个预测值。 这970个预测值记录在evaluation[‘mean’]中;evaluation还有其他几个键值:evaluation[‘loss’]表示总的损失,evaluation[‘times’]表示evaluation[‘mean’]对应的时间点等等. 评估完模型后,下面该是使用模型了,这里我们会用到predict函数来预测,传入参数为evaluation[‘start_tuple’]会被用于之后的预测中,它相当于最后30步的输出值和对应的时间点。以此为起点(也就是给定观察数据),我们可以对1000步以后的值进行预测,对应的代码为: (predictions,) = tuple(ar.predict( input_fn=tf.contrib.timeseries.predict_continuation_input_fn( evaluation, steps=250)))
这里的代码在1000步之后又像后预测了250个时间点。对应的值就保存在predictions[‘mean’]中。我们可以把观测到的值、模型拟合的值、预测值用下面的代码画出来: plt.figure(figsize=(15, 5)) plt.plot(data['times'].reshape(-1), data['values'].reshape(-1), label='origin') plt.plot(evaluation['times'].reshape(-1), evaluation['mean'].reshape(-1), label='evaluation') plt.plot(predictions['times'].reshape(-1), predictions['mean'].reshape(-1), label='prediction') plt.xlabel('time_step') plt.ylabel('values') plt.legend(loc=4) plt.savefig('predict_result.jpg')
使用LSTM预测单变量时间序列 注意:以下LSTM模型的例子必须使用TensorFlow最新的开发版的源码。具体来说,要保证 from tensorflow.contrib.timeseries.python.timeseries.estimators import TimeSeriesRegressor
可以成功执行。(就是前面说的需要安装最新版的tensorflow) 给出两个用LSTM预测时间序列模型的例子,分别是train_lstm.py和train_lstm_multivariate.py。前者是在LSTM中进行单变量的时间序列预测,后者是使用LSTM进行多变量时间序列预测。为了使用LSTM模型,我们需要先使用TFTS库对其进行定义,定义模型的代码来源于TFTS的示例源码,在train_lstm.py和train_lstm_multivariate.py中分别拷贝了一份。 产生训练数据 这里我们产生的数据公式修改一下 y=sin(π∗0.02∗x)+cos(π∗0.02∗x)+sin(π∗0.04∗x)+noise y=sin(π∗0.02∗x)+cos(π∗0.02∗x)+sin(π∗0.04∗x)+noise 同样用函数加噪声的方法生成一个模拟的时间序列数据: x = np.array(range(1000)) noise = np.random.uniform(-0.2, 0.2, 1000) y = np.sin(np.pi * x / 50 ) + np.cos(np.pi * x / 50) + np.sin(np.pi * x / 25) + noise data = { tf.contrib.timeseries.TrainEvalFeatures.TIMES: x, tf.contrib.timeseries.TrainEvalFeatures.VALUES: y, } ''' plt.plot(x, y) plt.savefig('train_data.jpg') ''' reader = NumpyReader(data) train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=4, window_size=100) # batch_size为4 序列长度为100
产生数据如下: 定义训练模型并预测 这里使用TFTS包内提供的TimeSeriesRegressor模型。其中_LSTMModel来自TFTS包的官方例子。
这里我们使用的模型参数为num_features = 1表示单变量时间序列,即每个时间点上观察到的量只是一个单独的数值。num_units=128表示使用隐层为128大小的LSTM模型。后续的训练,评估,预测和前面讲的代码类似。在以后的1000组数据上,我们向后预测了200组数据。 代码如下: estimator = ts_estimators.TimeSeriesRegressor( model=_LSTMModel(num_features=1, num_units=128), optimizer=tf.train.AdamOptimizer(0.001)) estimator.train(input_fn=train_input_fn, steps=2000) evaluation_input_fn = tf.contrib.timeseries.WholeDatasetInputFn(reader) evaluation = estimator.evaluate(input_fn=evaluation_input_fn, steps=1) # Predict starting after the evaluation 预测后续的200组数据 (predictions,) = tuple(estimator.predict( input_fn=tf.contrib.timeseries.predict_continuation_input_fn( evaluation, steps=200)))
绘制预测数据图 observed_times = evaluation['times'][0] observed = evaluation['observed'][0, :, :] evaluated_times = evaluation['times'][0] evaluated = evaluation['mean'][0] predicted_times = predictions['times'] predicted = predictions['mean'] plt.figure(figsize=(15, 5)) plt.axvline(999, linestyle='dotted', linewidth=4, color='r') observed_lines = plt.plot(observed_times, observed, label='observation', color='k') evaluated_lines = plt.plot(evaluated_times, evaluated, label='evaluation', color='g') predicted_lines = plt.plot(predicted_times, predicted, label='prediction', color='r') plt.legend(handles=[observed_lines[0], evaluated_lines[0], predicted_lines[0]], loc='upper left') plt.savefig('predict_result.jpg')
使用LSTM预测多变量时间序列 与上面的使用LSTM预测单变量时间序列不同的地方在于数据的读取和模型的预测量。使用原理实质上是一致的。 获取训练数据 所谓多变量时间序列,就是指在每个时间点上的观测量有多个值。在data/multivariate_periods.csv文件中,保存了一个多变量时间序列的数据:(下面是截取) 0,0.926906299771,1.99107237682,2.56546245685,3.07914768197,4.04839057867 1,0.108010001864,1.41645361423,2.1686839775,2.94963962176,4.1263503303 2,-0.800567600028,1.0172132907,1.96434754116,2.99885333086,4.04300485864 3,0.0607042871898,0.719540073421,1.9765012584,2.89265588817,4.0951014426 4,0.933712200629,0.28052120776,1.41018552514,2.69232603996,4.06481164223 5,-0.171730652974,0.260054421028,1.48770816369,2.62199129293,4.44572807842 6,-1.00180162933,0.333045158863,1.50006392277,2.88888309683,4.24755865606 7,0.0580061875336,0.688929398826,1.56543458772,2.99840358953,4.52726873347 8,0.764139447412,1.24704875327,1.77649279698,3.13578593851,4.63238922951 9,-0.230331874785,1.47903998963,2.03547545751,3.20624030377,4.77980005228 10,-1.03846045211,2.01133000781,2.31977503972,3.67951536251,5.09716775897 11,0.188643592253,2.23285349038,2.68338482249,3.49817168611,5.24928239634 12,0.91207302309,2.24244446841,2.71362604985,3.96332587625,5.37802271594 13,-0.296588665881,2.02594634141,3.07733910479,3.99698324956,5.56365901394 14,-0.959961476551,1.45078629833,3.18996420137,4.3763059609,5.65356015609 15,0.46313530679,1.01141441548,3.4980215948,4.20224896882,5.88842247449 16,0.929354125798,0.626635305936,3.70508262244,4.51791573544,5.73945973251
即每个时间步上能观察到多个数据变量(这里有5组数据)。举个简单的例子:如果现在我在跑步,每个时间步上,可以获取到我的心跳,血压,体温。这就是在每个时间步上能观察到3个数据变量。 下面依旧是使用CSVReader处理数据,区别在column_names参数,该参数告诉CSVReader那些变量是对应的时间步和变量。 csv_file_name = path.join('./data/multivariate_periods.csv') reader = tf.contrib.timeseries.CSVReader( csv_file_name, column_names=((tf.contrib.timeseries.TrainEvalFeatures.TIMES,) + (tf.contrib.timeseries.TrainEvalFeatures.VALUES,) * 5)) train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=4, window_size=32)
定义训练模型并预测 这里与上面的程序不同的地方在于_LSTMModel中参数num_features=5.即能观察的数据量维度为5.本次向后预测的数据为100组。(训练数据100组) estimator = ts_estimators.TimeSeriesRegressor( model=_LSTMModel(num_features=5, num_units=128), optimizer=tf.train.AdamOptimizer(0.001)) estimator.train(input_fn=train_input_fn, steps=200) evaluation_input_fn = tf.contrib.timeseries.WholeDatasetInputFn(reader) evaluation = estimator.evaluate(input_fn=evaluation_input_fn, steps=1) # Predict starting after the evaluation (predictions,) = tuple(estimator.predict( input_fn=tf.contrib.timeseries.predict_continuation_input_fn( evaluation, steps=100)))
绘制预测图 observed_times = evaluation['times'][0] observed = evaluation['observed'][0, :, :] evaluated_times = evaluation['times'][0] evaluated = evaluation['mean'][0] predicted_times = predictions['times'] predicted = predictions['mean'] plt.figure(figsize=(15, 5)) plt.axvline(99, linestyle='dotted', linewidth=4, color='r') observed_lines = plt.plot(observed_times, observed, label='observation', color='k') evaluated_lines = plt.plot(evaluated_times, evaluated, label='evaluation', color='g') predicted_lines = plt.plot(predicted_times, predicted, label='prediction', color='r') plt.legend(handles=[observed_lines[0], evaluated_lines[0], predicted_lines[0]], loc='upper left') plt.savefig('predict_result.jpg')
总结TFTS是Tensorflow官方提供的基于LSTM模型的时序预测工具,可以用于常见的时序模型上(替代HMM)。这里讲了如果使用TFTS模型读取数据并产生训练数据,同时讲了如果使用TFTS模块自带的AR和LSTM模型。 |
|
来自: 昵称5fg62 > 《智能金融 0A - 金融市场预测》