如何在 Keras 中使用 reset_states(states) 函数?

How to use reset_states(states) function in Keras?

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

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

为了这个目标,我想用 X 初始化 LSTM 的隐藏状态,就像在几个作品(例如,neuraltalk)中所做的那样,然后 LSTM 必须与 p1、p2、p3 相匹配才能预测 p4, ..,第 30 页。 在每批 (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.]]

好的,我已经用全一和全二的向量成功地设置了两个隐藏状态。 但是,值得利用 class 函数 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.]]

但是,如果我想检查状态是否已经初始化,我会找到以前的初始化值(全部一个,全部两个)。

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.]]

这里究竟发生了什么?为什么函数看起来根据打印件工作但不更改内部状态的值?

您可能会读到 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 不起作用。

  1. 变量定义:当你将你的内部状态定义为由某个值初始化的变量时,每次调用variable_initializer.

    时都会设置这个特定的vaklue
  2. 重置状态:它将更新此变量的当前值,但不会更改初始值设定项的默认值。为此,您需要通过另一个将给定状态设置为默认值的变量重新分配此状态。