from torch import nn
import torch
# nllloss首先需要初始化
nllloss = nn.NLLLoss() # 可选参数中有 reduction='mean', 'sum', 默认mean
在使用nllloss时,需要有两个张量,一个是预测向量,一个是label
predict = torch.Tensor([[2, 3, 1]]) # shape: (n, category)
label = torch.tensor([1]) # shape: (n,)
#
predict = torch.Tensor([[2, 3, 1]])
label = torch.tensor([1])
nllloss(predict, label)
# output: tensor(-3.)
nllloss对两个向量的操作为,将predict中的向量,在label中对应的index取出,并取负号输出。label中为1,则取2,3,1中的第1位3,取负号后输出。
2. predict shape为(n, category)的情况
predict = torch.Tensor([[2, 3, 1],
[3, 7, 9]])
label = torch.tensor([1, 2])
nllloss(predict, label)
# output: tensor(-6)
nllloss对两个向量的操作为,继续将predict中的向量,在label中对应的index取出,并取负号输出。label中为1,则取2,3,1中的第1位3,label第二位为2,则取出3,7,9的第2位9,将两数取平均后加负号后输出。
这时就可以看到最开始的nllloss初始化的时候,如果参数reduction取'mean',就是上述结果。如果reduction取'sum',那么各行取出对应的结果,就是取sum后输出,如下所示:
nllloss = nn.NLLLoss( reduction='sum')
predict = torch.Tensor([[2, 3, 1],
[3, 7, 9]])
label = torch.tensor([1, 2])
nllloss(predict, label)
# output: tensor(-12)
torch.nn.CrossEntropyLoss相当于softmax + log + nllloss。
上面的例子中,预测的概率大于1明显不符合预期,可以使用softmax归一,取log后是交叉熵,取负号是为了符合loss越小,预测概率越大。
所以使用nll loss时,可以这样操作
nllloss = nn.NLLLoss()
predict = torch.Tensor([[2, 3, 1],
[3, 7, 9]])
predict = torch.log(torch.softmax(predict, dim=-1))
label = torch.tensor([1, 2])
nllloss(predict, label)
# output: tensor(0.2684)
而使用torch.nn.CrossEntropyLoss可以省去softmax + log
cross_loss = nn.CrossEntropyLoss()
predict = torch.Tensor([[2, 3, 1],
[3, 7, 9]])
label = torch.tensor([1, 2])
cross_loss(predict, label)
# output: tensor(0.2684)