我们在上一篇文章中讲了怎样用Estimator构建CNN的模型,这篇文章主要是怎样用Estimator构建RNN模型,对应《TensorFlow机器学习项目实战》7.2, 单变量时间序列预测。这应该是本系列的最后一篇了。
我们在上一篇文章中讲了怎样用Estimator构建CNN的模型,这篇文章主要是怎样用Estimator构建RNN模型,对应《TensorFlow机器学习项目实战》7.2, 单变量时间序列预测。这应该是本系列的最后一篇了。
事实上,在TensorFlow 1.4下已经update了time series的库,如果用那个会方便很多。但是因为我们是基于《TensorFlow机器学习项目实战》来做,所以我们尽量保持代码一致。而且这样也能让我们更好的学习RNN和LSTM。
在[1]中,有update过的sine函数预测的例子,但是例子依然使用的是learn。而且还用了SKCompat来warp现在的Estimator。在TensorFlow的文档中有说这种方式会被砍掉。所以我们还是直接使用最新的Estimator接口。其实差别很小,最大的差别还是input函数,而在前两篇文章中,我们已经重点介绍了这个功能,相信你看这段代码能够很容易看懂。
另外一个主要参考对象就是tensorflow的官方例子[2]。这个例子主要是文本分类的,我们主要要将其分类问题换成回归问题,难度也不大。
跟前两篇文章相同,本文尽量小的改动作者的代码,使得代码可以良好运行。
完整代码如下:
import numpy as np import pandas as pd import tensorflow as tf from tensorflow.contrib import rnn from matplotlib import pyplot as plt TIMESTEPS = 5 DENSE_LAYERS = None TRAINING_STEPS = 10000 BATCH_SIZE = 128 PRINT_STEPS = TRAINING_STEPS / 100 learning_rate=0.03 X_FEATURE='x' def lstm_model(mode, features, labels, params): def lstm_cells( ): #我为了方便只是简单的堆积了两层 return [rnn.BasicLSTMCell(TIMESTEPS, state_is_tuple=True) for _ in range(2)] def dnn_layers(input_layers, layers): return input_layers def _lstm_model(features, mode,labels): stacked_lstm = rnn.MultiRNNCell(lstm_cells(), state_is_tuple=True) X=features[X_FEATURE]; x_ = tf.unstack(X, num=TIMESTEPS, axis=1) output, layers = rnn.static_rnn(stacked_lstm, x_, dtype=np.float32) output = dnn_layers(output[-1], []) predictions=tf.layers.dense(output,1) #我本来想用自带的model.linear_regression,但是在predict的时候总出错 #return learn.models.linear_regression(output, y) # Provide an estimator spec for `ModeKeys.PREDICT`. if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec( mode=mode, predictions={"elec": predictions}) # Calculate loss using mean squared error loss = tf.losses.mean_squared_error(labels, predictions) #此处选用GD做优化器 optimizer = tf.train.GradientDescentOptimizer( learning_rate=learning_rate) train_op = optimizer.minimize( loss=loss, global_step=tf.train.get_global_step()) # Calculate root mean squared error as additional eval metric eval_metric_ops = { "accuracy": tf.metrics.root_mean_squared_error( tf.cast(labels, tf.float32), predictions) } #Provide an estimator spec for `ModeKeys.EVAL` and `ModeKeys.TRAIN` modes. return tf.estimator.EstimatorSpec( mode=mode, loss=loss, train_op=train_op, eval_metric_ops=eval_metric_ops) return _lstm_model(features, mode,labels) df = pd.read_csv("data/elec_load.csv", error_bad_lines=False) print( df.describe()) array=(df.values- 147.0) /339.0 listX = [] listy = [] X={} y={} for i in range(0,len(array)-TIMESTEPS): listX.append(array[i:i+TIMESTEPS].reshape([TIMESTEPS,1])) #作者好像有点理解错了,索引取值冒号后面是不包含的 listy.append(array[i+TIMESTEPS]) arrayX=np.array(listX).astype(np.float32) arrayy=np.array(listy).astype(np.float32) X['train']=arrayX[0:12000] X['test']=arrayX[12000:13000] X['val']=arrayX[13000:14000] y['train']=arrayy[0:12000] y['test']=arrayy[12000:13000] y['val']=arrayy[13000:14000] train_input_fn = tf.estimator.inputs.numpy_input_fn( x={X_FEATURE: X['train']}, y=y['train'], batch_size=100, num_epochs=30, shuffle=True) test_input_fn = tf.estimator.inputs.numpy_input_fn( x={X_FEATURE: X['test']}, # y=y['test'], num_epochs=1, batch_size=100, shuffle=False) eva_input_fn = tf.estimator.inputs.numpy_input_fn( x={X_FEATURE: X['val']}, y=y['val'], num_epochs=1, shuffle=False) regressor=tf.estimator.Estimator(model_fn=lstm_model) regressor.train(input_fn=train_input_fn) score =regressor.evaluate(input_fn=eva_input_fn) print ('Accuracy: {0:f}'.format(score['accuracy'])) predictions=regressor.predict(input_fn=test_input_fn) predicted=np.zeros(y['test'].shape,dtype=np.float32) for i, p in enumerate(predictions): predicted[i]=p['elec'] plt.subplot() plot_predicted, = plt.plot(predicted, label='predicted') plot_test, = plt.plot(y['test'], label='test') plt.legend(handles=[plot_predicted, plot_test])
结果如图,欢迎讨论
reference
[3] 时间序列接口