В чем разница между 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
Я должен был попытаться это:
log_softmax
вход, а затем отправить егоpytorch.nn.CTCLoss
,tf.nn.log_softmax
вход, а затем отправить егоtf.nn.ctc_loss
напрямую отправить вход
tf.nn.ctc_loss
напрямую отправить вход
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