torch.nn.functional.cross_entropy使用
介绍
官网介绍:torch.nn.functional.cross_entropy
F.cross_entropy
是用于计算交叉熵损失函数的函数。它的输出是一个表示给定输入的损失值的张量。具体地说,F.cross_entropy
函数与nn.CrossEntropyLoss
类是相似的,但前者更适合于控制更多的细节,并且不需要像后者一样在前面添加一个Softmax层。
函数原型为:F.cross_entropy(input, target, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')
。
参数说明:
- input:(N, C)形状的张量,其中N为Batch_size,C为类别数。该参数对应于神经网络最后一个全连接层输出的未经Softmax处理的结果。
- target:一个大小为(N,)张量,其值是0 <= targets[i] <= C-1的元素,其中C是类别数。该参数包含一组给定的真实标签(ground truth)。
- weight:采用类别平衡的加权方式计算损失值。可以传入一个大小为(C,)张量,其中weight[j]是类别j的权重。默认为None。
- size_average:弃用,可以忽略。该参数已经被reduce参数取代了。
- ignore_index:指定被忽略的目标值的索引。如果目标值等于该索引,则不计算该样本的损失。默认值为-100,即不忽略任何目标值。
- reduce:指定返回的损失值的方式。可以是“None”(不返回损失值)、“mean”(返回样本损失值的平均值)和“sum”(返回样本损失值的总和)。默认值为“mean”。
- reduction:与reduce参数等价。表示返回的损失值的方式。默认值为“mean”。
计算过程
首先,我们有以下输入:
- predictions:一个2维tensor,表示模型的预测结果。它的形状是(2, 3),其中2是样本数量,3是类别数量。每一行对应一个样本的预测结果,每个元素表示该类别的概率。
predictions = torch.tensor([[0.304, 0.333, 0.363], [0.442, 0.279, 0.279]])
- labels:一个1维tensor,表示样本的真实标签。它的形状是(2,),其中2是样本数量。
labels = torch.tensor([2, 0])
在计算交叉熵损失之前,F.cross_entropy函数会对predictions进行softmax操作,以确保每行的元素和为1,并将其视为概率分布。在我们的示例中,predictions经过softmax操作后的结果为:
pred_softmax = torch.tensor([[0.3236, 0.3331, 0.3433],
[0.3705, 0.3148, 0.3148]])
接下来,我们定义了一个权重向量weights,用于指定每个类别的权重。在我们的示例中,权重向量为:
weights = torch.tensor([1.0, 2.0, 3.0])
然后,F.cross_entropy函数计算交叉熵损失。它首先计算每个样本的交叉熵损失,然后将所有样本的损失求平均。
对于第一个样本,它的预测结果为[0.304, 0.333, 0.363],真实标签为2。根据交叉熵损失的定义,我们可以计算出它的损失为:
-weights[2] * math.log(pred_softmax[0, 2])
其中log表示自然对数。在我们的示例中,根据权重和预测结果的计算,第一个样本的损失为:
-3.0 * math.log(0.3433) ≈ -3.0 * (-1.06915) ≈ 3.20745
对于第二个样本,它的预测结果为[0.442, 0.279, 0.279],真实标签为0。根据交叉熵损失的定义,我们可以计算出它的损失为:
-weights[0] * math.log(pred_softmax[1, 0])
在我们的示例中,根据权重和预测结果的计算,第二个样本的损失为:
-1.0 * math.log(0.3705) ≈ -1.0 * (-0.9929) ≈ 0.9929
最后,若reduction=‘none’,则不计算平均值;若reduction=‘mean’,则计算所有样本的损失求平均,得到最终的带权重的交叉熵损失值:
(3.20745 + 0.9929) / (1 + 3) ≈ 1.0500875
示例代码:
以下是一个示例代码,展示了如何使用weight参数来指定每个类别的权重:
import torch
import torch.nn.functional as F
import math
# 创建模型预测结果和真实标签
predictions = torch.tensor([[0.2, 0.3, 0.5], [0.8, 0.1, 0.1]])
labels = torch.tensor([2, 0])
# 定义每个类别的权重
weights = torch.tensor([1.0, 2.0, 3.0])
# 使用F.cross_entropy计算带权重的交叉熵损失
loss = F.cross_entropy(predictions, labels, weight=weights)
print(loss) # tensor(0.8773)
# 测试计算过程
pred = F.softmax(predictions, dim=1)
loss2 = -(3 * math.log(pred[0,2]) + math.log(pred[1,0]))/4 # 4 = 1+3 对应权重之和
print(loss2) # 0.8773049571540321
在这个例子中,我们创建了一个二维tensor predictions,表示模型的预测结果。每一行对应一个样本的预测结果,每个元素表示该类别的概率。我们还创建了一个一维tensor labels,表示样本的真实标签。
然后,我们定义了一个一维tensor weights,用于指定每个类别的权重。在计算交叉熵损失时,权重会被应用到每个类别上。
最后,使用F.cross_entropy函数计算了predictions和labels之间的交叉熵损失,同时考虑了类别权重。得到了一个标量tensor loss,表示模型的带权重的损失值。
通过调整权重,我们可以提高或降低某些类别对模型损失的贡献,从而影响模型的训练过程。权重的选择应根据具体问题和需求进行调整。
补充:F.binary_cross_entropy
补充:F.binary_cross_entropy_with_logits
F.binary_cross_entropy_with_logits
和 F.cross_entropy
是 PyTorch 中的两个函数,分别用于计算二分类交叉熵损失和多分类交叉熵损失。它们的主要区别在于输入张量的形状和处理方式不同。
F.binary_cross_entropy_with_logits
适用于二分类问题,其中模型的输出需要经过 sigmoid 函数将其转换为概率值,然后与真实标签进行比较。它的输入张量形状应该是
N
×
1
N \times 1
N×1 或
N
N
N,其中
N
N
N 表示样本数。F.binary_cross_entropy_with_logits
返回一个标量张量,表示预测值与真实标签之间的二分类交叉熵损失。
F.cross_entropy
适用于多分类问题,其中模型的输出已经经过 softmax 函数将其转换为概率值,然后与真实标签进行比较。它的输入张量形状应该是
N
×
C
N \times C
N×C,其中
N
N
N 表示样本数,
C
C
C 表示类别数。F.cross_entropy
返回一个标量张量,表示预测值与真实标签之间的多分类交叉熵损失。
以下是一个使用 F.binary_cross_entropy_with_logits
和 F.cross_entropy
函数的示例代码:
import torch
import torch.nn.functional as F
# 创建输入张量和真实标签张量
input_binary = torch.randn(3, 1)
target_binary = torch.tensor([1, 0, 1], dtype=torch.float32)
input_multi = torch.randn(3, 4)
target_multi = torch.tensor([2, 1, 0])
# 计算二分类交叉熵损失
loss_binary = F.binary_cross_entropy_with_logits(input_binary, target_binary)
# 计算多分类交叉熵损失
loss_multi = F.cross_entropy(input_multi, target_multi)
# 输出损失
print(loss_binary)
print(loss_multi)
在这个例子中,我们创建了一个形状为
3
×
1
3 \times 1
3×1 的输入张量 input_binary
和一个形状为
3
3
3 的真实标签张量 target_binary
,以及一个形状为
3
×
4
3 \times 4
3×4 的输入张量 input_multi
和一个形状为
3
3
3 的真实标签张量 target_multi
。然后,我们分别使用 F.binary_cross_entropy_with_logits
和 F.cross_entropy
函数计算了二分类交叉熵损失和多分类交叉熵损失,并将结果保存在 loss_binary
和 loss_multi
变量中。最后,我们输出了这些损失。
补充2:交叉熵通俗理解
交叉熵损失函数(Cross-Entropy Loss)是一种常用的损失函数,主要用于衡量分类问题中模型预测结果与真实标签之间的差异。
为了理解交叉熵损失函数,我们可以从两个方面进行解释:
-
信息论解释:交叉熵损失函数可以被看作是真实标签的信息量在模型预测概率分布上的平均值。信息论中的熵(Entropy)是衡量一个随机变量的不确定性的度量,而交叉熵则是真实分布与预测分布之间的差异。当预测分布与真实分布越接近时,交叉熵的值越小,表示模型的预测结果越准确。
-
最大似然估计解释:交叉熵损失函数可以被看作是最大似然估计的负对数似然。最大似然估计是一种统计方法,用于根据观测数据来估计概率分布的参数。交叉熵损失函数在分类问题中,将真实标签视为观测数据,并通过最小化交叉熵来寻找最适合的模型参数,使得模型能够最大程度地拟合真实标签的分布。
简而言之,交叉熵损失函数可以衡量模型预测结果与真实标签之间的差异,并通过最小化交叉熵来寻找最优的模型参数。当模型的预测结果与真实标签越接近时,交叉熵的值越小,表示模型的预测越准确。交叉熵损失函数在分类问题中被广泛使用,并被证明是一种有效的优化目标。