损失函数 - Pytorch中的CrossEntropyLoss vs BCELoss;Softmax vs Sigmoid;损失计算

本文探讨了CrossEntropyLoss与BCELoss在多类和二元分类任务中的区别,包括用途、实施细节和实际应用。CrossEntropyLoss适用于多类,BCELoss专为二元分类设计,强调了sigmoid与softmax在输出概率上的角色。Pytorch中推荐BCEWithLogitsLoss和CrossEntropyLoss的使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CrossEntropyLoss vs BCELoss

1. 用途差异

  • CrossEntropyLoss主要用于多类分类,二元分类是可行的
  • BCE 代表 二进制交叉熵,用于二元分类
  • 那么,为了简单起见,我们为什么不对所有情况都使用CrossEntropyLoss呢?答案在 (3)

2. 细节实施的差异

  • 当 CrossEntropyLoss 用于二元分类时,它需要 2 个输出要素。例如。logits=[-2.34, 3.45], Argmax(logits) →class 1
  • 当 BCEloss 用于二元分类时,它需要 1 个输出特征。例如 1.logits=[-2.34]<0 →class 0;例如 2.logits=[3.45] >0→类 1

3. 目的差异(在实践中)

  • 一个主要的区别是,如果要生成输出作为概率的一种形式,则应使用BCE。

  • 这是因为我们可以使用 sigmoid 来处理单个输出,同时使用 BCELoss 作为损失函数。例如 1.σ(-2.34)=p₁=8.79%(输出为1类的概率为8.79%,p₀=1–8.79%=91.21%,因此很可能是0类);例如 2.σ(3.45)=p₁=96.9%(可能是1级)

  • 我们不能将sigmoid用于2个输出特征,而使用CrossEntropyLoss作为损失函数。σ([-2.34, 3.45])=[8.79%, 96.9%]没有意义。这并不意味着 p₀=8.79%(如果是这样,p₁=1–8.79%=91.21%)。它也不意味着 p₁=96.9%。

  • 对于CrossEntropyLoss,softmax是获取概率输出的更合适的方法。但是,对于只有 2 个值的二元分类,softmax 的输出将始终基于其公式类似于 [0.1%,99.9%] 或 [99.9%,0.1%]。例如。softmax([-2,34, 3,45])=[0.3%, 99.7%]。它不代表有意义的概率。
    在这里插入图片描述

  • 所以 softmax 只适合多类分类。

以上导致 — Sigmoid vs softmax

  • 输出处的 Sigmoid 更适合二元分类。(可能也适用于多标签分类)。
  • 输出端Softmax更适合多类分类

对于 BCE,请使用 BCEWithLogitsLoss();对于 CE,请使用 CrossEntropyLoss()

  • 使用BCEWithLogitsLoss()而不是BCELoss(),因为前者已经包含一个sigmoid层。因此,您可以直接在损失函数中传递对数。技术原因:

这个版本在数值上比使用普通的Sigmoid后跟BCELoss更稳定,因为通过将运算组合成一层,我们利用对数-和-exp技巧来获得数值稳定性。(参考)

  • CrossEntropyLoss() 已经包含了一个 softmax 层。

Pytorch 中的损失计算

  • 对于 pytorch 中的损失计算(BCEWithLogitsLoss() 或 CrossEntropyLoss()),损失输出 loss.item() 是加载批次中每个样本的平均损失
  • 因此,每批的总损失=损失*batch_size=loss.item()*x.size(0),整个数据集的平均损失将为total_loss/total_size
  • 当在同一地块中绘制train_loss和val_loss时,这将非常有用。您可能希望以有意义的比例比较训练集和 val 集的损失,因为训练集和 val 集的数据大小通常不同。平均损失将是最合适的。
train_loss = 0
criterion = nn.BCEWithLogitsLoss()
for step, (x, y) in enumerate(train_loader):
    model.train()
    logits = model(x)
    loss = criterion(logits, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    train_loss += loss.item()*x.size(0)
ave_loss = train_loss/len(train_loader.dataset)
### PyTorchCrossEntropyLossBCELoss区别 #### CrossEntropyLoss适用场景 对于多分类问题,`torch.nn.CrossEntropyLoss` 是更为常见的选择。该损失函数适用于具有多个类别的单标签分类任务,在这种情况下,每个样本只属于一个类别。此函数内部实现了softmax层加上负对数似然损失(NLL),这意味着输入不需要预先通过softmax处理[^1]。 ```python import torch import torch.nn as nn criterion = nn.CrossEntropyLoss() output = torch.randn(4, 5, requires_grad=True) # batch_size=4, num_classes=5 target = torch.empty(4, dtype=torch.long).random_(5) loss = criterion(output, target) print(loss.item()) ``` #### BCELoss适用场景 另一方面,二元交叉熵损失(`torch.nn.BCELoss`)用于解决二分类或多标签分类问题。当面对的是多标签情况时——即允许一个实例可以归属于超过一个类别的情况,则应该采用这个损失函数。值得注意的是,使用`BCELoss`前需确保网络输出已经过sigmoid激活函数转换成概率形式[^2]。 ```python criterion = nn.BCELoss() input = torch.sigmoid(torch.randn((3, 2), requires_grad=True)) # 假设有三个样例两个标签 target = torch.tensor([[0., 1.], [1., 0.], [1., 1.]]) loss = criterion(input, target) print(loss.item()) ``` #### 主要差异总结 - **应用场景**: `CrossEntropyLoss`针对单一真实标签的多分类;而`BCELoss`适合于二分类以及允许多个正类别的多标签设置。 - **预处理需求**: 使用`CrossEntropyLoss`时不必显式应用softmax变换;相反地,利用`BCELoss`之前则通常需要先经过sigmoid运算来获得每种类别上的独立概率估计值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值