Python LSTM网络的训练与不同起点的预测

Python LSTM网络的训练与不同起点的预测,python,tensorflow,lstm,Python,Tensorflow,Lstm,这是使用张量流的LSTM单元的一个简单示例。我正在生成一个正弦波,并对我的网络进行十个周期的训练,我试图预测第十一个周期。预测值X是真实y的一个历元滞后。培训结束后,我将会话保存到磁盘,并在预测时恢复会话-这是典型的培训和将模型部署到生产中 当我预测最后一个周期时,y_预测的与真实的y非常匹配 如果我尝试使用任意起点预测正弦波(即取消注释第114行) 测试数据=测试数据[16:] 因此,y的真值将移动四分之一个周期,似乎LSTM预测仍然从零开始,需要几个时代才能赶上真值,最终与之前的预测相匹配。

这是使用张量流的LSTM单元的一个简单示例。我正在生成一个正弦波,并对我的网络进行十个周期的训练,我试图预测第十一个周期。预测值X是真实y的一个历元滞后。培训结束后,我将会话保存到磁盘,并在预测时恢复会话-这是典型的培训和将模型部署到生产中

当我预测最后一个周期时,y_预测的与真实的y非常匹配

如果我尝试使用任意起点预测正弦波(即取消注释第114行) 测试数据=测试数据[16:] 因此,y的真值将移动四分之一个周期,似乎LSTM预测仍然从零开始,需要几个时代才能赶上真值,最终与之前的预测相匹配。事实上,第二种情况下的预测似乎仍然是一个完整的正弦波,而不是3/4波

发生这种情况的原因是什么。如果我实现了一个回归器,我想从任何一点开始使用它

导入操作系统
作为pd进口熊猫
将numpy作为np导入
导入tensorflow作为tf
将tensorflow.contrib.rnn作为rnn导入
def sin_信号():
'''
生成sin函数
这列火车有十节
测试集是一个额外的周期
返回变量为熊猫格式,便于打印
'''
相位=np.arange(0,2*np.pi*11,0.1)
y=np.sin(相位)
data=pd.DataFrame.from_dict({'phase':phase,'y':y})
#用0填充最后一个元素-无论如何,这是周期的结束
数据['X']=data.y.shift(-1).fillna(0.0)
列车数据=数据[data.phase2*np.pi*10].copy()
返回列车数据、测试数据
类lstm_model():
定义初始值(self,size\u x,size\u y,num\u单位=32,num\u层=3,keep\u prob=0.5):
#def单_装置():
#返回rnn.DropOutRapper(
#rnn.LSTMCell(num\u单位),输出保持概率=保持概率)
def单_装置():
返回rnn.LSTMCell(数量单位)
self.graph=tf.graph()
使用self.graph.as_default():
“输入占位符”
self.X=tf.placeholder(tf.float32,[None,size\ux],name='X')
self.y=tf.placeholder(tf.float32,[None,size\u y],name='y')
“网络”
cell=rnn.multirncell([single_unit()表示范围内的u(num_层)])
X=tf.expand_dims(self.X,-1)
val,state=tf.nn.dynamic(cell,X,time\u major=True,dtype=tf.float32)
val=tf.transpose(val[1,0,2])
last=tf.gather(val,int(val.get_shape()[0])-1)
权重=tf.Variable(tf.truncated\u normal([num\u units,size\u y],0.0,1.0),name='weights')
bias=tf.Variable(tf.zeros(size_y),name='bias')
预测的y=tf.nn.xw\u加上b(最后,权重,偏差,name='predicted\u y')
“优化器”
优化器=tf.train.AdamOptimizer(name='adam\u optimizer')
全局步骤=tf.Variable(0,trainable=False,name='global\u步骤')
self.loss=tf.reduce_mean(tf.squared_差(预测的,self.y),name='mse_loss')
self.train\u op=optimizer.minimize(self.loss,global\u step=global\u step,name='training\u op')
“初始值设定项”
self.init_op=tf.global_variables_initializer()
类lstm_回归器():
定义初始化(自):
如果不是os.path.isdir('./检查“):
os.mkdir('./检查')
@静力学方法
def get_形状(数据帧):
df_shape=dataframe.shape
num_rows=df_形状[0]

num_cols=1如果len(df_shape)我怀疑,由于您在未来的任意起点开始预测,您的模型训练的内容和预测的开始内容之间存在值差距,并且LSTM的状态没有用该差距中的值更新

***更新:

在代码中,您有以下内容:

val, state = tf.nn.dynamic_rnn(cell, X, time_major=True, dtype=tf.float32)
然后在培训过程中:

_, loss = sess.run([model.train_op, model.loss], feed_dict=feed_dict)
我建议将初始状态输入到
dynamic\n
中,并在每次训练迭代时重新输入更新后的状态,如下所示:

inState = tf.placeholder(tf.float32, [YOUR_DIMENSIONS], name='inState')
val, state = tf.nn.dynamic_rnn(cell, X, time_major=True, dtype=tf.float32, initial_state=inState)
在培训期间:

iState = np.zeros([YOUR_DIMENSIONS])
feed_dict={
                model.X: X_train.values.reshape(-1, size_x),
                model.y: y_train.values.reshape(-1, size_y),
inState: iState # feed initial value for state placeholder
            }
_, loss, oState = sess.run([model.train_op, model.loss, model.state], feed_dict=feed_dict) # run one additional variable from the session
iState = oState # assign latest out-state to be re-fed as in-state
因此,通过这种方式,您的模型不仅可以在训练期间学习参数,还可以跟踪在该状态下训练期间看到的所有内容。现在,将此状态与会话的其余部分一起保存,并在预测阶段使用它

这方面的一个小困难是,从技术上讲,这个状态是一个占位符,因此根据我的经验,它不会自动保存在图形中。因此,您可以在培训结束时手动创建另一个变量,并为其指定状态;通过这种方式,它将保存在图形中,以供以后使用:

# make sure this variable is declared BEFORE the saver is declared
savedState = tf.get_variable('savedState', shape=[YOUR_DIMENSIONS])
# then, at the end of training:
    assignOp = tf.assign(savedState, oState)
    sess.run(assignOp)
# now save your graph
所以现在,一旦你恢复了图形,如果你想在一些人工间隙之后开始你的预测,那么你仍然需要运行你的模型通过这个间隙来更新状态。在我的例子中,我只是对整个间隙运行一个虚拟预测,只是为了更新状态,然后从这里开始以正常的间隔继续


希望这有帮助……

我相信情况也是如此。如何更新状态?我在您的代码中注意到,通常情况下,您在培训时没有传递状态(即,没有将状态从当前迭代步骤重新输入到下一个迭代步骤)。这是故意的吗?如果没有,让我在答案中粘贴几行,因为这里没有足够的空间……这不是故意的,我只是张量流中的一个noob.:)我们不是都…)我用一些建议更新了答案。如果需要澄清某些事情,请在此处发布…如何初始化MultiRNNCell?状态是一个元组,但占位符是张量。你需要重塑吗?