PyTorch 损失函数中目标和预测张量的形状

Shape of target and predictions tensors in PyTorch loss functions

我对 nn.CrossEntropyLoss 中张量的输入形状感到困惑。 我正在尝试为文本序列实现一个简单的自动编码器。我的问题的核心可以用下面的代码来说明

predictions = torch.rand(2, 3, 4)
target = torch.rand(2, 3)
print(predictions.shape)
print(target.shape)
nn.CrossEntropyLoss(predictions.transpose(1, 2), target)

在我的例子中,预测的形状为 (time_step, batch_size, vocabulary_size),而目标的形状为 (time_step, batch_size)。接下来,我根据 description 转置预测,在我的例子中,预测的第二个维度应该是 类 - vocabulary_size 的数量。代码 returns 错误 RuntimeError: bool value of Tensor with more than one value is ambiguous。有人可以告诉我如何使用该死的东西吗?提前致谢!

您不是在调用损失函数,而是在构建它。 nn.CrossEntropyLoss构造函数的签名是:

nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')

您将预测设置为 weight,将目标设置为 size_average, 其中 weight 是 classes 的可选重新缩放,size_average 已弃用,但需要一个布尔值。目标是大小为 [2, 3] 的张量,无法转换为布尔值。

您需要先创建损失函数,因为您没有使用构造函数的任何可选参数,所以您没有指定任何参数。

# Create the loss function
cross_entropy = nn.CrossEntropyLoss()

# Call it to calculate the loss for your data
loss = cross_entropy(predictions.transpose(1, 2), target)

或者直接使用功能版nn.functional.cross_entropy:

import torch.nn.functional as F

loss = F.cross_entropy(predictions.transpose(1, 2), target)

class版本的优势,与功能版本相比,您只需指定一次额外的参数(例如weight),而不必手动提供它们每次。

关于张量的维度,批量大小必须是第一维度,因为损失是批量中每个元素的平均,所以你有大小为 [[=47= 的损失张量]]。如果你使用 reduction="none",你会得到批处理中每个元素的这些损失,但默认情况下 (reduction="mean") 返回这些损失的平均值。如果跨时间步而不是批次取平均值,结果会有所不同。

最后,目标必须是 class 索引,这意味着它们需要具有类型 torch.long 而不是 torch.float。在这个随机选择的示例中,您可以使用 torch.randint.

创建随机 classes
predictions = torch.rand(2, 3, 4)
target = torch.randint(4, (2, 3))

# Reorder the dimensions
# From: [time_step, batch_size, vocabulary_size]
# To: [batch_size, vocabulary_size, time_step]
predictions = predictions.permute(1, 2, 0)
# From: [time_step, batch_size]
# To: [batch_size, time_step]
target = target.transpose(0, 1)

F.cross_entropy(predictions, target)