Python 如何在Keras中使用reset_状态(states)功能?

Python 如何在Keras中使用reset_状态(states)功能?,python,deep-learning,keras,lstm,rnn,Python,Deep Learning,Keras,Lstm,Rnn,我试图在训练每个批次之前设置LSTM内部状态。 我正在分享我的测试代码和发现,希望找到答案,并帮助解决类似问题的其他人 特别是,对于每个数据,我都有一个特征X(不会随时间变化)和一个序列p=p1,p2,p3,。。。第30页。 目标是:给定X和p1,p2,p3预测p4,p5。。第30页 为此,我想用X初始化LSTM的隐藏状态,正如在一些工作中所做的那样(例如neuraltalk),然后LSTM必须与p1、p2、p3相匹配,以预测p4、…、p30。 每次批处理之前都需要进行初始化(batch_siz

我试图在训练每个批次之前设置LSTM内部状态。 我正在分享我的测试代码和发现,希望找到答案,并帮助解决类似问题的其他人

特别是,对于每个数据,我都有一个特征X(不会随时间变化)和一个序列p=p1,p2,p3,。。。第30页。 目标是:给定X和p1,p2,p3预测p4,p5。。第30页

为此,我想用X初始化LSTM的隐藏状态,正如在一些工作中所做的那样(例如neuraltalk),然后LSTM必须与p1、p2、p3相匹配,以预测p4、…、p30。 每次批处理之前都需要进行初始化(batch_size=1),因此我需要控制LSTM状态初始化。 考虑到这个问题,我已经测试了以下代码:

首先,我在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.]]
好的,我已经成功地用所有1和所有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.]]
但是,如果我想检查状态是否已初始化,我会找到以前的初始化值(全部一个,全部两个)

这里到底发生了什么?为什么函数似乎根据打印工作,但不更改内部状态的值?

正如您所读到的,value参数设置了一个值,通过该值可以初始化变量。因此,当您调用
tf.global\u variables\u initializer().run()
时,您的状态将使用此处定义的值进行初始化:

new_h = K.variable(value=np.ones((1, 10)))
new_c = K.variable(value=np.ones((1, 10))+1)
编辑:

这对我来说似乎很明显,但我将再次解释为什么
reset\u states
不起作用

  • 变量定义:当您将内部状态定义为由某个值初始化的变量时,每次调用
    Variable\u initializer
    时,都会设置该特定值

  • 重置状态:它将更新此变量的当前值,但不会更改初始值设定项的默认值。为了做到这一点,您需要通过将给定状态设置为默认值的另一个变量重新分配此状态


  • 好的,但这并不能解释当我使用reset_states函数mmm时会发生什么。。我仍然不清楚如何通过reset_states函数使用第二种方法设置状态您的主要目标是什么?我在问题中解释过,我想在使用上下文向量(即与该批次的输入序列相关的功能)训练每个批次之前重置状态然后,您应该只在开始时初始化变量一次,并在每个批次之前使用
    reset\u states
    new_h = K.variable(value=np.ones((1, 10)))
    new_c = K.variable(value=np.ones((1, 10))+1)