Pytorch详解NLLLoss和CrossEntropyLoss、以及softmax和log_softmax

数据

import torch
import torch.nn.functional as F
import numpy as np

# 随机新建3个样例数据,每个样例数据包含4个属性特征
input = torch.randn(3,4)
tensor([[ 0.0054, -0.8030, -0.5758, -0.6518],
        [-0.5518,  0.3904,  0.5296,  0.4973],
        [ 0.1608,  0.5822,  0.9536, -0.3173]])

softmax

使用softmax对数据进行处理:

F.softmax(input, dim=1)

dim=1表示跨列操作,行数不变。输出结果:

tensor([[0.3963, 0.1766, 0.2216, 0.2054],
        [0.1067, 0.2738, 0.3147, 0.3047],
        [0.1868, 0.2847, 0.4127, 0.1158]])

每一行元素相加为1.

log_softmax

使用log_softmax进行处理:

F.log_softmax(input, dim=1)

输出结果:

tensor([[-0.9255, -1.7339, -1.5067, -1.5827],
        [-2.2375, -1.2953, -1.1561, -1.1883],
        [-1.6778, -1.2564, -0.8850, -2.1558]])

softmax和log_softmax联系

log_softmax相当于对softmax做了log操作,下面进行验证:

# 首先将tensor类型转为numpy类型
np_data = F.softmax(input, dim=1).data.numpy()
np.log(np_data)

输出结果为:

array([[-0.9255125 , -1.7338518 , -1.5066911 , -1.5826656 ],
       [-2.2374916 , -1.2952974 , -1.1560525 , -1.1883242 ],
       [-1.6778362 , -1.2563533 , -0.88496906, -2.155847  ]],
      dtype=float32)

可以看出与log_softmax的结果一致,log_softmax就是对softmax的结果做了log
softmax将数值压缩至0~1,而log_softmax将数据压缩至负无穷~0

NLLLoss

NLLLoss的结果就是把上面的输出与Label对应的那个值拿出来,再去掉负号,再求均值。

NLLLoss的输入是一个log_softmax和一个目标label

假设我们的数据正确的label是[0,2,3],第一行取第0个元素,第二行取第2个,第三行取第3个,去掉负号,得到[0.9255125,1.1560525,2.155847],然后求平均,结果是:(0.9255125+1.1560525 + 2.155847)/3=1.4124706666666667

下面使用NLLLoss函数验证一下:

target = torch.tensor([0,2,3])
loss = F.nll_loss(F.log_softmax(input, dim=1),target)

得到loss=tensor(1.4125)
结果一致。

CrossEntropyLoss

交叉熵的计算公式为:
c r o s s e n t r o p y = − ∑ k = 1 N ( p k ∗ l o g q k ) cross_entropy=-\sum_{k=1}^N(p_k*log q_k) crossentropy=k=1N(pklogqk)

其中 p p p表示真实值,在这个公式中是one-hot形式; q q q是预测值,在这里假设已经是经过 s o f t m a x softmax softmax后的结果了。

仔细观察可以知道,因为 p p p的元素不是0就是1,而且又是乘法,所以很自然地我们如果知道1所对应的index,那么就不用做其他无意义的运算了。所以在pytorch代码中target不是以one-hot形式表示的,而是直接用scalar表示。所以交叉熵的公式(m表示真实类别)可变形为:
c r o s s _ e n t r o p y = − ∑ k = 1 N ( p k ∗ l o g q k ) = − ∑ k = 1 N q m cross\_entropy=-\sum_{k=1}^N(p_k*log q_k)=-\sum_{k=1}^Nq_m cross_entropy=k=1N(pklogqk)=k=1Nqm
仔细看看,是不是就是等同于log_softmax和nll_loss两个步骤。

CrossEntropyLoss就是把以上Softmax–Log–NLLLoss合并成一步,我们用刚刚随机出来的input直接验证一下结果是不是1.4125

F.cross_entropy(input,target)

输出结果为tensor(1.4125),结果一致

猜你喜欢

转载自blog.csdn.net/vincent_duan/article/details/120058440