目录

  • 1 交叉熵损失函数
  • 2 二元交叉熵损失函数
  • 2.1 torch.nn.BCELoss()
  • 2.2 torch.nn.BCEWithLogitsLoss()
  • 3 参考文献


1 交叉熵损失函数

  在之前的损失函数介绍中已经解释过,什么是交叉熵损失函数以及其数学原理(【Pytorch基础】torch.nn.CrossEntropyLoss损失函数介绍)。在多分类问题中输出层的函数是pytorch交叉熵怎么算 pytorch二分类交叉熵_pytorch交叉熵怎么算函数, 在二分类问题中输出层的函数是pytorch交叉熵怎么算 pytorch二分类交叉熵_深度学习_02函数。

  而CrossEntropy损失函数适用于总共有N个类别的分类。当N=2时,即二分类任务,只需要判断是还是否的情况,就可以使用二分类交叉熵损失,本小节介绍二分类交叉熵损失函数。

2 二元交叉熵损失函数

2.1 torch.nn.BCELoss()

  BCELoss的全称是Binary Cross Entropy, 即二分类交叉熵损失。如下公式 (y是真实标签,x是预测值):
pytorch交叉熵怎么算 pytorch二分类交叉熵_pytorch交叉熵怎么算_03
其实这个函数就是CrossEntropyLoss的当类别数N=2时候的特例。因为类别数为2,属于第一类的概率为y,那么属于第二类的概率自然就是(1-y)。因此套用与CrossEntropy损失的计算方法,用对应的标签乘以对应的预测值再求和,就得到了最终的损失。参考文献【3】
在我自己的问题中二元交叉熵损失函数针对的是单标签二分类问题)关于单标签二分类和多标签二分类对于torch.nn.BCELoss()的使用见参考文献【4】【5】。
其中,pytorch交叉熵怎么算 pytorch二分类交叉熵_pytorch交叉熵怎么算_04是总样本数,pytorch交叉熵怎么算 pytorch二分类交叉熵_python_05是第pytorch交叉熵怎么算 pytorch二分类交叉熵_pytorch交叉熵怎么算_06个样本的所属类别,pytorch交叉熵怎么算 pytorch二分类交叉熵_损失函数_07是第pytorch交叉熵怎么算 pytorch二分类交叉熵_pytorch交叉熵怎么算_06个样本的预测值,一般来说,它是一个概率值。
举个例子:pytorch交叉熵怎么算 pytorch二分类交叉熵_深度学习_09例子来着参考文献【5】
pytorch交叉熵怎么算 pytorch二分类交叉熵_深度学习_10

from math import log
loss = ((1*log(0.8) + (1-1)*log(1-0.8)) + (0*log(0.2)+(1-0)*log(1-0.2)) + (0*log(0.4)+(1-0)*log(1-0.4))) / -3
print(loss)
0.3190375754648034

其实,在PyTorch中已经内置了BCELoss,它的主要用途是计算二分类问题的交叉熵,我们可以调用该方法,并将结果与上面手动计算的结果做个比较:

import torch
import torch.nn as nn

bce_loss = nn.BCELoss()
pred_pro = torch.tensor([0.8, 0.2, 0.4], dtype=torch.float)
label = torch.tensor([1, 0, 0], dtype=torch.float)

print(bce_loss(pred_pro, label))

tensor(0.3190)

需要注意的是,输入BCELoss中的预测值应该是个概率pytorch交叉熵怎么算 pytorch二分类交叉熵_损失函数_07

上面的栗子直接给出了预测的pytorch交叉熵怎么算 pytorch二分类交叉熵_损失函数_07,这是符合要求的。但在更一般的二分类问题中,网络的输出取值是整个实数域(可正可负可为0)
  为了由这种输出值得到对应的pytorch交叉熵怎么算 pytorch二分类交叉熵_损失函数_07,你可以在网络的输出层之后新加一个Sigmoid层,这样便可以将输出值的取值规范到0和1之间,这就是交叉熵公式中的pytorch交叉熵怎么算 pytorch二分类交叉熵_损失函数_07
当然,可以不更改网络输出,而是在将输出值送入交叉熵公式进行性计算之前,手动用Simgmoid函数做一个映射。
  在PyTorch中,提供了BCEWithLogitsLoss方法,它可以直接将输入的值规范到0和1 之间,相当于将Sigmoid和BCELoss集成在了一个方法中。

2.2 torch.nn.BCEWithLogitsLoss()

举个例子来具体进行说明:假设pred是shape为[4,1]的tensor,其中4代表样本个数,2代表该样本分别属于两个类别的概率(前提是规范到了0和1之间,否则就是两个实数域上的值,记住,现在我们讨论的是二分类);target是shape为[4]的tensor,4即样本数。

import torch
import torch.nn as nn

bce_loss = nn.BCELoss()

pred = torch.randn(4, 1)  # 预测值
print("pred", pred)
target = torch.rand(4).random_(0, 2)  # 真实类别标签
print("target", target)
# 将target进行独热编码
onehot_target = torch.eye(2)[target.long(), :]
print("onehot_target", onehot_target)

sigmoid = nn.Sigmoid()
sigmoid_pred = sigmoid(pred)
print("sigmoid_pred", sigmoid_pred)

loss1 = bce_loss(sigmoid_pred, target.view(4, -1))
print(loss1)

bce_loss2 = nn.BCEWithLogitsLoss()
loss2 = bce_loss2(pred, target.view(4, -1))
print(loss2)
“”“
pred tensor([[ 0.8269],
        [-0.7197],
        [-0.6237],
        [ 0.1657]])
target tensor([0., 0., 0., 1.])
onehot_target tensor([[1., 0.],
        [1., 0.],
        [1., 0.],
        [0., 1.]])
sigmoid_pred tensor([[0.6957],
        [0.3275],
        [0.3489],
        [0.5413]])
tensor(0.6573)
tensor(0.6573)

”“”