RNN 是不是会为后续的小批量重置初始状态?

Posted

技术标签:

【中文标题】RNN 是不是会为后续的小批量重置初始状态?【英文标题】:Is RNN initial state reset for subsequent mini-batches?RNN 是否会为后续的小批量重置初始状态? 【发布时间】:2016-11-21 08:21:52 【问题描述】:

有人可以澄清一下是否为后续的小批量重置了 TF 中 RNN 的初始状态,还是使用Ilya Sutskever et al., ICLR 2015 中提到的前一个小批量的最后状态?

【问题讨论】:

【参考方案1】:

除了 danijar 的回答,这里是一个 LSTM 的代码,它的状态是一个元组 (state_is_tuple=True)。它还支持多层。

我们定义了两个函数——一个用于获取具有初始零状态的状态变量,另一个用于返回操作,我们可以将其传递给session.run,以便使用 LSTM 的最后一个隐藏状态更新状态变量。

def get_state_variables(batch_size, cell):
    # For each layer, get the initial state and make a variable out of it
    # to enable updating its value.
    state_variables = []
    for state_c, state_h in cell.zero_state(batch_size, tf.float32):
        state_variables.append(tf.contrib.rnn.LSTMStateTuple(
            tf.Variable(state_c, trainable=False),
            tf.Variable(state_h, trainable=False)))
    # Return as a tuple, so that it can be fed to dynamic_rnn as an initial state
    return tuple(state_variables)


def get_state_update_op(state_variables, new_states):
    # Add an operation to update the train states with the last state tensors
    update_ops = []
    for state_variable, new_state in zip(state_variables, new_states):
        # Assign the new state to the state variables on this layer
        update_ops.extend([state_variable[0].assign(new_state[0]),
                           state_variable[1].assign(new_state[1])])
    # Return a tuple in order to combine all update_ops into a single operation.
    # The tuple's actual value should not be used.
    return tf.tuple(update_ops)

与 danijar 的回答类似,我们可以使用它在每批之后更新 LSTM 的状态:

data = tf.placeholder(tf.float32, (batch_size, max_length, frame_size))
cells = [tf.contrib.rnn.GRUCell(256) for _ in range(num_layers)]
cell = tf.contrib.rnn.MultiRNNCell(cells)

# For each layer, get the initial state. states will be a tuple of LSTMStateTuples.
states = get_state_variables(batch_size, cell)

# Unroll the LSTM
outputs, new_states = tf.nn.dynamic_rnn(cell, data, initial_state=states)

# Add an operation to update the train states with the last state tensors.
update_op = get_state_update_op(states, new_states)

sess = tf.Session()
sess.run(tf.global_variables_initializer())
sess.run([outputs, update_op], data: ...)

主要区别在于state_is_tuple=True 使 LSTM 的状态成为包含两个变量(单元状态和隐藏状态)的 LSTMStateTuple,而不仅仅是一个变量。然后使用多层使 LSTM 的状态成为 LSTMStateTuples 的元组——每层一个。

【讨论】:

请注意您创建 num_layers 相同 个单元格的方式,这可能不是您想要做的 运行时确定batch_size怎么办? @Mr_and_Mrs_D 感谢您的提示,我更新了代码。 @I.A 你可以给 get_state_variables 你期望创建状态变量的最大 batch_size 并忽略未使用的状态变量 我收到一个错误类型错误:张量对象仅在启用急切执行时才可迭代。要迭代此张量,请使用 tf.map_fn。【参考方案2】:

tf.nn.dynamic_rnn()tf.nn.rnn() 操作允许使用initial_state 参数指定RNN 的初始状态。如果不指定此参数,隐藏状态将在每个训练批次开始时初始化为零向量。

在 TensorFlow 中,您可以将张量包装在 tf.Variable() 中,以在多个会话运行之间将它们的值保留在图中。只需确保将它们标记为不可训练,因为优化器默认会调整所有可训练变量。

data = tf.placeholder(tf.float32, (batch_size, max_length, frame_size))

cell = tf.nn.rnn_cell.GRUCell(256)
state = tf.Variable(cell.zero_states(batch_size, tf.float32), trainable=False)
output, new_state = tf.nn.dynamic_rnn(cell, data, initial_state=state)

with tf.control_dependencies([state.assign(new_state)]):
    output = tf.identity(output)

sess = tf.Session()
sess.run(tf.initialize_all_variables())
sess.run(output, data: ...)

我没有测试过这段代码,但它应该会给你一个正确方向的提示。还有一个tf.nn.state_saving_rnn(),你可以向它提供一个状态保护对象,但我还没有使用它。

【讨论】:

batch_size 是什么变量,在这种情况下,创建的tf.Variable 会抛出错误,因为我们需要指定变量的大小。

以上是关于RNN 是不是会为后续的小批量重置初始状态?的主要内容,如果未能解决你的问题,请参考以下文章

请问SAP中使用FBRA(重置已结清项目),选择“只重置”,但是重置错了凭证,那么后续如何处理?

在redux中按下重置按钮时如何初始化所有状态

在每个页面上将状态重置为初始状态

将复选框重置为初始状态

WPF如何重置Combobox下拉菜单里的值为初始状态

核心数据:重置为初始状态