交叉熵主要是用来判定实际的输出与期望的输出的接近程度,为什么这么说呢,举个例子:在做分类的训练的时候,如果一个样本属于第K类,那么这个类别所对应的输出节点的输出值应该为1,而其他节点的输出都为0,即[0,0,1,0,….0,0],这个数组也就是样本的Label,是神经网络最期望的输出结果。也就是说用它来衡量网络的输出与标签的差异,利用这种差异经过反向传播去更新网络参数。参考文献【1】
Pytorch常用的交叉熵损失函数CrossEntropyLoss()详解
交叉熵损失,是分类任务中最常用的一个损失函数。在Pytorch中是基于下面的公式实现的。
Loss ( x ^ , x ) = − ∑ i = 1 n x log ( x ^ ) \operatorname{Loss}(\hat{x}, x)=-\sum_{i=1}^{n} x \log (\hat{x}) Loss(x^,x)=−i=1∑nxlog(x^)
其中 x x x是真实标签, x ^ \hat{x} x^ 是预测的类分布(通常是使用softmax将模 型输出转换为概率分布)。
取单个样本举例, 假设 x 1 = [ 0 , 1 , 0 ] x_1=[0, 1, 0] x1=[0,1,0], 模型预测样本 x 1 x_1 x1的概率为 x 1 ^ = [ 0.1 , 0.5 , 0.4 ] \hat{x_1}=[0.1, 0.5, 0.4] x1^=[0.1,0.5,0.4](因为是分布, 所以属于各个类的和为1)。则样本的损失计算如下所示:
Loss ( x 1 ^ , x 1 ) = − 0 × log ( 0.1 ) − 1 × log ( 0.5 ) − 0 × log ( 0.4 ) = log ( 0.5 ) \operatorname{Loss}(\hat{x_1}, x_1)=-0 \times \log (0.1)-1 \times \log (0.5)-0 \times \log (0.4)=\log (0.5) Loss(x1^,x1)=−0×log(0.1)−1×log(0.5)−0×log(0.4)=log(0.5)
实际使用中需要注意几点:
输入的形式大概如下所示:
import torch
target = [1, 3, 2]
input_ = [[0.13, -0.18, 0.87],
[0.25, -0.04, 0.32],
[0.24, -0.54, 0.53]]
# 然后就将他们扔到CrossEntropyLoss函数中,就可以得到损失。
loss_item = torch.nn.CrossEntropyLoss()
loss = loss_item(input, target)
CrossEntropyLoss函数里面的实现,如下所示:
def forward(self, input, target):
return F.cross_entropy(input, target, weight=self.weight,
ignore_index=self.ignore_index, reduction=self.reduction)
是调用的torch.nn.functional(俗称F)中的cross_entropy()函数。
此处需要区分一下:torch.nn.Module 和 torch.nn.functional(俗称F)中损失函数的区别。Module的损失函数例如CrossEntropyLoss、NLLLoss等是封装之后的损失函数类,是一个类,因此其中的变量可以自动维护。经常是对F中的函数的封装。而F中的损失函数只是单纯的函数。
下面看一下F.cross_entropy函数
其中参数weight、ignore_index、reduction要在实例化CrossEntropyLoss对象时指定,例如:
loss = torch.nn.CrossEntropyLoss(reduction='none')
F中的cross_entropy的实现
return nll_loss(log_softmax(input, dim=1), target, weight, None, ignore_index, None, reduction)
可以看到就是先调用log_softmax,再调用nll_loss。log_softmax就是先softmax再取log。
[1]Pytorch常用损失函数拆解
[2]Pytorch常用的交叉熵损失函数CrossEntropyLoss()详解
[3]负对数似然(negative log-likelihood)