目录
- 1 交叉熵损失函数
- 2 二元交叉熵损失函数
-
- 2.1 torch.nn.BCELoss()
- 2.2 torch.nn.BCEWithLogitsLoss()
- 3 参考文献
1 交叉熵损失函数 ??在之前的损失函数介绍中已经解释过,什么是交叉熵损失函数以及其数学原理(【Pytorch基础】torch.nn.CrossEntropyLoss损失函数介绍)。在多分类问题中输出层的函数是 S o f t m a x Softmax Softmax函数, 在二分类问题中输出层的函数是 S i g m o d Sigmod Sigmod函数。
??而CrossEntropy损失函数适用于总共有N个类别的分类。当N=2时,即二分类任务,只需要判断是还是否的情况,就可以使用二分类交叉熵损失,本小节介绍二分类交叉熵损失函数。
2 二元交叉熵损失函数 2.1 torch.nn.BCELoss() ??BCELoss的全称是Binary Cross Entropy, 即二分类交叉熵损失。如下公式 (y是真实标签,x是预测值):
L o s s = ? 1 N ∑ i = 1 N [ y i log ? ( p i ) + ( 1 ? y i ) log ? ( 1 ? p i ) ] Loss=-\frac{1}{N} \sum_{i=1}^{N}\left[y_{i} \log \left(p_{i}\right)+\left(1-y_{i}\right) \log \left(1-p_{i}\right)\right] Loss=?N1?i=1∑N?[yi?log(pi?)+(1?yi?)log(1?pi?)]
其实这个函数就是CrossEntropyLoss的当类别数N=2时候的特例。因为类别数为2,属于第一类的概率为y,那么属于第二类的概率自然就是(1-y)。因此套用与CrossEntropy损失的计算方法,用对应的标签乘以对应的预测值再求和,就得到了最终的损失。参考文献【3】
(在我自己的问题中二元交叉熵损失函数针对的是单标签二分类问题)关于单标签二分类和多标签二分类对于torch.nn.BCELoss()的使用见参考文献【4】【5】。
其中, N N N是总样本数, y i y_{i} yi?是第 i i i个样本的所属类别, p i p_{i} pi?是第 i i i个样本的预测值,一般来说,它是一个概率值。
举个例子: y i = [ 1 , 0 , 0 ] , p i = [ 0.8 , 0.2 , 0.4 ] y_{i}=[1, 0, 0], p_{i}=[0.8, 0.2, 0.4] yi?=[1,0,0],pi?=[0.8,0.2,0.4]例子来着参考文献【5】
L = ? 1 3 [ ( 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 ) ) ] = 0.319 L=-\frac{1}{3}[(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))]=0.319 L=?31?[(1?log0.8+(1?1)?log(1?0.8))+(0?log0.2+(1?0)?log(1?0.2))+(0?log0.4+(1?0)?log(1?0.4))]=0.319
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 nnbce_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中的预测值应该是个概率 p i p_{i} pi?。
上面的栗子直接给出了预测的 p i p_{i} pi?,这是符合要求的。但在更一般的二分类问题中,网络的输出取值是整个实数域(可正可负可为0)。
??为了由这种输出值得到对应的 p i p_{i} pi?,你可以在网络的输出层之后新加一个Sigmoid层,这样便可以将输出值的取值规范到0和1之间,这就是交叉熵公式中的 p i p_{i} pi?。
当然,可以不更改网络输出,而是在将输出值送入交叉熵公式进行性计算之前,手动用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 nnbce_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)”“”
3 参考文献 【pytorch|【Pytorch基础】torch.nn.BCELoss()和torch.nn.BCEWithLogitsLoss()损失函数】[1]pytorch nn.BCELoss()详解
[2]pytorch二分类损失函数BCEWithLogitsLoss
[3]Pytorch常用损失函数拆解
[4]loss函数之BCELoss
[5](七)详解pytorch中的交叉熵损失函数nn.BCELoss()、nn.BCELossWithLogits(),二分类任务如何定义损失函数,如何计算准确率、如何预测
推荐阅读
- 深度学习|torch 循环神经网络torch.nn.RNN()和 torch.nn.RNNCell()
- 【Pytorch学习】|torch.nn.init常用函数总结
- 笔记|PyVis|神经网络数据集的可视化
- 游戏|[转]JS游戏引擎 & HTML5
- Python|【21天Python进阶学习挑战赛】[day18-19]爬虫解析器BeautifulSoup4
- python|python numpy库作用_python数据分析之numpy库
- 开发|python数据分析之Numpy
- python数据分析|【python数据分析】numpy创建数组
- python|OpenCV中图像形态学操作