具有ignore_index的Pytorch损失函数导致模型无法收敛

时间:2019-09-17 12:10:26

标签: nlp pytorch

我正在阅读有关seq2eq Chatbot的实现的Pytorch官方教程。为了更好地理解,我使用了不同的方法来获得相似的结果。我认为其中一项改进是使用属性ignore_index = padding_token实现的简单nn.NLLLoss函数。以前的使用二进制掩码张量描述目标张量的填充的解决方案似乎太复杂了,我想要一个更简单的解决方案,但是由于它被淘汰了,因此增加了几行代码会使一切变得更糟。现在,模型根本无法收敛。我试图更改学习率,但这没有帮助。

Pytorch聊天机器人推荐:https://pytorch.org/tutorials/beginner/chatbot_tutorial.html

criterion = nn.NLLLoss(ignore_index=PAD_token, reduction='mean')

在训练函数的定义中,当我们一次向前通过解码器传播时,我在循环中只做了很小的改变:

if use_teacher_forcing:
    for t in range(max_target_len):
        decoder_output, decoder_hidden = decoder(
            decoder_input, decoder_hidden, encoder_outputs
        )
        # Teacher forcing: next input is current target
        decoder_input = target_variable[t].view(1, -1)

        # Calculate and accumulate loss

        loss = criterion(decoder_output, target_variable[t])
        total_loss += loss
        print_losses.append(loss.item())


# Perform backpropatation
total_loss.backward()

# Clip gradients: gradients are modified in place
_ = nn.utils.clip_grad_norm_(encoder.parameters(), clip)
_ = nn.utils.clip_grad_norm_(decoder.parameters(), clip)

# Adjust model weights
encoder_optimizer.step()
decoder_optimizer.step()

return sum(print_losses)/max_target_len

Output:
Iteration: 1; Percent complete: 0.0%; Average loss: 8.5246
Iteration: 2; Percent complete: 0.1%; Average loss: 8.5403
Iteration: 3; Percent complete: 0.1%; Average loss: 8.5663
Iteration: 4; Percent complete: 0.1%; Average loss: 8.5691
Iteration: 5; Percent complete: 0.1%; Average loss: 8.4637
Iteration: 6; Percent complete: 0.1%; Average loss: 8.5378
Iteration: 7; Percent complete: 0.2%; Average loss: 8.5575
Iteration: 8; Percent complete: 0.2%; Average loss: 8.5145
Iteration: 9; Percent complete: 0.2%; Average loss: 8.5717
Iteration: 10; Percent complete: 0.2%; Average loss: 8.5122
Iteration: 11; Percent complete: 0.3%; Average loss: 8.5587
Iteration: 12; Percent complete: 0.3%; Average loss: 8.5491
Iteration: 13; Percent complete: 0.3%; Average loss: 8.5933
Iteration: 14; Percent complete: 0.4%; Average loss: 8.5231
Iteration: 15; Percent complete: 0.4%; Average loss: 8.5239

…等等

总损失增加或波动相同的值,但并不想减少。是否有人尝试在具有可变长度序列的seq2seq模型中使用带有ignore_index的任何类型的损失函数,并产生了一些积极的结果? nn.CrossEntropyLoss的行为类似。我开始认为,ignore_index参数的损失计算不正确...

我想强调的是,传递给损失函数的张量具有以下维度:

loss = criterion(decoder_output, target_variable[t])
# decoder_output: (batch_size, vocab_size)
# target_variable[t]: (batch_size)

我认为这是适当的尺寸,但也许我应该重塑这些张量?在原始代码中,他们手动计算负对数,并将最终形状的“连接”张量传递给它:

    crossEntropy = -torch.log(torch.gather(inp, 1, target.view(-1, 1)).squeeze(1)) # shape (batch_size)

另一个问题。在我的版本中,我使用了:

packed = nn.utils.rnn.pack_padded_sequence(embedded, input_lengths, batch_first=True, enforce_sorted=False)

因此,我没有按照顺序长度按降序对批次进行排序。我注意到我的代码处理过程比原始处理慢,可能是由于使用未排序的批处理引起的,还是应该正常工作?

任何建议将不胜感激。

最诚挚的问候。

0 个答案:

没有答案