Pytorch学习之:深度剖析NLLLoss和 CrossEntropy 的区别:代码 + 原理 + 为什么有效

NLLLoss

  • 假设我现在做 NLP 任务,在不考虑 batch 大小的前提下:

    • 词表大小 vocab_size = 3 {0: 我, 1:吃, 2:饭}
    • 句子的长度 seq_len = 2
    • 那么现在我得到了一个张量,维度是 ( V o c a b _ s i z e , s e q _ l e n ) (Vocab\_size, seq\_len) (Vocab_size,seq_len) (3,2),三行两列,每一列是一个列向量代表句子中的一个词的 logits 分布:
    tensor([[ 1.1741, -0.4859],
            [ -3.7180,  1.5257],
            [ 0.0222,  0.5898]])
    
    • label 是:
    tensor([1, 2])
    

    这里先插一句在当前情境下 NLLOSS 的计算规则:

    • 第一步:将 label 中的每个值,作为 predict 结果中对应列的索引值,拿到 predict 对应列中的具体值,在这里就是在第一列中取出 -3.718,第二列中取出 0.5898
    • 第二步:将这些取出的值取反,得到 3.718-0.5898
    • 第三步:将这些取反后的值进行相加 (3.718-0.5898) / 2=1.5641
    pred = torch.tensor([[ 1.1741, -0.4859],
        [ -3.718,  1.5257],
        [ 0.0222,  0.5898]], dtype=torch.float32)
    label = torch.tensor([1,2], dtype=torch.long)
    # 先忽略这里的 ignore_index 后面会讲
    loss = NLLLoss(ignore_index=3)
    # 由于用 NLLLoss 计算的时候必须要有 batch 的维度,所以我们暂且迎合这个规则,增加一个 batch维度
    loss(pred.unsqueeze_(0), label.unsqueeze_(0))
    
    • 目前 label 给出的信息,这两个字应该是 ['吃', '饭']
    • 但模型的预测结果并不这么觉得,首先看 第一列 的分布
      tensor([1.1741, -3.7180, 0.0222])
      
    • 这个分布就表明了,对于预测结果的第一个词的预测过程词表中的 index=0 (我)的词的和 index=3(饭)都做了有利的贡献(分布中的对应值>0),而词表中 index=1 的词(吃)做了反向的贡献
    • 在 NLLloss 计算的时候,恰好在第一列中把 -3.718 这个数取出来了(label[0]=1),而这个词是一个做了反向贡献的词,所以 loss 值就变成了 3.718. 而如果 label[0] = 0 则取出来的是 1.1741 这个值,那么经过 NLLloss 计算后,这个一列的 loss 会变成 -1.1741,也就是 loss 为负值,loss越小当然越好。
      在这里插入图片描述
    • 那么为什么把 label 的值当做 pred 结果中此列的索引的这种计算方式能够反映当前模型学习的效果呢?即为什么 NLLloss 是有效的:
    • 我们假设如果这个模型学的非常好,那么当 label = 1 的时候,理应第一个列的 logits 分布中index=1 的位置就应该是一个较大的正值。如果他是个负值或者比较小的正值,就代表模型学的不够好。

CrossEntropy

  • 与 NLLLoss 的情景一样,我们依然沿用刚才的 predlabel

    	tensor([[ 1.1741, -0.4859],
    	        [ -3.7180,  1.5257],
    	        [ 0.0222,  0.5898]])
    
    • label 是:

      tensor([1, 2])
      
    • 还是先介绍 CrossEntropy 的计算步骤:

      • 第一步:按照列进行 softmax 操作,pred 首先变成了:
      pred = torch.tensor([[ 1.1741, -0.4859],
              [ -3.718,  1.5257],
              [ 0.0222,  0.5898]], dtype=torch.float32)
      label = torch.tensor([1,2], dtype=torch.long)
      s = F.softmax(pred, dim=0)
      print(s)
      tensor(
      	[[0.7555, 0.0877],
          [0.0057, 0.6553],
          [0.2388, 0.2570]])
      
      • 第二步:对当前的这个矩阵逐点计算 log
      torch.log(s)
      tensor([[-0.2803, -2.4343],
              [-5.1724, -0.4227],
              [-1.4322, -1.3586]])
      
      • 第三步:对当前的这个矩阵计算 NLLloss
      [-(-5.1724) + -(-1.3586)] / 2 = 3.2655
      
    • 那么为什么 CrossEntropy 有效呢?

      • 首先 softmax 的操作让每一列分布的差异变得更大
      • 由于 softmax 会让某一列的值分布在 0-1 之间,所以我们通过 log 计算之后,所有的值都 < 0,从第一列的值的变化就可以看出,原本的 -3.718 再进行了 softmaxlog 运算之后被扩大成了 -5.1734,而原本不明显的 0.222 也被拉大到了 -1.4322。因为 softmax 的特点是将一个负数变成一个非常贴近 0 的正数,而 log 的作用又会将贴近 0 的值变成一个很大的负数。很显然这一套操作下来(softmax + log),除了原本比较大的正值,那些原本 0 附近的正值和所有的负值造成的损失值都会变大很多。这样就避免了模型学习的时候 label 对他模棱两可的指导。比较小的正值也会产生 loss 来惩罚模型,从而帮助模型尽可能给出比较大的正值。
      • 使用 softmax 同时还有一个好处:那就是在同一个句子中,不管是预测的结果是对的还是错的,都会产生 loss 值,因为所有的位置在 log 之后都是负值,而再经过 NLLLoss 都会变成正值。这样就避免了某个词的 loss 是负数和其他词的 loss 取平均的时候将 loss 给抵消掉的问题。

联系

  • 从上面的例子中,我们也可以看出来:

    CrossentropyLoss = Softmax + log + NLLLoss

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
nn.NLLLoss()和nn.CrossEntropyLoss()是用于多分类任务的损失函数,在PyTorch中它们实际上是相同的。唯一的区别在于它们接收的输入不同: - nn.NLLLoss()的输入是一个对数概率向量和一个目标标签,它不会为我们计算对数概率。适合网络的最后一层是log_softmax损失函数的情况。 - nn.CrossEntropyLoss()的输入是一个预测值和一个目标标签,它会为我们自动计算预测值的对数概率,即先做softmax,再做log处理。在实际使用中,两者可以互换使用,效果是一样的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [paddle中nll_loss()与CrossEntropyLoss()损失函数区别](https://blog.csdn.net/weixin_43848436/article/details/115448659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Pytorch中损失函数 NLLLOSS 和 CROSSENTROPYLOSS 的区别](https://blog.csdn.net/cnhwl/article/details/125518586)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值