RNN回归预测
一:问题概述
输入一条sin曲线,预测一条cos曲线。
二:代码实现
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
BATCH_START=0
TIME_STEPS=20
BATCH_SIZE=50
INPUT_SIZE=1
OUTPUT_SIZE=1
CELL_SIZE=10
LR=0.006
def get_batch():
global BATCH_START,TIME_STEPS
#xs shape(50batchs,20steps)
xs=np.arange(BATCH_START,BATCH_START+TIME_STEPS*BATCH_SIZE).reshape((BATCH_SIZE,TIME_STEPS))/(10*np.pi)
seq=np.sin(xs)
res=np.cos(xs)
BATCH_START+=TIME_STEPS
#plt.plot(xs[0,:],res[0,:],'r',xs[0,:],'b--')
#plt.show()
#returned seq,res and shape(batch,step,input)
return [seq[:,:,np.newaxis],res[:,:,np.newaxis],xs]
class LSTMRNN(object):
def __init__(self,n_steps,input_size,output_size,cell_size,batch_size):
self.n_steps=n_steps
self.input_size=input_size
self.output_size=output_size
self.cell_size=cell_size
self.batch_size=batch_size
with tf.name_scope('inputs'):
self.xs=tf.placeholder(tf.float32,[None,n_steps,input_size],name='xs')
self.ys=tf.placeholder(tf.float32,[None,n_steps,output_size],name='ys')
with tf.variable_scope('in_hidden'):
self.add_input_layer()
with tf.variable_scope('LSTM_cell'):
self.add_cell()
with tf.variable_scope('out_hidden'):
self.add_output_layer()
with tf.name_scope('cost'):
self.compute_cost()
with tf.name_scope('train'):
self.train_op=tf.train.AdamOptimizer(LR).minimize(self.cost)
def add_input_layer(self,):
#layer_in_x:(batch*n_steps,input_size)
l_in_x=tf.reshape(self.xs,[-1,self.input_size],name='2_2D')
#Weights:(in_size,cell_size)
Ws_in=self._weight_variable([self.input_size,self.cell_size])
#bias:(cell_size,)
bs_in=self._bias_variable([self.cell_size,])
#layer_in_y:(batch*n_steps,cell_size)
with tf.name_scope('Wx_plus_b'):
l_in_y=tf.matmul(l_in_x,Ws_in)+bs_in
#reshape l_in_y -->(batchmn_steps,cell_size)
self.l_in_y=tf.reshape(l_in_y,[-1,self.n_steps,self.cell_size],name='2-3D')
def add_cell(self):
lstm_cell=tf.contrib.rnn.BasicLSTMCell(self.cell_size,forget_bias=1.0,state_is_tuple=True)
with tf.name_scope('initial_state'):
self.cell_init_state=lstm_cell.zero_state(self.batch_size,dtype=tf.float32)
self.cell_outputs,self.cell_final_state=tf.nn.dynamic_rnn(
lstm_cell,self.l_in_y,initial_state=self.cell_init_state,time_major=False)
def add_output_layer(self):
#shape=(batch*steps,cell_size)
l_out_x=tf.reshape(self.cell_outputs,[-1,self.cell_size],name='2-2D')
Ws_out=self._weight_variable([self.cell_size,self.output_size])
bs_out=self._bias_variable([self.output_size,])
#shape=(batch*steps,output_size)
with tf.name_scope('Wx_plus_b'):
self.pred=tf.matmul(l_out_x,Ws_out)+bs_out
def compute_cost(self):
losses=tf.contrib.legacy_seq2seq.sequence_loss_by_example(
[tf.reshape(self.pred,[-1],name='reshape_pred')],
[tf.reshape(self.ys,[-1],name='reshape_target')],
[tf.ones([self.batch_size*self.n_steps],dtype=tf.float32)],
average_across_timesteps=True,
softmax_loss_function=self.ms_error,
name='losses'
)
with tf.name_scope('average_cost'):
self.cost=tf.div(
tf.reduce_sum(losses,name='losses_sum'),
self.batch_size,
name='average_cost')
tf.summary.scalar('cost',self.cost)
@staticmethod
def ms_error(labels,logits):
return tf.square(tf.subtract(labels,logits))
def _weight_variable(self,shape,name='weights'):
initializer=tf.random_normal_initializer(mean=0.,stddev=1.,)
return tf.get_variable(shape=shape,initializer=initializer,name=name)
def _bias_variable(self,shape,name='biases'):
initializer=tf.constant_initializer(0.1)
return tf.get_variable(name=name,shape=shape,initializer=initializer)
if __name__ == '__main__':
model=LSTMRNN(TIME_STEPS,INPUT_SIZE,OUTPUT_SIZE,CELL_SIZE,BATCH_SIZE)
sess=tf.Session()
merged=tf.summary.merge_all()
writer=tf.summary.FileWriter("logs",sess.graph)
#relocate to the local dir and run this line to view it on Chrome(http://0.0.0.0:6006/):
#$tensorboard --logdir='logs'
sess.run(tf.global_variables_initializer())
plt.ion()
plt.show()
for i in range(200):
seq,res,xs=get_batch()
if i==0:
feed_dict={
model.xs:seq,
model.ys:res,
}
else:
feed_dict={
model.xs:seq,
model.ys:res,
model.cell_init_state:state
}
_,cost,state,pred=sess.run(
[model.train_op,model.cost,model.cell_final_state,model.pred],
feed_dict=feed_dict)
plt.plot(xs[0,:],res[0].flatten(),'r',xs[0,:],pred.flatten()[:TIME_STEPS],'b--')
plt.ylim((-1.2,1.2))
plt.draw()
plt.pause(0.3)
if i%20==0:
print('cost:',round(cost,4))
result=sess.run(merged,feed_dict)
writer.add_summary(result,i)
三:代码可视化
1. 打开cmd调用tensorboard
(base) C:\Users\000>activate tensorflow
(tensorflow) C:\Users\000>e:
(tensorflow) E:\>cd logs文件所在路径
(tensorflow) E:\logs文件所在路径>tensorboard --logdir=logs
Starting TensorBoard b'54' at http://0.0.0.0:6006
(Press CTRL+C to quit)
2. 输入上述网址 http://0.0.0.0:6006
打开GRAPHS,整体如下
3. 输入input
xs: sin函数
ys: cos函数,标准值,用于计算损失
4. 隐藏层输入in_hidden
(1)将xs转为二维数据
(2)乘以权重Ws_in
(3)加上偏置bs_in
(4)将计算结果Wx_plus_b转为3维
5. LSTM层
(1)使用BasicLSTMCell
(2)定义initial_state初始状态
(3)使用dynamic_rnn,进行循环
6. 隐藏层输出out_hidden
(1)将LSTM处理完的输出转为2D
(2)乘以权重Ws_out
(3)加上偏置bs_out
(4)得到第一次循环的输出预测值
(4)更新状态:initial_state更新为final_state
7.计算损失值cost
(1)使用tf.contrib.legacy_seq2seq.sequence_loss_by_example函数计算交叉熵losses
(2)因为上一步求得的losses值为每一个序列batch的值,所以求和后再取平均值,得到cost
四:运行结果
1. cost损失值
cost: 42.0495
cost: 7.3446
cost: 2.3511
cost: 0.4777
cost: 1.4825
cost: 0.6004
cost: 0.1342
cost: 0.263
cost: 1.7159
cost: 0.2112
2. 实时预测过程
红线:ys,cos函数
蓝线:预测值
可看到,随着训练,最后两线拟合。