RNN 初始状态是否为后续小批量重置?
Is RNN initial state reset for subsequent mini-batches?
有人可以澄清一下,TF 中 RNN 的初始状态是为后续的小批量重置,还是使用前一个小批量的最后状态,如 Ilya Sutskever et al., ICLR 2015 中所述?
tf.nn.dynamic_rnn()
or 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()
,你可以向它提供一个状态保护对象,但我还没有使用它。
除了 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 的元组 - 每层一个。
有人可以澄清一下,TF 中 RNN 的初始状态是为后续的小批量重置,还是使用前一个小批量的最后状态,如 Ilya Sutskever et al., ICLR 2015 中所述?
tf.nn.dynamic_rnn()
or 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()
,你可以向它提供一个状态保护对象,但我还没有使用它。
除了 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 的元组 - 每层一个。