PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

作者:gy笨瓜 时间:2022-01-12 19:39:19 

torch.nn.CrossEntropyLoss交叉熵损失

本文只考虑基本情况,未考虑加权。

torch.nnCrossEntropyLosss使用的公式

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

目标类别采用one-hot编码

其中,class表示当前样本类别在one-hot编码中对应的索引(从0开始),

x[j]表示预测函数的第j个输出

公式(1)表示先对预测函数使用softmax计算每个类别的概率,再使用log(以e为底)计算后的相反数表示当前类别的损失,只表示其中一个样本的损失计算方式,非全部样本。

每个样本使用one-hot编码表示所属类别时,只有一项为1,因此与基本的交叉熵损失函数相比,省略了其它值为0的项,只剩(1)所表示的项。

sample

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

torch.nn.CrossEntropyLoss使用流程

torch.nn.CrossEntropyLoss为一个类,并非单独一个函数,使用到的相关简单参数会在使用中说明,并非对所有参数进行说明。

首先创建类对象

In [1]: import torch
In [2]: import torch.nn as nn
In [3]: loss_function = nn.CrossEntropyLoss(reduction="none")

参数reduction默认为"mean",表示对所有样本的loss取均值,最终返回只有一个值

参数reduction取"none",表示保留每一个样本的loss

计算损失

In [4]: pred = torch.tensor([[0.0541,0.1762,0.9489],[-0.0288,-0.8072,0.4909]], dtype=torch.float32)
In [5]: class_index = torch.tensor([0, 2], dtype=torch.int64)
In [6]: loss_value = loss_function(pred, class_index)
In [7]: loss_value
Out[7]: tensor([1.5210, 0.6247]) # 与上述【sample】计算一致

实际计算损失值调用函数时,传入pred预测值与class_index类别索引

在传入每个类别时,class_index应为一维,长度为样本个数,每个元素表示对应样本的类别索引,非one-hot编码方式传入

测试torch.nn.CrossEntropyLoss的reduction参数为默认值"mean"

In [1]: import torch
In [2]: import torch.nn as nn
In [3]: loss_function = nn.CrossEntropyLoss(reduction="mean")
In [4]: pred = torch.tensor([[0.0541,0.1762,0.9489],[-0.0288,-0.8072,0.4909]], dtype=torch.float32)
In [5]: class_index = torch.tensor([0, 2], dtype=torch.int64)
In [6]: loss_value = loss_function(pred, class_index)
In [7]: loss_value
Out[7]: 1.073 # 与上述【sample】计算一致

交叉熵损失nn.CrossEntropyLoss()的真正计算过程

对于多分类损失函数Cross Entropy Loss,就不过多的解释,网上的博客不计其数。在这里,讲讲对于CE Loss的一些真正的理解。

首先大部分博客给出的公式如下:

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

其中p为真实标签值,q为预测值。

在低维复现此公式,结果如下。在此强调一点,pytorch中CE Loss并不会将输入的target映射为one-hot编码格式,而是直接取下标进行计算。

import torch
import torch.nn as nn
import math
import numpy as np

#官方的实现
entroy=nn.CrossEntropyLoss()
input=torch.Tensor([[0.1234, 0.5555,0.3211],[0.1234, 0.5555,0.3211],[0.1234, 0.5555,0.3211],])
target = torch.tensor([0,1,2])
output = entroy(input, target)
print(output)
#输出 tensor(1.1142)

#自己实现
input=np.array(input)
target = np.array(target)
def cross_entorpy(input, target):
   output = 0
   length = len(target)
   for i in range(length):
       hou = 0
       for j in input[i]:
           hou += np.log(input[i][target[i]])
       output += -hou
   return np.around(output / length, 4)
print(cross_entorpy(input, target))
#输出 3.8162

我们按照官方给的CE Loss和根据公式得到的答案并不相同,说明公式是有问题的。

正确公式

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

实现代码如下

import torch
import torch.nn as nn
import math
import numpy as np

entroy=nn.CrossEntropyLoss()
input=torch.Tensor([[0.1234, 0.5555,0.3211],[0.1234, 0.5555,0.3211],[0.1234, 0.5555,0.3211],])
target = torch.tensor([0,1,2])
output = entroy(input, target)
print(output)
#输出 tensor(1.1142)
#%%
input=np.array(input)
target = np.array(target)
def cross_entorpy(input, target):
   output = 0
   length = len(target)
   for i in range(length):
       hou = 0
       for j in input[i]:
           hou += np.exp(j)
       output += -input[i][target[i]] + np.log(hou)
   return np.around(output / length, 4)
print(cross_entorpy(input, target))
#输出 1.1142

对比自己实现的公式和官方给出的结果,可以验证公式的正确性。

观察公式可以发现其实nn.CrossEntropyLoss()是nn.logSoftmax()和nn.NLLLoss()的整合版本。

nn.logSoftmax(),公式如下

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

nn.NLLLoss(),公式如下

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

将nn.logSoftmax()作为变量带入nn.NLLLoss()可得

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

因为

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

可看做一个常量,故上式可化简为:

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

对比nn.Cross Entropy Loss公式,结果显而易见。

验证代码如下。

import torch
import torch.nn as nn
import math
import numpy as np

entroy=nn.CrossEntropyLoss()
input=torch.Tensor([[0.1234, 0.5555,0.3211],[0.1234, 0.5555,0.3211],[0.1234, 0.5555,0.3211],])
target = torch.tensor([0,1,2])
output = entroy(input, target)
print(output)
# 输出为tensor(1.1142)
m = nn.LogSoftmax()
loss = nn.NLLLoss()
input=m(input)
output = loss(input, target)
print(output)
# 输出为tensor(1.1142)

综上,可得两个结论

1.nn.Cross Entropy Loss的公式。

PyTorch基础之torch.nn.CrossEntropyLoss交叉熵损失

2.nn.Cross Entropy Loss为nn.logSoftmax()和nn.NLLLoss()的整合版本。

来源:https://blog.csdn.net/u012633319/article/details/111093144

标签:PyTorch,torch.nn.CrossEntropyLoss,交叉熵损失
0
投稿

猜你喜欢

  • SQL Server数据库简体繁体数据混用的问题

    2008-12-05 16:07:00
  • SQL server不支持utf8 php却用utf8的矛盾问题解决方法

    2023-07-20 12:01:28
  • asp中InstrRev的语法

    2008-01-22 18:14:00
  • Python如何实现强制数据类型转换

    2022-10-18 10:08:02
  • 如何理解Python中包的引入

    2021-08-14 11:42:31
  • Python 元组(Tuple)操作详解

    2023-06-28 15:36:39
  • 解决tensorflow训练时内存持续增加并占满的问题

    2021-09-24 02:48:05
  • Python模块的制作方法实例分析

    2021-09-06 05:57:26
  • Django之创建引擎索引报错及解决详解

    2023-06-11 10:55:15
  • 分享一些可视信息设计资源

    2009-10-06 15:19:00
  • Python list与NumPy array 区分详解

    2021-08-25 04:12:37
  • Linux 自动备份oracle数据库详解

    2023-07-14 08:11:41
  • 帮助你分析MySQL的数据类型以及建库策略

    2009-02-23 17:39:00
  • 关于Thinkphp6的日志问题

    2023-06-06 10:54:23
  • SQL Servr 2008空间数据应用系列四:基础空间对象与函数应用

    2011-02-23 15:01:00
  • 为什么首页最后设计

    2009-07-17 19:03:00
  • python黑魔法之编码转换

    2022-08-11 10:03:41
  • python 使用csv模块读写csv格式文件的示例

    2021-04-24 15:58:28
  • python利用MethodType绑定方法到类示例代码

    2023-08-23 08:07:31
  • PHP商品秒杀问题解决方案实例详解【mysql与redis】

    2023-09-27 10:49:04
  • asp之家 网络编程 m.aspxhome.com