为张量流CTC损失填充标签?



我想填充我的标签,以便它们具有相等的长度以传递到ctc_loss函数中。显然,不允许使用 -1。如果我要应用填充,填充值是否应该成为 ctc 标签的一部分?

更新

我有这段代码,可以将密集标签转换为稀疏标签,以传递给我认为与问题相关的ctc_loss函数。

def dense_to_sparse(dense_tensor, out_type):
indices = tf.where(tf.not_equal(dense_tensor, tf.constant(0, dense_tensor.dtype)
values = tf.gather_nd(dense_tensor, indices)
shape = tf.shape(dense_tensor, out_type=out_type)
return tf.SparseTensor(indices, values, shape)

实际上,-1值允许出现在ctc_batch_cost的y_true参数中,但有一个限制 - 它们不应该出现在label_length指定的实际标签"content"中(这里i标签"content"将从索引0开始,到索引label_length[i]结束)。

因此,完全可以按照您的预期,用-1填充标签,以便它们的长度相等。您唯一应该注意的是正确计算并传递相应的label_length值。

下面是来自 keras 的test_ctc单元测试的修改版本的示例代码:

import numpy as np
from tensorflow.keras import backend as K
number_of_categories = 4
number_of_timesteps = 5
labels = np.asarray([[0, 1, 2, 1, 0], [0, 1, 1, 0, -1]])
label_lens = np.expand_dims(np.asarray([5, 4]), 1)
# dimensions are batch x time x categories
inputs = np.zeros((2, number_of_timesteps, number_of_categories), dtype=np.float32)
input_lens = np.expand_dims(np.asarray([5, 5]), 1)
k_labels = K.variable(labels, dtype="int32")
k_inputs = K.variable(inputs, dtype="float32")
k_input_lens = K.variable(input_lens, dtype="int32")
k_label_lens = K.variable(label_lens, dtype="int32")
res = K.eval(K.ctc_batch_cost(k_labels, k_inputs, k_input_lens, k_label_lens))

即使将-1作为(第二个)labels序列的最后一个元素,它也能运行良好,因为相应的label_lens项(秒)指定其长度为 4。

如果我们将其更改为 5 或将其他标签值更改为-1,则会出现您提到的All labels must be nonnegative integers异常。但这只是意味着我们的label_lens无效。

这是我的做法。我有一个密集张量labels,其中包括 -1 的填充,以便批处理中的所有目标都具有相同的长度。然后我用

labels_sparse = dense_to_sparse(labels, sparse_val=-1)

哪里

def dense_to_sparse(dense_tensor, sparse_val=0):
"""Inverse of tf.sparse_to_dense.
Parameters:
dense_tensor: The dense tensor. Duh.
sparse_val: The value to "ignore": Occurrences of this value in the
dense tensor will not be represented in the sparse tensor.
NOTE: When/if later restoring this to a dense tensor, you
will probably want to choose this as the default value.
Returns:
SparseTensor equivalent to the dense input.
"""
with tf.name_scope("dense_to_sparse"):
sparse_inds = tf.where(tf.not_equal(dense_tensor, sparse_val),
name="sparse_inds")
sparse_vals = tf.gather_nd(dense_tensor, sparse_inds,
name="sparse_vals")
dense_shape = tf.shape(dense_tensor, name="dense_shape",
out_type=tf.int64)
return tf.SparseTensor(sparse_inds, sparse_vals, dense_shape)

这会创建标签的稀疏张量,这是您需要放入 ctc 损失的内容。也就是说,你调用tf.nn.ctc_loss(labels=labels_sparse, ...)填充(即密集张量中等于 -1 的所有值)根本不在这个稀疏张量中表示。

最新更新