Predecir la siguiente palabra utilizando el ejemplo de tensorflow del modelo ptb LSTM

Estoy tratando de usar el modelo tensorflow LSTM para hacer predicciones de la siguiente palabra.

Como se describe en esta pregunta relacionada (que no tiene una respuesta aceptada), el ejemplo contiene pseudocódigo para extraer las siguientes probabilidades de palabras:

lstm = rnn_cell.BasicLSTMCell(lstm_size) # Initial state of the LSTM memory. state = tf.zeros([batch_size, lstm.state_size]) loss = 0.0 for current_batch_of_words in words_in_dataset: # The value of state is updated after processing each batch of words. output, state = lstm(current_batch_of_words, state) # The LSTM output can be used to make next word predictions logits = tf.matmul(output, softmax_w) + softmax_b probabilities = tf.nn.softmax(logits) loss += loss_function(probabilities, target_words) 

Estoy confundido acerca de cómo interpretar el vector de probabilidades. __init__ función __init__ del PTBModel en ptb_word_lm.py para almacenar las probabilidades y los logits:

 class PTBModel(object): """The PTB model.""" def __init__(self, is_training, config): # General definition of LSTM (unrolled) # identical to tensorflow example ... # omitted for brevity ... # computing the logits (also from example code) logits = tf.nn.xw_plus_b(output, tf.get_variable("softmax_w", [size, vocab_size]), tf.get_variable("softmax_b", [vocab_size])) loss = seq2seq.sequence_loss_by_example([logits], [tf.reshape(self._targets, [-1])], [tf.ones([batch_size * num_steps])], vocab_size) self._cost = cost = tf.reduce_sum(loss) / batch_size self._final_state = states[-1] # my addition: storing the probabilities and logits self.probabilities = tf.nn.softmax(logits) self.logits = logits # more model definition ... 

Luego run_epoch algo de información sobre ellos en la función run_epoch :

 def run_epoch(session, m, data, eval_op, verbose=True): """Runs the model on the given data.""" # first part of function unchanged from example for step, (x, y) in enumerate(reader.ptb_iterator(data, m.batch_size, m.num_steps)): # evaluate proobability and logit tensors too: cost, state, probs, logits, _ = session.run([m.cost, m.final_state, m.probabilities, m.logits, eval_op], {m.input_data: x, m.targets: y, m.initial_state: state}) costs += cost iters += m.num_steps if verbose and step % (epoch_size // 10) == 10: print("%.3f perplexity: %.3f speed: %.0f wps, n_iters: %s" % (step * 1.0 / epoch_size, np.exp(costs / iters), iters * m.batch_size / (time.time() - start_time), iters)) chosen_word = np.argmax(probs, 1) print("Probabilities shape: %s, Logits shape: %s" % (probs.shape, logits.shape) ) print(chosen_word) print("Batch size: %s, Num steps: %s" % (m.batch_size, m.num_steps)) return np.exp(costs / iters) 

Esto produce una salida como esta:

 0.000 perplexity: 741.577 speed: 230 wps, n_iters: 220 (20, 10000) (20, 10000) [ 14 1 6 589 1 5 0 87 6 5 3 5 2 2 2 2 6 2 6 1] Batch size: 1, Num steps: 20 

Esperaba que el vector probs fuera una variedad de probabilidades, con una para cada palabra en el vocabulario (por ejemplo, con shape (1, vocab_size) ), lo que significa que podría obtener la palabra predicha utilizando np.argmax(probs, 1) como Se sugiere en la otra pregunta.

Sin embargo, la primera dimensión del vector es en realidad igual a la cantidad de pasos en el LSTM desenrollado (20 si se usan los ajustes de configuración pequeños), con lo cual no estoy seguro de qué hacer. Para acceder a la palabra predicha, ¿solo necesito usar el último valor (porque es el resultado del paso final)? ¿O hay algo más que me estoy perdiendo?

Traté de entender cómo se hacen y evalúan las predicciones mirando la implementación de seq2seq.sequence_loss_by_example , que debe realizar esta evaluación, pero esto termina por llamar gen_nn_ops._sparse_softmax_cross_entropy_with_logits , que no parece estar incluido en el repositivo de github, por lo que No estoy seguro de dónde buscar.

Soy bastante nuevo tanto en tensorflow como en LSTM, por lo que se agradece cualquier ayuda.

El tensor de output contiene la concatentación de las salidas de celda LSTM para cada paso de tiempo (consulte su definición aquí ). Por lo tanto, puede encontrar la predicción para la siguiente palabra si toma la palabra chosen_word[-1] (o la chosen_word[sequence_length - 1] si la secuencia se ha rellenado para que coincida con el LSTM desenrollado).

La tf.nn.sparse_softmax_cross_entropy_with_logits() está documentada en la API pública con un nombre diferente. Por razones técnicas, llama a una función de envoltura generada que no aparece en el repository de GitHub. La implementación de la operación está en C ++, aquí .

También estoy implementando el modelo seq2seq.

Así que déjame tratar de explicar con mi comprensión:

Las salidas de su modelo LSTM son una lista (con número de longitud) del tensor 2D de tamaño [tamaño de lote , tamaño ].

La línea de código:

output = tf.reshape(tf.concat(1, outputs), [-1, size])

producirá una nueva salida que es un tensor 2D de tamaño [ batch_size x num_steps , size ].

Para su caso, batch_size = 1 y num_steps = 20 -> la forma de salida es [ 20 , tamaño ].

Línea de código:

logits = tf.nn.xw_plus_b(output, tf.get_variable("softmax_w", [size, vocab_size]), tf.get_variable("softmax_b", [vocab_size]))

<=> salida [batch_size x num_steps, tamaño] x softmax_w [size, vocab_size] producirá logits de tamaño [ batch_size x num_steps , vocab_size ].
Para su caso, logits de tamaño [ 20 , vocab_size ] -> probs tensor tiene el mismo tamaño que logits por [ 20 , vocab_size ].

Línea de código:

chosen_word = np.argmax(probs, 1)

generará el valor tensor_de_localización del tamaño [ 20 , 1 ] con cada valor que es el siguiente índice de palabra de predicción de la palabra actual.

Línea de código:

loss = seq2seq.sequence_loss_by_example([logits], [tf.reshape(self._targets, [-1])], [tf.ones([batch_size * num_steps])])

es calcular la pérdida de entropía cruzada de softmax para el tamaño de lote de las secuencias.