В чем разница между tf.nn.ctc_loss и pytorch.nn.CTCLoss

Для того же ввода и метки:

  • выход pytorch.nn.CTCLoss 5,74,
  • выход tf.nn.ctc_loss 129,69,
  • но вывод math.log(tf ctc loss) 4,86

Так в чем разница между pytorch.nn.CTCLoss с участием tf.nn.ctc_loss?

tf: 1.13.1
pytorch: 1.1.0

Я должен был попытаться это:

  1. log_softmax вход, а затем отправить его pytorch.nn.CTCLoss,

  2. tf.nn.log_softmax вход, а затем отправить его tf.nn.ctc_loss

  3. напрямую отправить вход tf.nn.ctc_loss

  4. напрямую отправить вход tf.nn.ctc_loss, а потом math.log(output of tf.nn.ctc_loss)

В случае 2, 3 и 4 результатом вычисления является разница от pytorch.nn.CTCLoss

from torch import nn
import torch
import tensorflow as tf
import math

time_step = 50  # Input sequence length
vocab_size = 20  # Number of classes
batch_size = 16  # Batch size
target_sequence_length = 30  # Target sequence length


def dense_to_sparse(dense_tensor, sequence_length):
    indices = tf.where(tf.sequence_mask(sequence_length))
    values = tf.gather_nd(dense_tensor, indices)
    shape = tf.shape(dense_tensor, out_type=tf.int64)
    return tf.SparseTensor(indices, values, shape)


def compute_loss(x, y, x_len):
    ctclosses = tf.nn.ctc_loss(
        y,
        tf.cast(x, dtype=tf.float32),
        x_len,
        preprocess_collapse_repeated=False,
        ctc_merge_repeated=False,
        ignore_longer_outputs_than_inputs=False
    )
    ctclosses = tf.reduce_mean(ctclosses)

    with tf.Session() as sess:
        ctclosses = sess.run(ctclosses)
        print(f"tf ctc loss: {ctclosses}")
        print(f"tf log(ctc loss): {math.log(ctclosses)}")


minimum_target_length = 10

ctc_loss = nn.CTCLoss(blank=vocab_size - 1)
x = torch.randn(time_step, batch_size, vocab_size)  # [size] = T,N,C
y = torch.randint(0, vocab_size - 2, (batch_size, target_sequence_length), dtype=torch.long)  # low, high, [size]

x_lengths = torch.full((batch_size,), time_step, dtype=torch.long)  # Length of inputs
y_lengths = torch.randint(minimum_target_length, target_sequence_length, (batch_size,),
                          dtype=torch.long)  # Length of targets can be variable (even if target sequences are constant length)

loss = ctc_loss(x.log_softmax(2).detach(), y, x_lengths, y_lengths)
print(f"torch ctc loss: {loss}")

x = x.numpy()
y = y.numpy()
x_lengths = x_lengths.numpy()
y_lengths = y_lengths.numpy()
x = tf.cast(x, dtype=tf.float32)
y = tf.cast(dense_to_sparse(y, y_lengths), dtype=tf.int32)
compute_loss(x, y, x_lengths)

Я ожидаю выход tf.nn.ctc_loss то же самое с выходом pytorch.nn.CTCLoss, но на самом деле это не так, но как я могу сделать их такими же?

0 ответов

Автоматическое уменьшение среднего значения CTCLoss в pytorch - это не то же самое, что вычисление всех индивидуальных потерь с последующим вычислением среднего значения (как вы делаете в реализации Tensorflow). Действительно из документа CTCLoss (pytorch):

``'mean'``: the output losses will be divided by the target lengths and
            then the mean over the batch is taken.

Чтобы получить такое же значение:

1- Измените метод уменьшения на сумму:

ctc_loss = nn.CTCLoss(reduction='sum')

2- Разделите потерю, вычисленную на batch_size:

loss = ctc_loss(x.log_softmax(2).detach(), y, x_lengths, y_lengths)
loss = (loss.item())/batch_size

3- Измените параметр ctc_merge_repeated в Tensorflow на True (я предполагаю, что это также имеет место в pytorch CTC)

    ctclosses = tf.nn.ctc_loss(
    y,
    tf.cast(x, dtype=tf.float32),
    x_len,
    preprocess_collapse_repeated=False,
    ctc_merge_repeated=True,
    ignore_longer_outputs_than_inputs=False
)

Теперь вы получите очень близкие результаты между потерей pytorch и потерей тензорного потока (без регистрации значения). Оставшаяся небольшая разница, вероятно, связана с небольшими различиями между реализациями. В моих последних трех прогонах я получил следующие значения:

pytorch loss : 113.33 vs tf loss = 113.52
pytorch loss : 116.30 vs tf loss = 115.57
pytorch loss : 115.67 vs tf loss = 114.54
Другие вопросы по тегам