最近比较空闲,刚好学习下Tensorflow和python,于是想写一个Tensorflow的小应用。
时间序列预测在预估企业营收,指标等方面使用的非常多。以前用R写过一个shiny的应用,就是用指数平滑、stl分解等方法做时间序列预测。RNN也是很早之前就接触过理论,是用来处理序列数据的利器。放一个普通RNN的示意图:
可以看到,t时刻RNN单元的输出是由t-1时刻单元的输出St-1和t时刻的训练数据xt共同决定的,用公式表示就是St=f(U*Xt+W*S(t−1))
现在比较常用的RNN单元是LSTM、GRU这些,上面那个原始的RNN使用不太多。为什么呢?
从直观的理解来看:1,原始的RNN记忆容量有限,随着时间间隔不断增大时,RNN会丧失学习到远处单元信息的能力。2,原始RNN是全盘接受了输入的信息,但有的信息可能是无用的。于是针对原始RNN的缺点发展出了LSTM——长短期记忆网络。先放一张它的结构示意图:
通常把LSTM单元成为细胞。LSTM使用”门“来选择性的让信息通过,遗忘或增加到细胞状态。还增加了长期记忆机制,就是图中细胞上面的那条横线。LSTM具体的工作原理可以参考这个讲的很详细点击打开链接。
Tensorflow中使用的需要关注的是LSTM的输入输出。输入就是训练数据(x,y)。LSTM的输出有两个h、c。h是真正的输出状态用来做后续的预测等等,c是细胞的记忆状态。
不说太多理论,直接上代码吧。这边训练数据使用的sin函数产生1000个点,time_step=5
1, 生成训练数据
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.contrib import layers as tflayers
def generator(x):
return [np.sin(i*0.06) for i in range(x)]
def rnn_data_format(data,timestep=7,label=False):
data=pd.DataFrame(data)
rnn_data=[]
if label: ###label是二维数组,[样本数,1]
for i in range(len(data) - timestep):
rnn_data.append([x for x in data.iloc[i+timestep].as_matrix()])
else: ###样本是3维数组[样本数,time_step,1]
for i in range(len(data) - timestep):
rnn_data.append([x for x in data.iloc[i:(i+timestep)].as_matrix()])
return np.array(rnn_data,dtype=np.float32)
class DataSet(object):
def __init__(self, x,y):
self._data_size = len(x)
self._epochs_completed = 0
self._index_in_epoch = 0
self._data_index = np.arange(len(x))
self.x=x
self.y=y
def next_batch(self,batch_size):
start=self._index_in_epoch
if start+batch_size>=self._data_size :
np.random.shuffle(self._data_index)
self._index_in_epoch=0
start=self._index_in_epoch
end=self._index_in_epoch+batch_size
self._index_in_epoch=end
else:
end = self._index_in_epoch + batch_size
self._index_in_epoch = end
batch_x,batch_y=self.get_data(start,end)
return np.array(batch_x,dtype=np.float32),np.array(batch_y,dtype=np.float32)
def get_data(self,start,end):
batch_x=[]
batch_y=[]
for i in range(start,end):
batch_x.append(self.x[self._data_index[i]])
batch_y.append(self.y[self._data_index[i]])
return batch_x,batch_y
##生成数据
x=generator(1000)
X=rnn_data_format(x,5)
y=rnn_data_format(x,5,label=True)
trainds = DataSet(X,y)
上面的代码用来生产训练数据,用sin函数生成了1000个数据点。rnn_data_format是为了生成[time_step, input]维度的数据。这里吧time_step设为5。因此可知,X的每一个样本是shape为[5,1]的矩阵,用来预测y,y的每一个样本shape为[1,1]。