为Tensorflow CTC损失填充标签?

为Tensorflow CTC损失填充标签?,tensorflow,Tensorflow,我希望填充标签,使其长度相等,以便传递到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)

我希望填充标签,使其长度相等,以便传递到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填充,因此一批中的所有目标都具有相同的长度。然后我用

labels_sparse = dense_to_sparse(labels, sparse_val=-1)
在哪里


这将创建标签的稀疏张量,这是需要放入ctc中的张量。也就是说,您调用
tf.nn.ctc\u loss(labels=labels\u sparse,…)
填充(即密集张量中所有等于-1的值)根本不在这个稀疏张量中表示。

实际上,
-1
值允许出现在的
y\u true
参数中,但有一个限制-它们不应出现在由
label\u length
指定的实际标签“content”中(此处
i
-th标签“content”将从索引
0
开始,并在索引
label\u length[i]结束)

因此,使用
-1
来填充标签是非常好的,这样它们的长度就可以与您预期的一样长。唯一需要注意的是正确计算并传递相应的
label\u length

以下是示例代码,它是
测试的修改版本

即使将
-1
作为(第二个)
标签
序列的最后一个元素,它也可以正常运行,因为相应的
标签镜头
项(第二个)指定其长度为4


如果我们将其更改为5,或者如果我们将其他一些标签值更改为
-1
,那么我们就得到了
所有标签都必须是非负整数
您提到的例外。但是这仅仅意味着我们的
标签是无效的。

你说的“不允许”是什么意思?我用-1作为填充物就可以了。无论如何,标签都需要作为稀疏张量传递到ctc_loss中,并且该稀疏张量不应包含任何填充。当我将-1作为填充时,ctc抛出此错误:
所有标签必须是非负整数
。假设我有一个目标标签“apple”,它的编码是[0,15,15,12,5]。如果我像[0,15,15,12,5,-1,-1,-1]那样添加-1作为填充,我会遇到这个错误。为什么要填充基本事实文本?您可以通过稀疏张量的索引和值来指定每个文本的长度。在我看来,稀疏张量接口当然是非常复杂的,但是,它只是将标签字符串传送到OP。标签字符串条目必须对应于RNN输出(矩阵)的索引,因此它们必须在0和空白减1的索引之间。让我知道这是否有帮助。我不需要输入一个稠密张量,然后将它映射到TF图中的稀疏张量,而是输入一个稀疏张量。因此,我可以完全避免填充。它确实有效。我只是想澄清一下。“当/如果以后将其恢复为稠密张量时,您可能会选择此作为默认值”,这是什么意思?我应该使用0将其恢复为稠密张量吗?我的意思是:
tf.sparse\u to\u densite
函数有一个
默认值
参数。您可能希望为该参数选择-1(以便恢复的稠密张量再次使用-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)
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))