我正在尝试在训练每个批次之前设置LSTM内部状态。 我正在分享我的测试代码和发现,希望找到答案并帮助解决类似问题的其他人。
特别地,对于每个数据,我具有特征X(其不随时间改变)和序列P = p1,p2,p3,... p30。 目标是:给定X和p1,p2,p3预测p4,p5,.. p30。
为了达到这个目的,我想用X来初始化LSTM的隐藏状态,就像在几个工作中所做的那样(例如,神经元),然后LSTM必须与p1,p2,p3拟合以预测p4,... ,P30。 在每个批处理(batch_size = 1)之前需要进行初始化,因此我需要控制LSTM状态初始化。 仔细考虑这个问题Initializing LSTM hidden state Tensorflow/Keras我测试了以下代码:
首先,我在recurrent.py中定义的reset_states()函数中添加了一些打印件,以便了解究竟发生了什么。
def reset_states(self, states=None):
if not self.stateful:
raise AttributeError('Layer must be stateful.')
batch_size = self.input_spec[0].shape[0]
if not batch_size:
raise ValueError('If a RNN is stateful, it needs to know '
'its batch size. Specify the batch size '
'of your input tensors: \n'
'- If using a Sequential model, '
'specify the batch size by passing '
'a `batch_input_shape` '
'argument to your first layer.\n'
'- If using the functional API, specify '
'the time dimension by passing a '
'`batch_shape` argument to your Input layer.')
# initialize state if None
if self.states[0] is None:
self.states = [K.zeros((batch_size, self.units))
for _ in self.states]
print "reset states A (all zeros)"
elif states is None:
for state in self.states:
K.set_value(state, np.zeros((batch_size, self.units)))
print "reset states B (all zeros)"
else:
if not isinstance(states, (list, tuple)):
states = [states]
print "reset states C (list or tuple copying)"
if len(states) != len(self.states):
raise ValueError('Layer ' + self.name + ' expects ' +
str(len(self.states)) + ' states, '
'but it received ' + str(len(states)) +
' state values. Input received: ' +
str(states))
for index, (value, state) in enumerate(zip(states, self.states)):
if value.shape != (batch_size, self.units):
raise ValueError('State ' + str(index) +
' is incompatible with layer ' +
self.name + ': expected shape=' +
str((batch_size, self.units)) +
', found shape=' + str(value.shape))
K.set_value(state, value)
print "reset states D (set values)"
print value
print "\n"
这是测试代码:
import tensorflow as tf
from keras.layers import LSTM
from keras.layers import Input
from keras.models import Model
import numpy as np
import keras.backend as K
input = Input(batch_shape=(1,3,1))
lstm_layer = LSTM(10,stateful=True)(input)
>>> reset states A (all zeros)
如您所见,第一次打印是在创建lstm图层时执行的
model = Model(input,lstm_layer)
model.compile(optimizer="adam", loss="mse")
with tf.Session() as sess:
tf.global_variables_initializer().run()
h = sess.run(model.layers[1].states[0])
c = sess.run(model.layers[1].states[1])
print h
>>> [[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]
print c
>>> [[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]
内部状态已设置为全零。 作为替代方案,可以使用函数reset_states()
model.layers[1].reset_states()
>>> reset states B (all zeros)
在这种情况下打印了第二条消息。一切似乎都正常。 现在我想用任意值设置状态。
new_h = K.variable(value=np.ones((1, 10)))
new_c = K.variable(value=np.ones((1, 10))+1)
model.layers[1].states[0] = new_h
model.layers[1].states[1] = new_c
with tf.Session() as sess:
tf.global_variables_initializer().run()
h = sess.run(model.layers[1].states[0])
c = sess.run(model.layers[1].states[1])
print h
>>> [[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]
print c
>>> [[ 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]]
好的,我已经用我的所有一个和所有两个向量成功设置了两个隐藏状态。 但是,值得利用类函数reset_states(),它将状态作为输入。 该函数利用函数K.set_values(x,values),它期望'values'是一个numpy数组。
new_h_5 = np.zeros((1,10))+5
new_c_24 = np.zeros((1,10))+24
model.layers[1].reset_states([new_h_5,new_c_24])
它似乎有效,确实输出是:
>>> reset states D (set values)
>>> [[ 5. 5. 5. 5. 5. 5. 5. 5. 5. 5.]]
>>>
>>>
>>>
>>>
>>> reset states D (set values)
>>> [[ 24. 24. 24. 24. 24. 24. 24. 24. 24. 24.]]
但是,如果我想检查状态是否已初始化,我会找到先前的初始化值(全部为1,全部为两个)。
with tf.Session() as sess:
tf.global_variables_initializer().run()
hh = sess.run(model.layers[1].states[0])
cc = sess.run(model.layers[1].states[1])
print hh
>>> [[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]
print cc
>>> [[ 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]]
这里到底发生了什么?为什么函数似乎根据打印工作但不改变内部状态的值?
答案 0 :(得分:2)
正如您可能阅读here,value参数设置一个值,通过该值可以初始化变量。因此,当您致电tf.global_variables_initializer().run()
时,您的状态会使用此处定义的值进行初始化:
new_h = K.variable(value=np.ones((1, 10)))
new_c = K.variable(value=np.ones((1, 10))+1)
修改强>
对我来说这似乎很明显,但我会再次解释为什么reset_states
无效。
变量定义:当您将内部状态定义为由某个值初始化的变量时,每次调用variable_initializer
时都会设置此特定的vaklue。
重置状态:它将更新此变量的当前值,但不会更改初始化程序的默认值。为了做到这一点,你需要通过另一个变量将这些状态重新分配给定状态设置为默认值。