Tensorflow guarda el estado final de LSTM en dynamic_rnn para la predicción

Quiero guardar el estado final de mi LSTM para que se incluya cuando restauro el modelo y se puede usar para la predicción. Como se explica a continuación, el ahorrador solo tiene conocimiento del estado final cuando uso tf.assign . Sin embargo, esto produce un error (también se explica a continuación).

Durante el entrenamiento, siempre devuelvo a la red el estado final de LSTM, como se explica en esta publicación . Aquí están las partes importantes del código:

Al construir el gráfico:

  self.init_state = tf.placeholder(tf.float32, [ self.n_layers, 2, self.batch_size, self.n_hidden ]) state_per_layer_list = tf.unstack(self.init_state, axis=0) rnn_tuple_state = tuple([ tf.contrib.rnn.LSTMStateTuple(state_per_layer_list[idx][0], state_per_layer_list[idx][1]) for idx in range(self.n_layers) ]) outputs, self.final_state = tf.nn.dynamic_rnn( cell, inputs=self.inputs, initial_state=rnn_tuple_state) 

Y durante el entrenamiento:

  _current_state = np.zeros((self.n_layers, 2, self.batch_size, self.n_hidden)) _train_step, _current_state, _loss, _acc, summary = self.sess.run( [ self.train_step, self.final_state, self.merged ], feed_dict={self.inputs: _inputs, self.labels:_labels, self.init_state: _current_state}) 

Cuando luego restauro mi modelo desde un punto de control, el estado final tampoco se restaura. Como se describe en este post, el problema es que Saver no tiene conocimiento del nuevo estado. El post también sugiere una solución, basada en tf.assign . Lamentablemente, no puedo usar el sugerido

  assign_op = tf.assign(self.init_state, _current_state) self.sess.run(assign_op) 

porque el estado self.init no es una variable sino un marcador de posición. Me sale el error

AttributeError: el objeto ‘Tensor’ no tiene atributo ‘asignar’

He intentado resolver este problema durante varias horas pero no consigo que funcione.

Cualquier ayuda es apreciada!

EDITAR:

He cambiado self.init_state a

  self.init_state = tf.get_variable('saved_state', shape= [self.n_layers, 2, self.batch_size, self.n_hidden]) state_per_layer_list = tf.unstack(self.init_state, axis=0) rnn_tuple_state = tuple([ tf.contrib.rnn.LSTMStateTuple(state_per_layer_list[idx][0], state_per_layer_list[idx][1]) for idx in range(self.n_layers) ]) outputs, self.final_state = tf.nn.dynamic_rnn( cell, inputs=self.inputs, initial_state=rnn_tuple_state) 

Y durante el entrenamiento no doy valor a self.init_state:

  _train_step, _current_state, _loss, _acc, summary = self.sess.run( [ self.train_step, self.final_state, self.merged ], feed_dict={self.inputs: _inputs, self.labels:_labels}) 

Sin embargo, todavía no puedo ejecutar la tarea de asignación. Sabes que recibo

TypeError: Se esperaba que float32 se pasara al parámetro ‘value’ de op ‘Assign’, got (LSTMStateTuple (c = array ([[0.07291573, -0.06366599, -0.23425588, …, 0.05307654,

Para guardar el estado final, puede crear una variable TF por separado, luego, antes de guardar el gráfico, ejecute una operación de asignación para asignar su estado más reciente a esa variable y luego guarde el gráfico. Lo único que debe tener en cuenta es declarar esa variable ANTES de declarar el Saver ; De lo contrario no se incluirá en el gráfico.

Esto se discute con gran detalle aquí, incluido el código de trabajo: TF LSTM: Guardar el estado de la sesión de entrenamiento para la sesión de predicción más adelante

*** ACTUALIZACIÓN: respuestas a las preguntas de seguimiento:

Parece que está usando BasicLSTMCell , con state_is_tuple=True . La discusión anterior a la que te referí usó GRUCell con state_is_tuple=False . Los detalles entre los dos son algo diferentes, pero el enfoque general podría ser similar, así que espero que esto funcione para usted:

Durante el entrenamiento, primero initial_state ceros como initial_state en dynamic_rnn y luego continúas realimentando su propia salida como entrada como initial_state . Por lo tanto, el dynamic_rnn estado de salida de nuestra llamada dynamic_rnn es lo que desea guardar para más adelante. Dado que resulta de una llamada sess.run() , esencialmente es una matriz numpy (no un tensor y no un marcador de posición). Así que la pregunta equivale a “cómo puedo guardar una matriz numpy como una variable Tensorflow junto con el rest de las variables en el gráfico”. Es por eso que asigna el estado final a una variable cuyo único propósito es ese.

Entonces, el código es algo como esto:

  # GRAPH DEFINITIONS: state_in = tf.placeholder(tf.float32, [LAYERS, 2, None, CELL_SIZE], name='state_in') l = tf.unstack(state_in, axis=0) state_tup = tuple( [tf.nn.rnn_cell.LSTMStateTuple(l[idx][0], l[idx][1]) for idx in range(NLAYERS)]) #multicell = your BasicLSTMCell / MultiRNN definitions output, state_out = tf.nn.dynamic_rnn(multicell, X, dtype=tf.float32, initial_state=state_tup) savedState = tf.get_variable('savedState', shape=[LAYERS, 2, BATCHSIZE, CELL_SIZE]) saver = tf.train.Saver(max_to_keep=1) in_state = np.zeros((LAYERS, 2, BATCHSIZE, CELL_SIZE)) # TRAINING LOOP: feed_dict = {X: x, Y_: y_, batchsize: BATCHSIZE, state_in:in_state} _, out_state = sess.run([training_step, state_out], feed_dict=feed_dict) in_state = out_state # ONCE TRAINING IS OVER: assignOp = tf.assign(savedState, out_state) sess.run(assignOp) saver.save(sess, pathModel + '/my_model.ckpt') # RECOVERING IN A DIFFERENT PROGRAM: gInit = tf.global_variables_initializer().run() lInit = tf.local_variables_initializer().run() new_saver = tf.train.import_meta_graph(pathModel + 'my_model.ckpt.meta') new_saver.restre(sess, pathModel + 'my_model.ckpt') # retrieve State and get its LAST batch (latest obervarions) savedState = sess.run('savedState:0') # this is FULL state from training state = savedState[:,:,-1,:] # -1 gets only the LAST batch of the state (latest seen observations) state = np.reshape(state, [state.shape[0], 2, -1, state.shape[2]]) #[LAYERS, 2, 1 (BATCH), SELL_SIZE] #x = .... (YOUR INPUTS) feed_dict = {'X:0': x, 'state_in:0':state} #PREDICTION LOOP: preds, state = sess.run(['preds:0', 'state_out:0'], feed_dict = feed_dict) # so now state will be re-fed into feed_dict with the next loop iteration 

Como se mencionó, este es un enfoque modificado de lo que me funciona bien con GRUCell , donde state_is_tuple = False . Lo BasicLSTMCell para probar BasicLSTMCell con state_is_tuple=True . Funciona, pero no tan exactamente como el enfoque original. Todavía no sé si es solo porque para mí GRU es mejor que LSTM o por alguna otra razón. A ver si esto funciona para ti …

También tenga en cuenta que, como puede ver con el código de recuperación y predicción, es probable que sus predicciones se basen en un tamaño de lote diferente al de su ciclo de entrenamiento (¿supongo que lote de 1?) Por lo tanto, debe pensar cómo manejar su estado recuperado – simplemente tomar el último lote? ¿O algo mas? Este código toma la última capa del estado guardado solamente (es decir, las observaciones más recientes del entrenamiento) porque eso es lo que me pareció relevante …