ctc_loss 错误 "No valid path found."

ctc_loss error "No valid path found."

使用 tf.nn.ctc_loss 训练模型会在每次训练操作为 运行:

时产生错误
tensorflow/core/util/ctc/ctc_loss_calculator.cc:144] No valid path found.

与之前有关此功能的问题不同,这不是由于分歧。我的学习率很低,即使是第一个train op也会出错。

模型是 CNN -> LSTM -> CTC。这是模型创建代码:

# Build Graph
self.videoInput = tf.placeholder(shape=(None, self.maxVidLen, 50, 100, 3), dtype=tf.float32)
self.videoLengths = tf.placeholder(shape=(None), dtype=tf.int32)
self.keep_prob = tf.placeholder(dtype=tf.float32)
self.targets = tf.sparse_placeholder(tf.int32)
self.targetLengths = tf.placeholder(shape=(None), dtype=tf.int32)

conv1 = tf.layers.conv3d(self.videoInput ...)
pool1 = tf.layers.max_pooling3d(conv1 ...)
conv2 = ...
pool2 = ...
conv3 = ...
pool3 = ...

cnn_out = tf.reshape(pool3, shape=(-1, self.maxVidLength, 4*7*96))

fw_cell = tf.nn.rnn_cell.MultiRNNCell(self.cell(), for _ in range(3))
bw_cell = tf.nn.rnn_cell.MultiRNNCell(self.cell(), for _ in range(3))
outputs, _ = tf.nn.bidirectional_dynamic_rnn(
            fw_cell, bw_cell, cnn_out, sequence_length=self.videoLengths, dtype=tf.float32)

outputs = tf.concat(outputs, 2)
outputs = tf.reshape(outputs, [-1, self.hidden_size * 2])

w = tf.Variable(tf.random_normal((self.hidden_size * 2, len(self.char2index) + 1), stddev=0.2))
b = tf.Variable(tf.zeros(len(self.char2index) + 1))

out = tf.matmul(outputs, w) + b
out = tf.reshape(out, [-1, self.maxVidLen, len(self.char2index) + 1])
out = tf.transpose(out, [1, 0, 2])

cost = tf.reduce_mean(tf.nn.ctc_loss(self.targets, out, self.targetLengths))
self.train_op = tf.train.AdamOptimizer(0.0001).minimize(cost)

这里是 feed dict 创建代码:

indices = []
values = []
shape = [len(vids) * 2, self.maxLabelLen]
vidInput = np.zeros((len(vids) * 2, self.maxVidLen, 50, 100, 3), dtype=np.float32)

# Actual video, then left-right flip
for j in range(len(vids) * 2):

    # K is video index
    k = j if j < len(vids) else j - len(vids)

    # convert video and label to input format
    vidInput[j, 0:len(vids[k])] = vids[k] if k == j else vids[k][:,::-1,:]
    indices.extend([j, i] for i in range(len(labelList[k])))
    values.extend(self.char2index[c] for c in labelList[k])

fd[self.targets] = (indices, values, shape)
fd[self.videoInput] = vidInput

# Collect video lengths and label lengths
vidLengths = [len(j) for j in vids] + [len(j) for j in vids]
labelLens = [len(l) for l in labelList] + [len(l) for l in labelList]
fd[self.videoLengths] = vidLengths
fd[self.targetLengths] = labelLens

事实证明,ctc_loss 要求标签长度比输入长度短。如果标签长度太长,损失计算器无法完全展开,因此无法计算损失。

例如,标签 BIFI 要求输入长度至少为 4,而标签 BIIF 要求输入长度至少为 5,因为在重复符号之间插入了空格。

我在我的案例中发现的另一个可能原因是输入数据范围未归一化为 0~1,因为 LSTM 激活函数在训练开始时变得饱和,并导致 "no valid path"以某种方式登录。

对我来说,通过设置 preprocess_collapse_repeated=True 解决了问题。
FWIW:我的目标序列长度已经比输入短,RNN 输出是 softmax 的。

我遇到了同样的问题,但我很快意识到这只是因为我使用的是 glob 并且我的标签在文件名中,所以它超出了。

您可以使用以下方法解决此问题:

os.path.join(*(filename.split(os.path.sep)[noOfDir:]))