python tensorflow beam-search

python - Tensorflow: no se puede entender la secuencia de salida ctc_beam_search_decoder()



beam-search (1)

Estoy usando el tf.nn.ctc_beam_search_decoder() de tf.nn.ctc_beam_search_decoder() para decodificar la salida de un RNN haciendo un mapeo muchos-muchos (es decir, múltiples salidas de softmax para cada celda de red).

Una versión simplificada de la salida de la red y el decodificador de búsqueda de Beam es:

import numpy as np import tensorflow as tf batch_size = 4 sequence_max_len = 5 num_classes = 3 y_pred = tf.placeholder(tf.float32, shape=(batch_size, sequence_max_len, num_classes)) y_pred_transposed = tf.transpose(y_pred, perm=[1, 0, 2]) # TF expects dimensions [max_time, batch_size, num_classes] logits = tf.log(y_pred_transposed) sequence_lengths = tf.to_int32(tf.fill([batch_size], sequence_max_len)) decoded, log_probabilities = tf.nn.ctc_beam_search_decoder(logits, sequence_length=sequence_lengths, beam_width=3, merge_repeated=False, top_paths=1) decoded = decoded[0] decoded_paths = tf.sparse_tensor_to_dense(decoded) # Shape: [batch_size, max_sequence_len] with tf.Session() as session: tf.global_variables_initializer().run() softmax_outputs = np.array([[[0.1, 0.1, 0.8], [0.8, 0.1, 0.1], [0.8, 0.1, 0.1], [0.8, 0.1, 0.1], [0.8, 0.1, 0.1]], [[0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7]], [[0.1, 0.7, 0.2], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7]], [[0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7]]]) decoded_paths = session.run(decoded_paths, feed_dict = {y_pred: softmax_outputs}) print(decoded_paths)

El resultado en este caso es:

[[0] [1] [1] [1]]

[batch_size, max_sequence_len] el tensor de salida debe ser de dimensiones [batch_size, max_sequence_len] , y cada fila contiene los índices de las clases relevantes en la ruta encontrada.

En este caso, esperaría que el resultado fuera similar a:

[[2, 0, 0, 0, 0], [2, 2, 2, 2, 2], [1, 2, 2, 2, 2], [2, 2, 2, 2, 2]]

¿Qué no estoy entendiendo sobre cómo funciona ctc_beam_search_decoder ?


Como se indica en la documentación tf.nn.ctc_beam_search_decoder , la forma de la salida no es [batch_size, max_sequence_len] . En cambio, es

[batch_size, max_decoded_length[j]]

(con j=0 en tu caso).

Basado en el comienzo de la sección 2 de este documento (que se cita en el repositorio de github ), max_decoded_length[0] está delimitado desde arriba por max_sequence_len , pero no son necesariamente iguales. La cita relevante es:

Sea S un conjunto de ejemplos de entrenamiento extraídos de una distribución fija D_ {XxZ}. El espacio de entrada X = (R ^ m) es el conjunto de todas las secuencias de vectores dimensionales con valores reales. El espacio objetivo Z = L * es el conjunto de todas las secuencias sobre el alfabeto (finito) L de las etiquetas. En general, nos referimos a elementos de L * como secuencias de etiquetas o etiquetados. Cada ejemplo en S consiste en un par de secuencias (x, z). La secuencia objetivo z = (z1, z2, ..., zU) es como máximo tan larga como la secuencia de entrada x = (x1, x2, ..., xT), es decir, U <= T. Dado que las secuencias de entrada y de destino generalmente no tienen la misma longitud, no hay una forma a priori de alinearlas.

De hecho, max_decoded_length[0] depende de la matriz específica softmax_outputs . En particular, dos de tales matrices con exactamente las mismas dimensiones pueden dar como resultado diferentes max_decoded_length[0] .

Por ejemplo, si reemplaza la fila

softmax_outputs = np.array([[[0.1, 0.1, 0.8], [0.8, 0.1, 0.1], [0.8, 0.1, 0.1], [0.8, 0.1, 0.1], [0.8, 0.1, 0.1]], [[0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7]], [[0.1, 0.7, 0.2], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7]], [[0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7], [0.1, 0.2, 0.7]]])

con las filas

np.random.seed(7) r=np.random.randint(0,100,size=(4,5,3)) softmax_outputs=r/np.sum(r,2).reshape(4,5,1)

obtendrás la salida

[[1 0 1] [1 0 1] [1 0 0] [1 0 0]]

(en los ejemplos anteriores, softmax_outputs consta de logits y tiene exactamente las mismas dimensiones que la matriz que proporcionó).

Por otro lado, cambiando la semilla a np.random.seed(50) da la salida

[[1 0] [1 0] [1 0] [0 1]]

PD

Respecto a la última parte de su pregunta:

En este caso, esperaría que el resultado fuera similar a:

[[2, 0, 0, 0, 0], [2, 2, 2, 2, 2], [1, 2, 2, 2, 2], [2, 2, 2, 2, 2]]

Tenga en cuenta que, en función de la documentation , num_classes realidad representa num_labels + 1 . Específicamente:

Las entradas El tamaño de dimensión más interno de Tensor, num_classes , representa num_labels + 1 clases, donde num_labels es el número de etiquetas verdaderas, y el valor más grande ( num_classes - 1 ) está reservado para la etiqueta en blanco.

Por ejemplo, para un vocabulario que contiene 3 etiquetas [a, b, c], num_classes = 4 y la indexación de las etiquetas es {a: 0, b: 1, c: 2, blank: 3}.

Entonces las etiquetas verdaderas en su caso son 0 y 1, y 2 está reservado para la etiqueta en blanco. La etiqueta en blanco representa la situación de no observar etiqueta (sección 3.1 aquí ):

Una red CTC tiene una capa de salida softmax (Bridle, 1990) con una unidad más que etiquetas en L. Las activaciones de la primera | L | las unidades se interpretan como las probabilidades de observar las etiquetas correspondientes en momentos particulares. La activación de la unidad extra es la probabilidad de observar una etiqueta ''en blanco'' o no. Juntas, estas salidas definen las probabilidades de todas las formas posibles de alinear todas las secuencias de etiquetas posibles con la secuencia de entrada.