[英]Tensorflow: Can't understand ctc_beam_search_decoder() output sequence
我正在使用Tensorflow的tf.nn.ctc_beam_search_decoder()
来解码执行一些多对多映射的RNN的输出(即,每个网络小区的多个softmax输出)。
网络输出的简化版本和Beam搜索解码器是:
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)
这种情况下的输出是:
[[0]
[1]
[1]
[1]]
我的理解是输出张量应该是维度[batch_size, max_sequence_len]
,每行包含找到的路径中相关类的索引。
在这种情况下,我希望输出类似于:
[[2, 0, 0, 0, 0],
[2, 2, 2, 2, 2],
[1, 2, 2, 2, 2],
[2, 2, 2, 2, 2]]
我怎么不理解ctc_beam_search_decoder
是如何工作的?
如tf.nn.ctc_beam_search_decoder文档中所示 ,输出的形状不是[batch_size, max_sequence_len]
。 相反,它是
[batch_size, max_decoded_length[j]]
(在你的情况下j=0
)。
根据第2条的开头本文 (其在所引用的github库 ), max_decoded_length[0]
是从上面所界定max_sequence_len
,但它们不一定相等。 相关的引用是:
设S是从固定分布D_ {XxZ}绘制的一组训练样例。 输入空间X =(R ^ m)是m维实值向量的所有序列的集合。 目标空间Z = L *是标签的(有限)字母L上的所有序列的集合。 通常,我们将L *的元素称为标记序列或标记。 S中的每个例子由一对序列(x,z)组成。 目标序列z =(z1,z2,...,zU) 最多与输入序列x =(x1,x2,...,xT)一样长,即U <= T. 由于输入序列和目标序列通常不是相同的长度,因此没有先验的对齐方式。
实际上, max_decoded_length[0]
取决于特定矩阵softmax_outputs
。 特别地,具有完全相同尺寸的两个这样的矩阵可以导致不同的max_decoded_length[0]
。
例如,如果您替换该行
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]]])
与行
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)
你会得到输出
[[1 0 1]
[1 0 1]
[1 0 0]
[1 0 0]]
(在上面的例子中, softmax_outputs
由softmax_outputs
组成,它与你提供的矩阵完全相同)。
另一方面,将种子更改为np.random.seed(50)
会给出输出
[[1 0]
[1 0]
[1 0]
[0 1]]
PS
关于你问题的最后部分:
在这种情况下,我希望输出类似于:
[[2, 0, 0, 0, 0], [2, 2, 2, 2, 2], [1, 2, 2, 2, 2], [2, 2, 2, 2, 2]]
请注意,根据文档 , num_classes
实际上表示num_labels + 1
。 特别:
输入Tensor的最内部维度大小
num_classes
表示num_labels + 1
类,其中num_labels
是真实标签的数量,最大值(num_classes - 1
)是为空白标签保留的。例如,对于包含3个标签[a,b,c]的词汇表,
num_classes = 4
,标签索引为{a:0,b:1,c:2,blank:3}。
因此,您的案例中的真实标签为0和1,并且为空白标签保留2。 空白标签表示没有标签的情况( 此处第3.1节):
CTC网络有一个softmax输出层(Bridle,1990),比L中的标签多一个单位。第一个| L |的激活。 单位被解释为在特定时间观察相应标签的概率。 额外单位的激活是观察“空白”或没有标签的概率。 这些输出一起定义了将所有可能的标记序列与输入序列对齐的所有可能方式的概率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.