python - basic lstm cell tensorflow
TensorFlow: recuerde el estado LSTM para el próximo lote(LSTM con estado) (2)
Dado un modelo LSTM entrenado, quiero realizar inferencia para
seq_length = 1
únicos, es decir,
seq_length = 1
en el ejemplo a continuación.
Después de cada paso de tiempo, los estados LSTM internos (memoria y ocultos) deben recordarse para el próximo ''lote''.
Para el comienzo de la inferencia, los estados LSTM internos
init_c, init_h
se calculan dada la entrada.
Estos se almacenan en un objeto
LSTMStateTuple
que se pasa al LSTM.
Durante el entrenamiento, este estado se actualiza cada paso de tiempo.
Sin embargo, por inferencia, quiero que el
state
se guarde entre lotes, es decir, los estados iniciales solo deben calcularse al principio y después de eso, los estados LSTM deben guardarse después de cada ''lote'' (n = 1).
Encontré esta pregunta relacionada con StackOverflow:
Tensorflow, ¿la mejor manera de guardar el estado en RNN?
.
Sin embargo, esto solo funciona si
state_is_tuple=False
, pero TensorFlow pronto desaprobará este comportamiento (consulte
rnn_cell.py
).
Keras parece tener un buen envoltorio para hacer posibles LSTM con
estado,
pero no sé la mejor manera de lograr esto en TensorFlow.
Este problema en el TensorFlow GitHub también está relacionado con mi pregunta:
https://github.com/tensorflow/tensorflow/issues/2838
¿Alguien buenas sugerencias para construir un modelo LSTM con estado?
inputs = tf.placeholder(tf.float32, shape=[None, seq_length, 84, 84], name="inputs")
targets = tf.placeholder(tf.float32, shape=[None, seq_length], name="targets")
num_lstm_layers = 2
with tf.variable_scope("LSTM") as scope:
lstm_cell = tf.nn.rnn_cell.LSTMCell(512, initializer=initializer, state_is_tuple=True)
self.lstm = tf.nn.rnn_cell.MultiRNNCell([lstm_cell] * num_lstm_layers, state_is_tuple=True)
init_c = # compute initial LSTM memory state using contents in placeholder ''inputs''
init_h = # compute initial LSTM hidden state using contents in placeholder ''inputs''
self.state = [tf.nn.rnn_cell.LSTMStateTuple(init_c, init_h)] * num_lstm_layers
outputs = []
for step in range(seq_length):
if step != 0:
scope.reuse_variables()
# CNN features, as input for LSTM
x_t = # ...
# LSTM step through time
output, self.state = self.lstm(x_t, self.state)
outputs.append(output)
Descubrí que era más fácil guardar todo el estado para todas las capas en un marcador de posición.
init_state = np.zeros((num_layers, 2, batch_size, state_size))
...
state_placeholder = tf.placeholder(tf.float32, [num_layers, 2, batch_size, state_size])
Luego, descomprímalo y cree una tupla de LSTMStateTuples antes de usar la API nativa de tensorflow RNN.
l = tf.unpack(state_placeholder, axis=0)
rnn_tuple_state = tuple(
[tf.nn.rnn_cell.LSTMStateTuple(l[idx][0], l[idx][1])
for idx in range(num_layers)]
)
RNN pasa en la API:
cell = tf.nn.rnn_cell.LSTMCell(state_size, state_is_tuple=True)
cell = tf.nn.rnn_cell.MultiRNNCell([cell]*num_layers, state_is_tuple=True)
outputs, state = tf.nn.dynamic_rnn(cell, x_input_batch, initial_state=rnn_tuple_state)
La variable de
state
se alimentará al siguiente lote como marcador de posición.
Tensorflow, ¿la mejor manera de guardar el estado en RNN? En realidad fue mi pregunta original. El siguiente código es cómo uso las tuplas de estado.
with tf.variable_scope(''decoder'') as scope:
rnn_cell = tf.nn.rnn_cell.MultiRNNCell /
([
tf.nn.rnn_cell.LSTMCell(512, num_proj = 256, state_is_tuple = True),
tf.nn.rnn_cell.LSTMCell(512, num_proj = WORD_VEC_SIZE, state_is_tuple = True)
], state_is_tuple = True)
state = [[tf.zeros((BATCH_SIZE, sz)) for sz in sz_outer] for sz_outer in rnn_cell.state_size]
for t in range(TIME_STEPS):
if t:
last = y_[t - 1] if TRAINING else y[t - 1]
else:
last = tf.zeros((BATCH_SIZE, WORD_VEC_SIZE))
y[t] = tf.concat(1, (y[t], last))
y[t], state = rnn_cell(y[t], state)
scope.reuse_variables()
En lugar de usar
tf.nn.rnn_cell.LSTMStateTuple
, simplemente creo una lista de listas que funciona bien.
En este ejemplo no estoy salvando el estado.
Sin embargo, podría haber hecho fácilmente el estado de las variables y simplemente utilizar asignar para guardar los valores.