交叉熵
交叉熵
假设有两个分布
可以看出,交叉熵与相对熵仅相差了
两者的交叉熵为:
对所有训练样本取均值得:
这个结果与通过最大似然估计方法求出来的结果一致。
Cross Entropy Loss
Cross Entropy Loss 是非常重要的损失函数,也是应用最多的损失函数之一。二分类问题的交叉熵 Loss 主要有两种形式,下面分别详细介绍。
第一种形式是基于输出标签 label 的表示方式为
注意公式中
推导:
从最大似然性的角度出发,预测类别的概率可以写成:
当真实标签
当真实标签
因为
我们希望
当
从图中明显能够看出,
当
从图中明显能够看出,
第二种形式是基于输出标签 label 的表示方式为
从概率角度来看,预测类别的概率可以写成:
接下来,同样引入
以
其实上面介绍的两种形式的交叉熵 Loss 是一样的,只不过由于标签 label 的表示方式不同,公式稍有变化。标签用
特点:
- 本质上也是一种对数似然函数,可用于二分类和多分类任务中。
二分类问题中的 loss 函数(输入数据是 softmax 或者 sigmoid 函数的输出):
多分类问题中的 loss 函数(输入数据是 softmax 或者 sigmoid 函数的输出):
- 当使用 sigmoid 作为激活函数的时候,常用交叉熵损失函数而不用均方误差损失函数,因为它可以完美解决平方损失函数权重更新过慢的问题,具有“误差大的时候,权重更新快;误差小的时候,权重更新慢”的良好性质。
F.cross_entropy()
F.cross_entropy
是 PyTorch 中用于计算交叉熵损失的函数,常用于分类任务中。交叉熵损失函数是一种衡量预测分布与真实分布之间差异的常用方法,特别适合分类任务。
基本公式
交叉熵损失的公式如下:
其中:
是真实标签(通常是独热编码或整数形式)。 是预测的类别概率,由模型输出的 logits(未归一化的分数)经过 softmax 得到。
PyTorch中的实现
F.cross_entropy
集成了以下几个步骤:
- Logits 计算:它接收的模型输出通常是 logits(未归一化的分数),而不是直接的概率分布。
- Softmax 转换:函数内部会对 logits 应用 softmax 操作,得到每个类别的预测概率。
- 负对数似然计算:对预测概率取对数后,根据真实标签计算负对数似然。
- 损失输出:最终返回平均损失值(或总损失,取决于设置)。
函数签名
torch.nn.functional.cross_entropy(
input,
target,
weight=None,
size_average=None,
ignore_index=-100,
reduce=None,
reduction='mean',
label_smoothing=0.0
)
2
3
4
5
6
7
8
9
10
参数说明:
input
:模型的输出 logits,形状为或 ,其中: 是批次大小。 是类别数。
target
:真实标签,形状为或 。它是每个样本的整数类别索引(非独热编码)。 weight
:类别权重(可选),用于平衡类别不平衡的问题。形状为。 ignore_index
:忽略特定类别的索引(可选),用于标记不参与损失计算的样本。reduction
:指定如何对每个样本的损失进行汇总。可选值:'mean'
(默认):返回损失的平均值。'sum'
:返回损失的总和。'none'
:返回每个样本的单独损失值。
label_smoothing
:标签平滑系数(可选)。若,将真实标签的分布平滑为非零值。
示例代码
- 简单分类任务
import torch
import torch.nn.functional as F
# 模拟 logits 和真实标签
logits = torch.tensor([[1.0, 2.0, 3.0], [1.0, 2.0, 0.5]]) # 2 个样本,3 个类别
targets = torch.tensor([2, 1]) # 样本真实类别索引
# 计算交叉熵损失
loss = F.cross_entropy(logits, targets)
print("Cross-Entropy Loss:", loss.item())
2
3
4
5
6
7
8
9
10
- 使用类别权重
weights = torch.tensor([1.0, 2.0, 0.5]) # 设置类别权重
loss = F.cross_entropy(logits, targets, weight=weights)
print("Weighted Loss:", loss.item())
2
3
- 忽略某些类别
targets = torch.tensor([2, -100]) # 第二个样本的标签被忽略
loss = F.cross_entropy(logits, targets, ignore_index=-100)
print("Loss with Ignored Index:", loss.item())
2
3
常见问题与注意事项
input
应为 logits 而非概率:- 如果提供的是已经经过 softmax 的概率,则会导致结果不正确。
target
应为整数标签:- 如果需要支持独热编码标签,可以考虑其他损失函数(如
torch.nn.BCELoss
或torch.nn.BCEWithLogitsLoss
)。
- 如果需要支持独热编码标签,可以考虑其他损失函数(如
- 类别不平衡问题:
- 如果类别不平衡,建议使用
weight
参数为不同类别设置权重。
- 如果类别不平衡,建议使用
通过 F.cross_entropy
,可以高效地计算分类任务中的损失,同时支持许多定制化选项,适应各种需求。
BCEWithLogitsLoss
where
This is used for measuring the error of a reconstruction in for example an auto-encoder. Note that the targets
weight
: pytorch 官方对 weight 给出的解释,if provided it’s repeated to match input tensor shape,就是给出 weight 参数后,会将其 shape 和 input 的 shape 相匹配。
BCEWithLogitsLoss
是 PyTorch 中用于二分类任务的一个损失函数,它结合了 sigmoid 层和二元交叉熵损失(Binary Cross Entropy Loss)。在训练模型时,我们通常会得到模型的原始输出(logits),即未经过 sigmoid 激活的分数。BCEWithLogitsLoss
允许我们直接将这些 logits 作为输入,并在内部进行 sigmoid 操作后再计算二元交叉熵损失。
数学上,BCEWithLogitsLoss
的计算可以分为两步:
Sigmoid 操作:首先,对 logits 应用 sigmoid 函数来得到概率预测值。
其中
是 logits, 是经过 sigmoid 激活后的概率预测值。 二元交叉熵损失:然后,使用得到的概率预测值
和真实标签 (通常为 0 或 1)来计算二元交叉熵损失。 其中
表示样本索引, 是真实标签, 是预测概率。
将这两步结合起来,BCEWithLogitsLoss
的数学表达式可以看作是在内部进行了 sigmoid 操作后,再计算二元交叉熵损失。
在 PyTorch 的 BCEWithLogitsLoss
实现中,还有一个可选的权重参数 weight
和归约参数 reduction
(如 'none'
, 'mean'
, 'sum'
),用于调整损失的计算方式。权重参数 weight
可以用于处理类别不平衡的问题,而归约参数 reduction
则决定了损失是如何在批量样本上进行归约的(例如取平均或求和)。
binary_cross_entropy_with_logits
torch.nn.functional.binary_cross_entropy_with_logits(input, target, weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)
:
在 PyTorch 中,torch.nn.functional.binary_cross_entropy_with_logits
是一个用于计算二分类任务的交叉熵损失的函数,它结合了 logits(原始模型输出)和 sigmoid 操作,直接计算损失,而无需手动应用 sigmoid。下面是该函数的主要参数说明:
参数
- input (Tensor): 模型未经过 sigmoid 激活的原始输出(logits)。形状应为
(N, *)
,其中N
是批量大小,*
表示任何数量的额外维度。 - target (Tensor): 真实标签,与
input
有相同的形状(即(N, *)
),但数据类型应为long
。标签值应为 0 或 1。 - weight (Tensor, optional): 各类别的损失权重。它应该是一个形状为
(C,)
的 Tensor,其中C
是类别的数量(在二分类中通常为 1)。对于不平衡的数据集,可以通过为少数类别指定更大的权重来调整损失。 - size_average (bool, optional): 是否计算每个 mini-batch 损失的平均值。在 PyTorch 的新版本中,此参数已被
reduction
替换。默认为True
。 - reduce (bool, optional): 是否对输出进行归约。在 PyTorch 的新版本中,此参数已被
reduction
替换。默认为True
。 - reduction (str, optional): 指定损失的归约类型。可选值为
'none' | 'mean' | 'sum'
。'none'
: 不进行归约,返回每个元素的损失;'mean'
: 输出损失的平均值;'sum'
: 输出损失的总和。默认值为'mean'
。 - pos_weight (Tensor, optional): 正样本的权重。如果给定,它必须是与
input
形状相同的 Tensor。
注意:在实际应用中,你通常会使用 torch.nn.BCEWithLogitsLoss
类作为损失函数的封装,而不是直接使用 torch.nn.functional.binary_cross_entropy_with_logits
函数。使用类的方式可以更方便地管理参数和状态。
binary_cross_entropy 与 binary_cross_entropy_with_logits 区别
有一个(类)损失函数名字中带了 with_logits. 而这里的 logits 指的是,该损失函数已经内部自带了计算 logit 的操作,无需在传入给这个 loss 函数之前手动使用 sigmoid/softmax 将之前网络的输入映射到[0,1]之间