CrossEntropyLoss的作用相当于将nn.LogSoftmax()和nn.NLLLoss()结合在一起,nn.LogSoftmax()相当于先对输入矩阵计算softmax值,然后取log。举例说明这几个函数的功能:
(1)使用nn.Softmax() + torch.log()来模拟nn.LogSoftmax()
import torch
import torch.nn as nn
# 随机生成输入
input = torch.randn(3, 3)
print("输入矩阵:\n", input)
label = torch.tensor([1, 2, 0])
# (1)使用nn.Softmax() + torch.log()来模拟nn.LogSoftmax()
# 对输入值计算softmax值
softmax = nn.Softmax(dim=1)
softmax_output = softmax(input)
print("输入矩阵的softmax值: \n", softmax_output)
# 对softmax值取log
log_output = torch.log(softmax_output)
print("对softmax值取log: \n", log_output)
# 输出结果如下:
输入矩阵:
tensor([[-0.8842, -0.4118, 0.6773],
[-0.5324, -1.1168, -0.3089],
[-0.5324, 1.9512, 1.6705]])
输入矩阵的softmax值:
tensor([[0.1357, 0.2176, 0.6467],
[0.3561, 0.1985, 0.4453],
[0.0454, 0.5439, 0.4108]])
对softmax值取log:
tensor([[-1.9974, -1.5250, -0.4359],
[-1.0324, -1.6168, -0.8089],
[-3.0927, -0.6091, -0.8898]])
# 对输入值直接使用nn.LogSoftmax()
log_softmax = nn.LogSoftmax(dim=1)
log_softmax_output = log_softmax(input)
print("nn.LogSoftmaxloss的输出结果: \n", log_softmax_output)
# 输出结果如下:
nn.LogSoftmaxloss的输出结果:
tensor([[-1.9974, -1.5250, -0.4359],
[-1.0324, -1.6168, -0.8089],
[-3.0927, -0.6091, -0.8898]])
上面两段代码的输出结果是相同的,所以使用nn.Softmax() + torch.log()可以实现nn.LogSoftmax()的功能
(2)使用nn.LogSoftmax()和nn.NLLLoss()[负对数似然函数]来模拟nn.CrossEntropyLoss()
# 使用nn.LogSoftmax()和nn.NLLLoss()
nllloss = nn.NLLLoss()
nllloss_output = nllloss(log_softmax_output, label)
print("NLLLoss的输出结果:\n", nllloss_output)
# 输出结果
NLLLoss的输出结果:
tensor(1.8089)
那么NLLLoss的输出结果是如何计算的呢?
NLLLoss的结果就是把LogSoftmax的输出与Label对应的那个值拿出来,再去掉负号,再求均值。即 (1.5250+0.8089+3.0927)/3=1.8089
# 使用nn.CrossEntropyLoss()
cross_entropyloss = nn.CrossEntropyLoss()
cross_entropyloss_output = cross_entropyloss(input, label)
print("CrossEntropyLoss的输出结果:\n", cross_entropyloss_output)
# 输出结果
CrossEntropyLoss的输出结果:
tensor(1.8089)
上面两段代码的输出结果是相同的,所以可以使用nn.LogSoftmax()和nn.NLLLoss()来模拟nn.CrossEntropyLoss()。
总结:
Pytorch中CrossEntropyLoss()函数的主要是将softmax-log-NLLLoss合并到一块得到的结果。
计算输入input和target中每个元素的平均绝对误差(mean absolute error [MAE]),input和target都是有着n个向量的认识形状的张量,二者形状相同。举例如下:
input = torch.randn((1, 2))
print("input\n", input)
target = torch.randn((1, 2))
print("target\n", target)
l1loss = nn.L1Loss()
l1loss_output = l1loss(input, target)
print("L1Loss输出:\n", l1loss_output)
# 输出结果
input
tensor([[-0.3591, -1.1398]])
target
tensor([[-0.1370, -0.8672]])
L1Loss输出:
tensor(0.2474)
输出结果计算:(|-0.3591-(-0.1370)| + |-1.1398-(-0.8672)|) = 0.2474
计算输入input和target中每个元素的均方误差(mean squared error [MSE]),input和target形状相同。举例如下:
input = torch.randn((1, 2))
print("input\n", input)
target = torch.randn((1, 2))
print("target\n", target)
mseloss = nn.MSELoss()
mseloss_output = mseloss(input, target)
print("MSELoss输出:\n", mseloss_output)
# 输出结果
input
tensor([[0.3812, 1.2124]])
target
tensor([[ 1.1891, -0.2384]])
MSELoss输出:
tensor(1.3788)
输出结果计算:[(0.3812-1.1891)² + (1.2124-(-0.2384))²] / 2 = 1.3788
输入input和target形状相同,公式如下:
当预测值和ground truth差别较小的时候(绝对值差小于1),其实使用的是L2 Loss;而当差别大的时候,是L1 Loss的平移。SooothL1Loss其实是L2Loss和L1Loss的结合,它同时拥有L2 Loss和L1 Loss的部分优点。